【问题标题】:Why do I get double output from pipe?为什么我从管道得到双输出?
【发布时间】:2020-04-30 21:23:06
【问题描述】:

我试图从管道中读取一次并打印出结果,但我得到了双重输出。

我认为读取和写入大小不正确(Why is the output printed twice with write() and not with print() in IPC using pipe?),但我在写入之前打印出子级的大小,然后尝试将相同的大小输入到读取函数中,我仍然得到双输出。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

typedef struct
{
    int PID;
    char *filename;
    int wordCount;
    int lineCount;
    int byteCount;

} filestr;

int pipe(int pd[2]);
void mywc(FILE *fp, char *name, filestr *fileA);
int isParam(char* fileName);
int getParam(int argCount, char **args);
void error_exit(char *s);

int main(int argc, char *argv[])
{
    int pd[2], status, pid, param, 
    wordT=0, lineT=0, byteT=0;
    filestr fileAtr;


    //param = getParam(argc, argv);
    //printf("PARAM: %d\n", param);

    if(pipe(pd) == -1)
        error_exit("pipe() failed");

    for(int i = 1; i < argc; ++i)
    {
        pid = fork();

        if(pid == -1)
        {
            perror("fork");
            exit(1);
        }

        else if(pid == 0)
        {
            FILE *file = fopen(argv[i], "r");
            if(file != 0){
                mywc(file, argv[i], &fileAtr);

                wait(NULL);
                close(pd[0]);

                printf("SIZE: %d\n", sizeof(fileAtr));
                if(write(pd[1], &fileAtr, sizeof(fileAtr)) == -1)
                    error_exit("write() failed");   
            }




            exit(0);
        }
    }

    int sum;
    for(int j = 0; j < argc; ++j)
    {
        close(pd[1]);

        if(read(pd[0], &fileAtr, (32*sizeof(int))) == -1)
            error_exit("read() failed");
        printf("PID : %d\n", fileAtr.PID);
        printf("File Name : %s\n", fileAtr.filename);
        printf("Words : %d\n", fileAtr.wordCount);
        printf("Lines : %d\n", fileAtr.lineCount);
        printf("Bytes : %d\n\n", fileAtr.byteCount);    

        wordT += fileAtr.wordCount;
        lineT += fileAtr.lineCount;
        byteT += fileAtr.byteCount;
    }
    printf("Grand Total: word: %d line: %d byte: %d\n", wordT, lineT, byteT);

}

void mywc(FILE *fp, char *name, filestr *fileA)
{
    int c, lineCount=0, wordCount=0, byteCount=0;

    while( (c = getc(fp)) != EOF )
    {

        if( c == ' ' )
        {
            wordCount++;
            byteCount++;
        }
        else if ( c == '\n')
        {
            wordCount++;
            byteCount++;
            lineCount++;
        }
        else
        {
            byteCount++;
        }
    }

    fileA->PID = getpid();
    fileA->filename = name;
    fileA->wordCount = wordCount;
    fileA->lineCount = lineCount;
    fileA->byteCount = byteCount;
}

int getParam(int argCount, char **args)
{
    int param;
    for(int i = 0; i < argCount; i++)
    {
        if((strcmp(args[i], "-lwc") == 0) || (strcmp(args[i], "-lcw") == 0) || (strcmp(args[i], "-wlc") == 0) 
            || (strcmp(args[i], "-wcl") == 0) || (strcmp(args[i], "-cwl") == 0) || (strcmp(args[i], "-clw") == 0))
            param = 3;
        else if((strcmp(args[i], "-w") == 0))
            param = 0;
        else if((strcmp(args[i], "-l") == 0))
            param = 1;
        else if((strcmp(args[i], "-c") == 0))
            param = 2;
    }
    return param;
}

void error_exit(char *s)
{
    fprintf(stderr, "\nError: %s\n", s);
    exit(1);
}

我的输出:


SIZE: 32
PID : 14896
File Name : test
Words : 4
Lines : 4
Bytes : 26

PID : 14896
File Name : test
Words : 4
Lines : 4
Bytes : 26

Grand Total: word: 8 line: 8 byte: 52

编辑:添加完整代码

【问题讨论】:

  • 你需要产生一个可重现的例子,包括你所有的#includes和mywc的定义。
  • 请注意,您的j 循环比i 循环多运行一次。
  • @dxiv 我不敢相信……这就是问题所在。谢谢。
  • @dshin 你没有。您永远不会因为找到答案而删除问题。
  • @dshin 很高兴它有帮助。但是,如果您阅读其他 cmets,那只是 一个 问题。附言如果每个人都删除了他们已解决的问题,就没有 SO。不要。

标签: c linux pipe fork


【解决方案1】:

打印输出的循环

for(int j = 0; j < argc; ++j)
{
    ...
}

j = 0 而不是j = 1argc 是 2。所以它打印输出两次。

【讨论】:

    【解决方案2】:

    两个问题的组合:首先,for(int i = 1; i &lt; argc; ++i) 将运行 argc - 1 次,但 for(int j = 0; j &lt; argc; ++j) 将运行 argc 次。其次,if(read(pd[0], &amp;fileAtr, (32*sizeof(int))) == -1) 只处理read 可以做的一件事。除了使用-1 失败之外,它还可以在到达EOF 时返回0,或者返回一些字节,但比您要求的要少(称为部分读取)。在您的情况下,EOF 正在发生,但您的代码没有注意到,所以它只是很高兴地与碰巧已经存在的数据一起出现(在这种情况下,是最终结果的副本)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-24
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-16
      相关资源
      最近更新 更多