Unix管道正在输入但不显示输出

时间:2017-07-20 03:57:25

标签: c pipe

我正在尝试为C程序创建一个管道,该程序接受pre.c并使用子进程处理它并接受sort.c并将其作为父进程处理。当我执行管道可执行文件时,系统会提示我输入必要的输入,但是当我按住ctrl-d时没有显示输出。当我运行./pre | ./sort更多相同 - 没有输出。当我单独运行这些单独的可执行文件时,它们似乎工作正常。有什么想法阻止输出正确处理?

pre.c:

#include <stdio.h>

typedef struct{
   char  name[4];
   int   population;
} State;

enum { MAX_STATES = 10 };

int main()
{
    State myStates[MAX_STATES];

    int i, j;

    // Function to read in multiple lines (up to 10) of user input; loop 
    // controls in place, detects format problems, prevents string buffer 
    // overflows.
    for (i = 0; i < MAX_STATES; i++)
    {
        if (scanf("%2s %d\n", myStates[i].name, &myStates[i].population) != 2)
            break;
    }

    printf("\n");

    // Function to output (stdout) array of State structs that exceed 10 
    // population. 
    for(j = 0; j < i; j++)
        {
            if(myStates[j].population >= 10)
            {
                printf("%s %d\n", myStates[j].name, myStates[j].population);
            }
        }

    return 0;
}

sort.c:

#include <stdio.h>
#include <string.h>

typedef struct{
   char  name[3];
   int   population;
} State;

enum { MAX_STATES = 10 };

int main()
{
    State myStates[MAX_STATES];

    int i, 
        j,
        k, 
        count = 0;

    char temp[3];

    while( scanf("%s%d", myStates[i].name, &myStates[i].population)!= EOF)
        i++;

    count = i;

    // for(i = 0; i < MAX_STATES; i++)
    // {
    //     if (scanf("%2s %d\n", myStates[i].name, &myStates[i].population) != 2)
    //         break;
    //     count++;
    // }

    printf("\n");

    // Function to sort necessary input 
    for(j = 0; j < (count-1); j++)
        {
            strcpy(temp, myStates[j].name);
            for(k = j + 1; k < count; k++)
            {
                if(strcmp(myStates[j].name, myStates[k].name) > 0)
                {
                    strcpy(myStates[j].name, myStates[k].name);
                    strcpy(myStates[k].name, temp);
                }
            }
        }

     for( i=0; i < count; i++)
     {
        printf("%s\n", myStates[i].name);
     }

    return 0;
}

pipe.c:

#include <stdio.h>

int main()
{
    int pid;
    int fd[2];
    pid = pipe(fd);
    fork();

    if(pid < 0) // error case
        printf("could not create pipe\n");
    else if(pid == 0)
    {
        // Child Process
        close(1);
        dup(fd[1]);
        close(fd[0]);
        close(fd[1]);
        execvp("./pre", 0);
    }
    else
    {
        // Parent Process
        close(0);
        dup(fd[0]);
        close(fd[0]);
        close(fd[1]);
        execvp("./sort", 0);
    }

    return 0;
}

输入:

$ ./pipe
TX 32
RI 3
CA 53

输出:

1 个答案:

答案 0 :(得分:2)

固定代码 - 但sort.c现在使用的是qsort(),而不是您的家庭冲泡排序,这对我来说不适用于更大的数据集。

程序在运行macOS Sierra 10.12.6的Mac上使用GCC 7.1.0和命令行干净地编译:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
>     pre.c -o pre
$

进行这项工作需要进行大量的小改动 - 删除变量,添加标题等等。

pipe.c中的一项主要变化是从pid而不是fork()抓取pipe()

pre.c

#include <stdio.h>

typedef struct
{
    char name[3];
    int population;
} State;

enum { MAX_STATES = 10 };

int main(void)
{
    State myStates[MAX_STATES];

    int i, j;

    for (i = 0; i < MAX_STATES; i++)
    {
        if (scanf("%2s %d\n", myStates[i].name, &myStates[i].population) != 2)
            break;
    }

    for (j = 0; j < i; j++)
    {
        if (myStates[j].population >= 10)
        {
            printf("%s %d\n", myStates[j].name, myStates[j].population);
        }
    }

    return 0;
}

sort.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct
{
    char name[3];
    int population;
} State;

static int cmp(const void *v1, const void *v2)
{
    const State *s1 = (State *)v1;
    const State *s2 = (State *)v2;
    return strcmp(s1->name, s2->name);
}

enum { MAX_STATES = 10 };

int main(void)
{
    State myStates[MAX_STATES];

    int count = 0;

    for (int i = 0; i < MAX_STATES; i++)
    {
        if (scanf("%s %d", myStates[i].name, &myStates[i].population) != 2)
            break;
        count++;
    }

    qsort(myStates, count, sizeof(myStates[0]), cmp);

    for (int i = 0; i < count; i++)
    {
        printf("%s\n", myStates[i].name);
    }

    return 0;
}

pipe.c

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    int fd[2];
    if (pipe(fd) != 0)
    {
        fprintf(stderr, "could not create pipe\n");
        return(1);
    }

    int pid = fork();
    if (pid < 0)
    {
        fprintf(stderr, "could not fork\n");
        return(1);
    }
    else if (pid == 0)
    {
        close(1);
        if (dup(fd[1]) != 1)
            return(1);
        close(fd[0]);
        close(fd[1]);
        char *arg1[] = { "./pre", 0 };
        execv(arg1[0], arg1);
        fprintf(stderr, "failed to execute %s\n", arg1[0]);
        return(1);
    }
    else
    {
        close(0);
        if (dup(fd[0]) != 0)
            return(1);
        close(fd[0]);
        close(fd[1]);
        char *arg2[] = { "./sort", 0 };
        execv(arg2[0], arg2);
        fprintf(stderr, "failed to execute %s\n", arg2[0]);
        return(1);
    }

    return 0;
}

样本数据

CA 39250017
TX 27862596
FL 20612439
NY 19745289
IL 12801539
PA 12784227
OH 11646273
GA 10310371
NC 10146768
MI 9928301

(人口数据来自Wikipedia。)

./pre < states

的输出
CA 39250017
TX 27862596
FL 20612439
NY 19745289
IL 12801539
PA 12784227
OH 11646273
GA 10310371
NC 10146768
MI 9928301

./pre < states | ./sort

的输出
CA
FL
GA
IL
MI
NC
NY
OH
PA
TX

./pipe < states

的输出
CA
FL
GA
IL
MI
NC
NY
OH
PA
TX