【问题标题】:Simple 30 char buffer PIPE prints non printable characters, no idea why简单的 30 字符缓冲区 PIPE 打印不可打印字符,不知道为什么
【发布时间】:2012-06-08 04:03:57
【问题描述】:

我使用了一个简单的 fork() 来模拟客户端/服务器,然后使用一个非常简单的管道来发送/接收最大 30 长度的字符缓冲区,但它最终打印出不可打印的字符(小“?”和一个 4 1 和 0)之后所需的单词。

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

int main () {
    int pipefd[2];
    int cpid;
    char buf[31];
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE)
    }
    cpid = fork();
    if (cpid == -1) P
        perror("cpid");
        exit(EXIT_FAILURE);
    }
    if (cpid == 0) {      // child reads from pipe
        close (pipefd[1]); // close unused write end
        read (pipefd[0], &buf, 30); // if I use 30 instead of strlen(buf) it prints Server transmit: Server receives. It does not wait for write. Makes no sense
        printf ("Server receives: %s", buf);
        close (pipefd[0])l
        exit (EXIT_SUCCESS);
    }
    else {               // parent writes to pipe
        close (pipefd[0]); // closing unused read end;
        char buf2[30];
        printf("Server transmits: ");
        scanf ("%s", buf2);
        write (pipefd[1], buf2, strlen(buf2));
        close(pipefd[1]);
        wait(NULL);
        exit(EXIT_SUCCESS);
    }
  return 0;
}

另外,如果我写了一个以上的单词,它就会忘记第二个。在 c++ 中,我使用了 getline (cin, string) 但这不是一个选项。

还使用了read (pipefd[0], &amp;buf, sizeof(buf));,现在它以正确的顺序打印(不知道为什么 strlen 不起作用)但最后我仍然得到不可打印的字符。

【问题讨论】:

    标签: c fork pipe


    【解决方案1】:

    当您 write (pipefd[1], buf2, strlen(buf2)); 时,您忽略了将 '\0' 放入流中。将其更改为:

    write (pipefd[1], buf2, strlen(buf2)+1);
    

    你的字符串现在将包含空终止符,防止最后出现垃圾。

    使用read (pipefd[0], &amp;buf, strlen(buf)) 无效,因为buf 未初始化。 strlen 是一个简单的函数,它在字符串末尾查找终止的 null,找到后停止。与 C++ 向量的 length 函数不同,C 函数无法访问内存元数据。 (sizeof是运营商)

    【讨论】:

    • 现在我感觉很糟糕,因为我已经知道了,只是……错过了。但现在。如何阅读超过 1 个单词?
    • 这不会造成溢出的机会吗?或者我如何指定何时结束循环?你能给我一个简单的例子吗?我知道我可以while (read(pipefd[0], &amp;buf, 1) &gt; 0) 然后做一个柜台。让我试试看
    • @Kalec,这确实是一个单独的问题。由于您不移动缓冲区,因此没有溢出风险。尝试在处理读写的代码块周围放置循环。然后,如果您遇到困难,请发布另一个关于在哪里的问题。
    • @Kalec,我不觉得很傻。当您说“超过一个词”时,您的字面意思是多词输入被截断。我以为你的意思是你的服务器只读取一个块,然后退出。 fgets 确实解决了你的问题,单句转移不需要循环。
    猜你喜欢
    • 1970-01-01
    • 2012-04-28
    • 2017-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多