如何将C中管道的信息输出到文件?

发布于 2024-08-22 04:09:45 字数 2040 浏览 6 评论 0原文

当我执行第二个程序后尝试输出到文件时,我对自己做错了什么感到困惑。

假设我的输入文件具有以下名称:

马蒂·B·海滩 7 8
扎卡里湾惠特克 12 23
伊万·桑切斯 02 15
吉姆·图隆加纳姆 9 03

我的程序完成后,它将把学生的名字转换为用户名,并将其输出到一个文件中,如下所示:

mbb0708
zbw1223
是0215
jt0903

目前,就我的程序而言,它没有向文件输出任何内容,并且终端似乎处于无限循环中,尽管之前自我测试了我的转换器程序并确保它将名称正确输出到标准输出。

我不确定我在这里做错了什么?第一次用管道编程。我知道必须使用读取和写入命令提取数据,但是使用 dup2 命令是否需要单独读取命令?

管理器.c

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

int main(int argc, char** argv)
{
    pid_t pid;

    int nbytes;

    /*Buffer to hold data from pipe*/
    char buffer[BUFSIZ + 1];

    /*Pipe Information*/
    int commpipe[2];
    if(pipe(commpipe))
    {
        fprintf(stderr, "Pipe failed.\n");
        return EXIT_FAILURE;
    }

    if((pid = fork()) == -1)
    {
        fprintf(stderr,"Fork error. Exiting.\n"); 
        exit(1);
    }
    else if(pid == 0)
    {
        /*This is the child process. Close our copy of the write end of the file descriptor.*/
        close(commpipe[1]);
        /* Connect the read end of the pipe to standard input*/
        dup2(commpipe[0], STDIN_FILENO);
        /*Program will convert the Student's name to their respective names*/
        execl("converter","converter",NULL);
        /*Exit if failure appears*/
        exit(EXIT_FAILURE);
    }
    else
    {
        FILE *file;
        file = fopen("usernames.txt","a+"); //append a file(add text to a file or create a file it does not exist)
        /*Close or copy of the read end of the file descriptor */
        //close(commpipe[1]);

        nbytes = write(commpipe[1], buffer, BUFSIZ);

        //Read from pipe here first? 

        //Output to usernames.txt the usernames of the user from the pipe.
        fprintf(file, "%s", buffer);

        /*Wait for the child process to finish*/
        waitpid(pid, NULL, 0);
    }

    return 0;
}

I'm confused about what I'm doing wrong when I'm attempting to output to a file after I've execed a second program.

Say I have input file that has the following names:

Marty B. Beach 7 8
zachary b. Whitaker 12 23
Ivan sanchez 02 15
Jim Toolonganame 9 03

After my programs finish, it will convert the student's names to their usernames and output it to a file such as this:

mbb0708
zbw1223
is0215
jt0903

Currently as my program stands, it outputs nothing to the file and the terminal seems to be in an infinite loop despite self testing my converter program before and making sure it outputs names correctly to stdout.

I'm not sure what I'm doing wrong here? First time programming with pipes. I know have to make use of the read and write commands extract the data, but with the dup2 command is that necessary for the read command alone?

manager.c

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

