2

我写了一个简单的程序来学习如何在 C 中编写管道消息,在这样做的时候我发现了一些我无法解释或理解的相当奇怪的东西,这是代码:

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

#define MAXSIZE 100
int fd[2];

void writeMsg() {
    int i;
    char message[MAXSIZE];
    for (i = 0; i < 12; i++) {
        sprintf(message,"%d%d%d%d%d%d%d%d%d%d\n",i,i,i,i,i,i,i,i,i,i);
        write(fd[1], message, strlen(message));
    }
}

int main() {
    pipe(fd);
    char message[MAXSIZE];
    int pid;
    pid = fork();
    if (pid == 0) {
        writeMsg();
    }
    if (pid > 10) {
        wait(NULL);
        read(fd[0], message, MAXSIZE);
        printf("%s", message);
    }
    return 0;
}

在 writeMsg 中有一个循环在管道中写入大于 MAXSIZE 的消息,然后在 main 中读取并打印该消息,奇怪的是,如果我strlen(message)write(fd[1], message, strlen(message))以下消息中使用会打印:

0000000000
1111111111
2222222222
3333333333
4444444444
5555555555
6666666666
7777777777
8888888888
9

但是,如果我改为使用write(fd[1], message, strlen(message)+1)消息是:

0000000000

strlen(message)和 和有什么不一样strlen(message)+1?在这里http://codewiki.wikidot.com/c:system-calls:write据说如果要写入的字节数小于提供的缓冲区,则输出被截断,但 +1 字符串大小为11,不大于 MAXSIZE。欢迎任何澄清或更正。

4

2 回答 2

2

发生的事情是,当write用字符调用时也被写入strlen(message) + 1\0

这意味着,当read()ing 时,\0将被附加到您的 char 数组中。由于printf()找到时停止\0,这就是为什么在您第一次调用时所写的唯一打印文本的原因write()

于 2013-08-14T23:32:45.607 回答
2

+1 将导致字符串末尾(换行符之后)的零被传输,这意味着当您在另一端打印缓冲区时,将printf在第一行之后停止。我想你并不想发送那个零,所以不要那样做......

如果你真的想通过管道在字符串末尾的零,那么你将不得不找出每个字符串的结束位置,并单独打印它们,例如strlen()用来确定消息的长度,并使用移动的索引index += strlen(&message[index])+1,并printf("%s", &message[index]);在一个循环中,直到您打印所有内容(将索引与您阅读的内容进行比较!)。

使用循环直到read返回零字节应该允许您读取所有输入(您现在读取的内容太短,这就是您没有得到所有 9 的原因)。

于 2013-08-14T23:33:51.700 回答