当前位置: 技术问答>linux和unix
to:wwwunix : 这个问题该解决那?非常感谢!!!
来源: 互联网 发布时间:2016-04-25
本文导语: 我便写的一个bc计算器 这个程序有bug,当两个操作数的结果大于4096个字节时,一次打印不出全部结果,管道此时阻塞,下一次再执行计算的时候不能得出正确结果。 所以我在程序上加入了一个while语句,希望把管道...
我便写的一个bc计算器
这个程序有bug,当两个操作数的结果大于4096个字节时,一次打印不出全部结果,管道此时阻塞,下一次再执行计算的时候不能得出正确结果。
所以我在程序上加入了一个while语句,希望把管道的内容全部打印出来,但是发现程序跳不出来了,不能再次计算了,请问这是什么原因。(while语句见我的注视。
#include
#include
#define oops(m,x) {perror(m); exit(x);}
main()
{
int pid,todc[2],fromdc[2];
//make two pipes
if(pipe(todc)==-1||pipe(fromdc)==-1)
oops("get pipe failed.",1);
//get a process for user interface
if((pid=fork())==-1)
oops("fork failed ",2);
if(pid==0) //child is dc
be_dc(todc,fromdc);
else{ //parent is ui
be_bc(todc,fromdc);
wait(NULL); //wait for child
}
}
void be_dc(int in[2],int out[2])
{
close(in[1]);
close(out[0]);
if(dup2(in[0],0)==-1) //copy read end to 0
oops("dc:cannot redirect stdin ",3);
close(in[0]); //moved to fd 0
if(dup2(out[1],1)==-1) //dupe write end to 1
oops("dc:cannot redirect stdout",4);
close(out[1]); //moved to 1
execlp("dc","dc","-",NULL);
oops("cannot run dc",5);
}
void be_bc(int todc[2],int fromdc[2])
//从stdin读,然后转换成RPN,传送给pipe,然后
//从其他管道读入,并打印出
{
int num1,num2;
char operation[BUFSIZ],*fgets();
char message[BUFSIZ];
FILE *fpout ,*fpin;
int n_read;
close(todc[0]);
close(fromdc[1]);
fpout=fdopen(todc[1],"w");
fpin=fdopen(fromdc[0],"r");
if(fpout==NULL||fpin==NULL)
fatal("Error convering pipes to streams");
//main loop
while(printf("tinybc:"),fgets(message,BUFSIZ,stdin)!=NULL)
{
if(sscanf(message,"%d%[+-*/^]%d",&num1,operation,&num2)!=3)
{printf("syntax errorn");
continue;
}
if(fprintf(fpout,"%dn%dn%cnpn",num1,num2,*operation)==EOF)
fatal("Error writing");
fflush(fpout);
if(fgets(message,BUFSIZ,fpin)==NULL)
break;
printf("%d%c%d=%s",num1,*operation,num2,message);
/*
这里有个小 bug,当我的执行完一个运算的时候,不能跳出继续另一个运算,这是怎么回事阿?
我觉得问题就在这个while语句中。请高人指点。。。
*/
while(fgets(message,BUFSIZ,fpin)!=NULL)
{
printf("%s",message);
}
}
fclose(fpout);
fclose(fpin);
}
fatal(char *mess[])
{
fprintf(stderr,"Error :%sn",mess);
exit(1);
}
这个程序有bug,当两个操作数的结果大于4096个字节时,一次打印不出全部结果,管道此时阻塞,下一次再执行计算的时候不能得出正确结果。
所以我在程序上加入了一个while语句,希望把管道的内容全部打印出来,但是发现程序跳不出来了,不能再次计算了,请问这是什么原因。(while语句见我的注视。
#include
#include
#define oops(m,x) {perror(m); exit(x);}
main()
{
int pid,todc[2],fromdc[2];
//make two pipes
if(pipe(todc)==-1||pipe(fromdc)==-1)
oops("get pipe failed.",1);
//get a process for user interface
if((pid=fork())==-1)
oops("fork failed ",2);
if(pid==0) //child is dc
be_dc(todc,fromdc);
else{ //parent is ui
be_bc(todc,fromdc);
wait(NULL); //wait for child
}
}
void be_dc(int in[2],int out[2])
{
close(in[1]);
close(out[0]);
if(dup2(in[0],0)==-1) //copy read end to 0
oops("dc:cannot redirect stdin ",3);
close(in[0]); //moved to fd 0
if(dup2(out[1],1)==-1) //dupe write end to 1
oops("dc:cannot redirect stdout",4);
close(out[1]); //moved to 1
execlp("dc","dc","-",NULL);
oops("cannot run dc",5);
}
void be_bc(int todc[2],int fromdc[2])
//从stdin读,然后转换成RPN,传送给pipe,然后
//从其他管道读入,并打印出
{
int num1,num2;
char operation[BUFSIZ],*fgets();
char message[BUFSIZ];
FILE *fpout ,*fpin;
int n_read;
close(todc[0]);
close(fromdc[1]);
fpout=fdopen(todc[1],"w");
fpin=fdopen(fromdc[0],"r");
if(fpout==NULL||fpin==NULL)
fatal("Error convering pipes to streams");
//main loop
while(printf("tinybc:"),fgets(message,BUFSIZ,stdin)!=NULL)
{
if(sscanf(message,"%d%[+-*/^]%d",&num1,operation,&num2)!=3)
{printf("syntax errorn");
continue;
}
if(fprintf(fpout,"%dn%dn%cnpn",num1,num2,*operation)==EOF)
fatal("Error writing");
fflush(fpout);
if(fgets(message,BUFSIZ,fpin)==NULL)
break;
printf("%d%c%d=%s",num1,*operation,num2,message);
/*
这里有个小 bug,当我的执行完一个运算的时候,不能跳出继续另一个运算,这是怎么回事阿?
我觉得问题就在这个while语句中。请高人指点。。。
*/
while(fgets(message,BUFSIZ,fpin)!=NULL)
{
printf("%s",message);
}
}
fclose(fpout);
fclose(fpin);
}
fatal(char *mess[])
{
fprintf(stderr,"Error :%sn",mess);
exit(1);
}
|
管道有个缓存大小,你一定写超过4096的时候一次就写不全了,所以你一次读也就不能读出全部的结果了。
你循环读的时候需要判断要读多长的数据,因为管道本身的读写都没有界定数据边界的机制,你必须自己知道要读多长数据,或是根据读到的内容判断是否已经收完了本次数据。
你循环读的时候需要判断要读多长的数据,因为管道本身的读写都没有界定数据边界的机制,你必须自己知道要读多长数据,或是根据读到的内容判断是否已经收完了本次数据。