int main(int argc, char** argv)
{
    pid_t pid;

    int nbytes;

    /*Buffer to hold data from pipe*/
    char buffer[BUFSIZ + 1];

    /*Pipe Information*/
    int commpipe[2];
    if(pipe(commpipe))
    {
        fprintf(stderr, "Pipe failed.\n");
        return EXIT_FAILURE;
    }

    if((pid = fork()) == -1)
    {
        fprintf(stderr,"Fork error. Exiting.\n"); 
        exit(1);
    }
    else if(pid == 0)
    {
        /*This is the child process. Close our copy of the write end of the file descriptor.*/
        close(commpipe[1]);
        /* Connect the read end of the pipe to standard input*/
        dup2(commpipe[0], STDIN_FILENO);
        /*Program will convert the Student's name to their respective names*/
        execl("converter","converter",NULL);
        /*Exit if failure appears*/
        exit(EXIT_FAILURE);
    }
    else
    {
        FILE *file;
        file = fopen("usernames.txt","a+"); //append a file(add text to a file or create a file it does not exist)
        /*Close or copy of the read end of the file descriptor */
        //close(commpipe[1]);

        nbytes = write(commpipe[1], buffer, BUFSIZ);

        //Read from pipe here first? 

        //Output to usernames.txt the usernames of the user from the pipe.
        fprintf(file, "%s", buffer);

        /*Wait for the child process to finish*/
        waitpid(pid, NULL, 0);
    }

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏花。依旧 2024-08-29 04:09:45

一个问题是,管理器将所有数据发送到转换器后,管理器没有关闭 commpipe[1]。因此,转换器永远不会在 stdin 上得到 EOF,因此不会退出。

由于缓冲,管理器很可能无法从转换器返回任何数据。当不写入终端时,stdio 的某些实现使用全缓冲区缓冲(而不是行缓冲)。一旦修复了之前的错误并关闭了进程,就会刷新标准输出。您还可以考虑在 put 行之后添加 fflush(stdout) 。

One problem is that after manager has sent all the data to converter, the manager is not closing commpipe[1]. Because of that, converter will never get EOF on stdin so will not exit.

Most likely manager isn't getting any data back from converter due to buffering. Some implementations of stdio use full-buffer buffering (as opposed to line-buffering) when not writing to a terminal. Once you fix the previous error and get the process to close, that will flush stdout. You can also consider adding fflush(stdout) after your puts line.

一百个冬季 2024-08-29 04:09:45

看看 OpenGroup 网站,有一个看起来类似的示例给你的。我建议您首先使用一些硬编码来使示例正常工作。一旦工作正常,添加代码来读取和写入结果。

我做了一些小的更改以使示例正常工作:

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

int main(int argc, char** argv){
   int fildes[2];
   const int BSIZE = 100;
   char buf[BSIZE];
   ssize_t nbytes;
   int status;


   status = pipe(fildes);
   if (status == -1 ) {
       /* an error occurred */
       printf("Error!\n");
       exit(-1);
   }

   printf("Forking!\n");
   switch (fork()) {
   case -1: /* Handle error */
       printf("Broken Handle :(\n");
       break;


   case 0:  /* Child - reads from pipe */
       printf("Child!\n");
       close(fildes[1]);                       /* Write end is unused */
       nbytes = read(fildes[0], buf, BSIZE);   /* Get data from pipe */
       /* At this point, a further read would see end of file ... */
       assert(nbytes < BSIZE);                 /* Prevent buffer overflow */
       buf[nbytes] = '\0';                     /* buf won't be NUL terminated */
       printf("Child received %s", buf);
       close(fildes[0]);                       /* Finished with pipe */
       fflush(stdout);
       exit(EXIT_SUCCESS);


   default:  /* Parent - writes to pipe */
       printf("Parent!\n");
       close(fildes[0]);                       /* Read end is unused */
       write(fildes[1], "Hello world\n", 12);  /* Write data on pipe */
       close(fildes[1]);                       /* Child will see EOF */
       /* Note that the Parent should wait for a response from the
       child here, because the child process will be terminated once
       the parent exits */
       exit(EXIT_SUCCESS);
   }

   return 0;
}

Have a look at the OpenGroup site, there's an example that looks similar to yours. I suggest you get the sample working first with some hard coded. Once that is working, add the code to read and write the results.

I made some minor changes to get the example working:

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

int main(int argc, char** argv){
   int fildes[2];
   const int BSIZE = 100;
   char buf[BSIZE];
   ssize_t nbytes;
   int status;


   status = pipe(fildes);
   if (status == -1 ) {
       /* an error occurred */
       printf("Error!\n");
       exit(-1);
   }

   printf("Forking!\n");
   switch (fork()) {
   case -1: /* Handle error */
       printf("Broken Handle :(\n");
       break;


   case 0:  /* Child - reads from pipe */
       printf("Child!\n");
       close(fildes[1]);                       /* Write end is unused */
       nbytes = read(fildes[0], buf, BSIZE);   /* Get data from pipe */
       /* At this point, a further read would see end of file ... */
       assert(nbytes < BSIZE);                 /* Prevent buffer overflow */
       buf[nbytes] = '\0';                     /* buf won't be NUL terminated */
       printf("Child received %s", buf);
       close(fildes[0]);                       /* Finished with pipe */
       fflush(stdout);
       exit(EXIT_SUCCESS);


   default:  /* Parent - writes to pipe */
       printf("Parent!\n");
       close(fildes[0]);                       /* Read end is unused */
       write(fildes[1], "Hello world\n", 12);  /* Write data on pipe */
       close(fildes[1]);                       /* Child will see EOF */
       /* Note that the Parent should wait for a response from the
       child here, because the child process will be terminated once
       the parent exits */
       exit(EXIT_SUCCESS);
   }

   return 0;
}
灼痛 2024-08-29 04:09:45

据我了解,您的转换器程序从标准输入读取行并将其写入标准输出。由于管道是单向实体,因此您将需要其中两个与管理器通信 - 一个将数据发送到转换器,另一个从转换器接收输出。

也许您应该考虑增强转换器以采用(作为可选参数)输入和输出文件的名称。

As I understand, your converter program reads lines from stdin and writes them to stdout. As a pipe is a uni-directional entity, you will need TWO of them to communicate with the manager - one to send data to the converter and one to receive output from it.

Maybe you should consider enhancing the converter to take (as optional arguments) the name of an input and output file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文