使用管道用C读取字符串数组

时间:2014-09-24 06:04:52

标签: c pipe

我现在正在学习如何使用带有C的管道,并且我很难将一个字符串列表逐个写入子进程中的管道,然后从父管道中读取它们处理。这是我目前的代码:

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

int main()
{
    int pfd[2];
    char buf[1000];
    int cfork;

    if (pipe(pfd) == -1) {
        exit(1);
    }

    cfork = fork();

    if (cfork == -1) {
        printf("Fork Failed\n");
        exit(1);
    }
    else if (cfork == 0) {
        printf("Child Process\n");

        char *fruit[] = {
            "Orange", "Apple",
            "Banana", "Pear"
        };

        int num_fruit = 4;
        for (int i = 0; i < num_fruit; i++) {
            printf("Current fruit: %s\n", fruit[i]);
            write(pfd[1], fruit[i], (strlen(fruit[i])));
        }
        _exit(0);
    }
    else {
        printf("Parent Process\n");
        read(pfd[0], buf, sizeof(buf));
        printf("Fruit Fetched: %s\n", buf);
        wait(NULL);
    }

    return 0;

}

我想要做的是,在孩子身上,读取水果字符串,将其写入管道,让父母读取该字符串并打印它,直到所有字符串都被打印出来。我的麻烦是,孩子,因为它在一个循环中,只是不断地将每个字符串添加到缓冲区,所以程序,如它所示,打印出&#34; OrangeAppleBanana&#34;。我很确定我在父母中也需要一个循环,但是当我尝试了一个while循环来等待孩子发送的某些结束条件字符串时(例如&#34; done&#34;),我的程序仍然陷入无限循环。

对于C新手来说,在孩子中逐个编写字符串并让父进程逐个打印出来的最直接的方法是什么?

修改

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

int main()
{
    int pfd[2];
    int cfork;

    if (pipe(pfd) == -1) {
        exit(1);
    }

    cfork = fork();

    if (cfork == -1) {
        printf("Fork Failed\n");
        exit(1);
    }
    else if (cfork == 0) {

        int numbers[] = {
            1, 2,
            3, 4
        };

        int limit = 4;
        close(pfd[0]);
        for (int i = 0; i < limit; i++) {
            printf("Child - Current Number: %d\n", numbers[i]);
            write(pfd[1], &numbers[i], sizeof(numbers[i]));
        }
        close(pfd[1]);
        _exit(0);
    }
    else {

        int temp;
        int reads = 4;
        close(pfd[1]);
        for (int i = 0; i < reads; i++) {
            read(pfd[0], &temp, sizeof(temp));
            printf("Parent - Number Fetched: %d\n", temp);
        }
        close(pfd[0]);
        waitpid(-1, NULL, 0);
    }

    return 0;

这是我的新代码,我使用整数而不是字符串。到目前为止似乎工作。仍然不确定我在字符串上做错了什么。

2 个答案:

答案 0 :(得分:1)

我相信你的问题是“字符串”。 C中的字符串以空值终止,因此当您通过管道发送它们时,接收方(父级)不知道字符串的结束位置。 Strlen确实计算字符串中的字符数,但不计算null charatter。你应该这样做:

 write(pfd[1], fruit[i], (strlen(fruit[i]))+1);

家长现在可以知道拆分字符串的时间和地点。

另一个问题是你需要在parrent中循环。您需要在循环中设置一个条件,以检查EOF。在你的例子中,你知道你将获得4个水果,你可以循环4次。

关闭不需要的管道读写结束是一种很好的做法。在您的示例中,child应该关闭读取结束,而parent应该关闭写入结束。你可以这样做:

close(pfd[0]);  //use this in child

close(pfd[1]);   //use this in parent

您还应该习惯关闭所有不需要的描述符。在您的示例中,您应该在完成写入/读取后关闭子进程和父进程中的管道。这样,您可以创建一个读取循环条件,该条件在EOF之后关闭。 (当孩子关闭管道时,接收器可以结束)

作为额外提示,请尝试使用“perror”进行错误报告 http://www.tutorialspoint.com/c_standard_library/c_function_perror.htm

答案 1 :(得分:0)

//Child
close(pfd[0]); // Close read end this blocks if parent is reading from pipe
write(pfd[1]...); // write data into pipe
close(pfd[1]); // close write end of pipe now the pipe is ready to read

// Parent
close(pfd[1]); // close write end of pipe blocks if child is writing to pipe.
read(pfd[0] ...);
close(pfd[0]..); // close read end so pipe is ready to write to.