在X函数中,我使用管道来缓冲(一对printfs
,它们在X函数内部调用的Y函数中打印)stdout
流(如果有一个Fd,然后是缓冲区)完成后,关闭一个管道和其他Fd,然后在其上使用printf
。
我想完全确定缓冲区是空的,下次再次调用此X函数来执行任务时。 我尝试了一些我在网上找到的东西:
fflush
ioctl
,_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]);
}
答案 0 :(得分:1)
编辑:fflush
定位结束时的精度。
我设法使用我自己的combParenthesis
来运行你的代码(第一遍:中等字符串,第二遍:大字符串,第三小字符串)。我从未在输出中发现垃圾......只要我将printf("\n next string %s", buf);
替换为stderr
上的输出
fprintf(stderr, "\n next string %s", buf);
通过在stdin和ofp之后用一个fflush(stdout)
刷新标准输出,我也得到了正确的输出。恕我直言,问题是:
printf("\n next string %s", buf)
在stdout上写文,并且可以缓冲标准草 以下是我发现的主要改进:
combParenthesis
读取输出带有管道重复标准输出,则永远不要在任何地方写入stdout(或确保将其刷新)dup2(fds[0],STDIN_FILENO);
,因为你直接阅读了管道的另一端(这是更好的)sz = (pairs*2)+1
小于sizeof(buf)
编辑:事实上,我刚刚意识到你的代码可以工作,即使你在应用程序的其他地方混合了printf
,只要你在之前刷新stdout 将它复制到fds [1]
所以这里是X()
功能的固定版本,带有明确的编辑功能(但恕我直言,你应该考虑我的其他建议):
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]);
}
我从未在读取内容中获得垃圾,即使将输出重定向到文件也能正常工作,但由于我无法解释的原因,消息的顺序并不是我所期望的。希望你不关心