Почему я получаю двойной выход из трубы? - PullRequest
1 голос
/ 01 мая 2020

Я пытаюсь прочитать из канала один раз и распечатать результаты, но я получаю двойной вывод.

Я думал, что размеры чтения и записи были неправильными ( Почему вывод печатается дважды с помощью write (), а не с print () в IP C с использованием 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

РЕДАКТИРОВАТЬ: Добавлен полный код

Ответы [ 2 ]

2 голосов
/ 01 мая 2020

l oop, который печатает ваш вывод

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

Идет от j = 0 вместо j = 1. argc равно 2. Таким образом, выводится дважды.

1 голос
/ 01 мая 2020

Сочетание двух проблем: во-первых, for(int i = 1; i < argc; ++i) будет выполняться argc - 1 раза, но for(int j = 0; j < argc; ++j) будет выполняться argc раза. Во-вторых, if(read(pd[0], &fileAtr, (32*sizeof(int))) == -1) обрабатывает только одну вещь, которую read может сделать. Помимо сбоя с -1, он также может возвращать 0, когда достигает EOF, или возвращать несколько байтов, но меньше, чем вы просили (это называется частичным чтением). В вашем случае EOF происходит, но ваш код этого не замечает, поэтому он просто с радостью согласуется с данными, которые уже были там (в данном случае дубликат окончательного результата).

...