在C中,当两个管道是同一过程的一部分时,如何冲洗管道以清洁缓冲区?
在X函数中,我使用管道来缓冲在C中,当两个管道是同一过程的一部分时,如何冲洗管道以清洁缓冲区?,c,linux,pipe,flush,C,Linux,Pipe,Flush,在X函数中,我使用管道来缓冲stdout流(在X函数内部调用的Y函数中打印的两个printf),如果一个Fd,然后在缓冲完成后,关闭一个管道和另一个Fd,然后在其上使用printf 我想完全确定缓冲区是空的,下次再次调用这个X函数来执行任务时。 我在网上找到了几样东西: fflush ioctl,\u flushlbf:看起来gcc不支持它们。g++支持它吗 fseek(stdin、EOF、SEEK_END) fpurge(ofp) 我多次调用X()函数。如果下一组输出大于上一组,那么我已经编写
stdout
流(在X函数内部调用的Y函数中打印的两个printf
),如果一个Fd,然后在缓冲完成后,关闭一个管道和另一个Fd,然后在其上使用printf
我想完全确定缓冲区是空的,下次再次调用这个X函数来执行任务时。
我在网上找到了几样东西:
fflush
ioctl
,\u flushlbf
:看起来gcc不支持它们。g++支持它吗fseek(stdin、EOF、SEEK_END)代码>
fpurge(ofp)代码>
X()
函数。如果下一组输出大于上一组,那么我已经编写的当前代码可以正常工作
如果下一组输出小于当前输出。然后下一组有一些额外的垃圾值,这给了我一个指示,缓冲区可能没有完全刷新
由于某种原因,我用C编写了整个代码,但使用的是g++编译器
我的代码如下:
void X(int pairs,char* expOut)
{
char buf[256];
int fds[2];
char output[300];
char input[50];
/* opening pipes */
pipe(fds);
/* saving the the given stdout stream */
int bak = dup(STDOUT_FILENO);
/* associating Fds[1] pipe with stdout */
int res=dup2(fds[1],STDOUT_FILENO);
/* associating Fds[0] pipe with stdin */
dup2(fds[0],STDIN_FILENO);
assert(res!=-1);
/* Call To function Y: function combParenthesis is a recursive function,
which prints out some strings couple of time */
combParenthesis(pairs) ;
fflush(stdout);
/* closing stdout FD stream */
close(fds[1]);
fflush(stdout);
/* restoring the old stdout stream */
dup2(bak, 1);
close(bak);
/* opening, stdin stream for reading */
FILE *ofp = fdopen(fds[0], "r");
char strs[30][30];
for (int i=0;i<30;i++) {
memset(strs[i], 0, 30);
}
int i=0;
if (ofp)
{
int sz;
if((pairs*2)+1 <= 1)
{
sz=5;
}
else
{sz = (pairs*2)+1 ;}
/* read the stream line by line */
while (fgets(buf,sz ,ofp)) {
printf("\n next string %s", buf);
i++;
}
if (ferror(ofp)) {
printf("something went wrong in the input to printf");
}
}
/* different ways to flush it out */
char c;
while( (c = fgetc( ofp )) != EOF && c != '\n' );
fseek(stdin,EOF,SEEK_END);
fpurge(ofp);
fclose(ofp);
fflush(stdin);
// _flushlbf();
/* close the fd associated with stdin */
close(fds[0]);
}
void X(整数对,字符*expOut)
{
char-buf[256];
int-fds[2];
字符输出[300];
字符输入[50];
/*开管*/
管道(fds);
/*保存给定的标准输出流*/
int bak=dup(标准文件号);
/*将Fds[1]管道与标准输出关联*/
int res=dup2(fds[1],标准文件号);
/*将Fds[0]管道与标准DIN关联*/
dup2(fds[0],标准文件号);
断言(res!=-1);
/*对函数Y的调用:函数括号是递归函数,
几次打印出一些字符串*/
圆括号(对);
fflush(stdout);
/*关闭标准输出FD流*/
关闭(fds[1]);
fflush(stdout);
/*恢复旧的标准输出流*/
dup2(bak,1);
关闭(bak);
/*打开,标准数据流进行读取*/
文件*ofp=fdopen(fds[0],“r”);
字符strs[30][30];
对于(int i=0;iEDIT):在fflush
定位的末尾处的精度
我仅使用自己的comb括号运行了您的代码(第一遍:中等字符串,第二遍:较大字符串,第三遍较小)。我从未在输出中发现垃圾…只要我将您的printf(“\n next string%s”,buf);
替换为stderr
fprintf(stderr, "\n next string %s", buf);
我还通过一个fflush(stdout)
在stdin和of之后刷新stdout,得到了正确的输出。问题是:
- 关闭管道,使标准输出不再复制到ofp或标准输入
- 您使用
printf(“\n下一个字符串%s”,buf)”在stdout上写入
,stdout可以被缓冲
- 你冲洗干净的溪流
- 当您在下一次通话中重复stdout时,您可以阅读stdout中最后一次通话的剩余内容
以下是我发现的主要改进:
- 如果使用管道复制标准输出读取
comb括号
,切勿在任何过度位置写入标准输出(或确保刷新)
- 您需要执行一个不必要的
dup2(fds[0],STDIN_FILENO);
,因为您直接在管道的另一端读取(哪个更好)
- 您从不验证
sz=(pairs*2)+1
是否小于sizeof(buf)
编辑:事实上,我刚刚意识到,如果您在将stdout复制到fds[1]之前刷新stdout,您的代码就可以工作,即使在应用程序的其他地方使用mixedprintf
因此,这里有一个固定版本的X()
函数,其中有明确的编辑(但我想你也应该考虑我的其他建议):
void X(整数对,字符*expOut)
{
char-buf[256];
int-fds[2];
字符输出[300];
字符输入[50];
/*开始编辑*/
/*第一次冲洗标准液*/
fflush(stdout);
/*结束编辑*/
/*开管*/
管道(fds);
/*保存给定的标准输出流*/
int bak=dup(标准文件号);
/*将Fds[1]管道与标准输出关联*/
int res=dup2(fds[1],标准文件号);
/*将Fds[0]管道与标准DIN关联*/
dup2(fds[0],标准文件号);
断言(res!=-1);
/*对函数Y的调用:函数括号是递归函数,
几次打印出一些字符串*/
圆括号(对);
/*关闭标准输出FD流*/
关闭(fds[1]);
fflush(stdout);
/*恢复旧的标准输出流*/
dup2(bak,1);
关闭(bak);
/*打开,标准数据流进行读取*/
文件*ofp=fdopen(fds[0],“r”);
字符strs[30][30];
对于(int i=0;i在结尾或开头或缓冲区有额外的垃圾值,如何读取输入缓冲区?管道不知道任何记录结构等。因此,清空管道的唯一方法是在循环中一次读取一个字符,直到读取的返回状态为EOF。我尝试了字符c;而((c=fgetc(ofp))!=EOF&&c!='\n');fseek(stdin、EOF、SEEK_END);要确保读取整个缓冲区,…逐字符读取,直到file@SergeBallesta:通过“读取输入缓冲区”你是说我该如何输入缓冲区?/*对函数Y的调用:函数comb括号是一个递归函数,它会在几次打印出一些字符串*/comb括号(对);使用printf()打印出许多字符串;这会进入缓冲区。另外,如果第一次函数Y打印的字符串数量比下一次多,那么只有我面临这个问题。@user1036348否,我的意思是如何在程序中从输入自助餐中获取字符,如何读取fgets
,getc
…我需要进一步处理字符串,然后不能使用printf以外的任何其他打印方法。上面的代码消除了一些代码,以保持问题的简单性。我阅读了
void X(int pairs,char* expOut)
{
char buf[256];
int fds[2];
char output[300];
char input[50];
/* BEGIN EDIT */
/* first flush stdout */
fflush(stdout);
/* END EDIT */
/* opening pipes */
pipe(fds);
/* saving the the given stdout stream */
int bak = dup(STDOUT_FILENO);
/* associating Fds[1] pipe with stdout */
int res=dup2(fds[1],STDOUT_FILENO);
/* associating Fds[0] pipe with stdin */
dup2(fds[0],STDIN_FILENO);
assert(res!=-1);
/* Call To function Y: function combParenthesis is a recursive function,
which prints out some strings couple of time */
combParenthesis(pairs) ;
/* closing stdout FD stream */
close(fds[1]);
fflush(stdout);
/* restoring the old stdout stream */
dup2(bak, 1);
close(bak);
/* opening, stdin stream for reading */
FILE *ofp = fdopen(fds[0], "r");
char strs[30][30];
for (int i=0;i<30;i++) {
memset(strs[i], 0, 30);
}
int i=0;
if (ofp)
{
int sz;
if((pairs*2)+1 <= 1)
{
sz=5;
}
else
{sz = (pairs*2)+1 ;}
/* read the stream line by line */
// EDIT : changed sz with sizeof(buf)-1 - cause: no correct pairs value
while (fgets(buf, sizeof(buf) - 1,ofp)) {
printf("\n next string %s", buf);
i++;
}
if (ferror(ofp)) {
printf("something went wrong in the input to printf");
}
}
/* different ways to flush it out */
/* BEGIN EDIT : ALL FLUSHING COMMENTED OUT
char c;
while( (c = fgetc( ofp )) != EOF && c != '\n' );
fseek(stdin,EOF,SEEK_END);
fpurge(ofp);
fclose(ofp);
fflush(stdin);
// _flushlbf();
END EDIT */
/* close the fd associated with stdin */
close(fds[0]);
}