在C中,当两个管道是同一过程的一部分时,如何冲洗管道以清洁缓冲区?

在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()函数。如果下一组输出大于上一组,那么我已经编写

在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,您的代码就可以工作,即使在应用程序的其他地方使用mixed
    printf

    因此,这里有一个固定版本的
    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]);    
    }