Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

pipe to /bin/dc 1

Status
Not open for further replies.

iribach

Technical User
Oct 12, 2002
211
CH
hi
we found errors in our db, so i have to recompute all values in most of the tables (dumped in ascii format). the are very big >100'000 lines, every rows has >100 fields, the values are also big >10^9 and on each row are 10 arithmetic compounds to exec.

- i first try to generate an input file for /bin/bc using sed
it works fine and is ... terribly slow, unacceptable !! :(

- the same using /bin/dc
2-3 times faster, still unacceptable !!:(

- so using 'c' for and /bin/dc i get better results, takes 1h for 50k lines :(

i'm sure, a w+r pipe to /bin/dc in my c programm will make me happy
can somebody help me to do this ??

merci
iribach
 
/*
iribach: here an example.
the job is done by 'dc_start()'
i copy this code from an old (1986) sunBSD c-src, and
cannot remember the name of this really good c-programmer.
for commodity val[] & sum[] are global
*/

#define MAXval 100
#define MAXsum 1
#define MAXidc 32

/* ATTENTION the example below returns a '164' chars long number !!! */

#define MAXodc 256

char val[MAXval+1][MAXidc+1];
char sum[MAXsum+1][MAXodc+1];

void dc_form(FILE *);
int calcola(void);
int dc_start(FILE **, FILE **);

int main(int argc,char **argv)
{
....
int cnt, errors, gline;
errors = gline = 0;
/* initialize sum[] */
for(cnt = 0; MAXsum > cnt; strcpy(sum[cnt++],"0"));
/* open your ascii file and splitt it in val[] */

while(fgets(buff,sizeof(buff),fd)){
++gline;
sscanf(buff,"%s\t%s\t.......%s"
,val[0]
,...
,...
,val[MAXval]
);
if(!calcola()){
++errors;
fprintf(stderr,"%d error encontered\n",gline);
continue;
}
for(cnt = 0; MAXsum > cnt; printf("%*s\n",MAXodc,sum[cnt++]));
}
exit(errors);
}

void dc_form(FILE *fd)
{
/* write the dc formula */
/* substitue the val by your (readed) val[] */
/* fprintf(fd," 33sb\n"); becomes fprintf(fd," %ssb\n",val[xx]); */
/* also chec for NEGATIVE values */
/* use 'bc -c' to find out the reversed polish syntax */

fprintf(fd," 25k\n");
fprintf(fd," 12345.6788sa\n");
fprintf(fd," 33sb\n");
fprintf(fd,"lalb^sa\n");
fprintf(fd,"laps.\n");
fprintf(fd,"q\n");
return;
}

int calcola()
{
FILE *for_dc, *from_dc;
int pid, pos = 0;

if(0 >(pid = dc_start(&from_dc,&for_dc))) return(0);

dc_form(from_dc); fclose(from_dc);

while(fgets(sum[pos],MAXodc,for_dc)){
sum[pos][strlen(sum[pos])-1] = 0; /* cut '\n' */
++pos;
}
fclose(for_dc);
wait(&pid);
return(pos);
}

int dc_start(FILE **fwr, FILE **fre)
{
int pid, fdwrit[2], fdread[2];

if(0 >pipe(fdwrit)) goto error_aaa;
if(0 >pipe(fdread)) goto error_bbb;

switch(pid = vfork()){
case -1:
goto error_ccc;
case 0:
/* child, read from fdwrit, write to fdread */
close(0); dup(fdwrit[0]);
close(1); dup(fdread[1]);
for(pid = getdtablesize(); pid >4; close(--pid));
execl("/bin/dc","dc",NULL);
_exit(~0);
default:
/* parent, write to fdwrit, read from fdread */
*fwr = fdopen(fdwrit[1],"w"); close(fdwrit[0]);
*fre = fdopen(fdread[0],"r"); close(fdread[1]);
return(pid);
}
error_ccc:
close(fdread[0]); close(fdread[1]);
error_bbb:
close(fdwrit[0]); close(fdwrit[1]);
error_aaa:
return(-1);
}
-----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
thank you jamisar, not easy to read, it works.
50k lines in 15 minutes, very very very good.
your star.
nobody else ?
iribach
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top