read()缓冲区中的胡言乱语?

时间:2011-09-22 06:19:54

标签: c ruby

我是C的新手,因此我对以下行为感到困惑。使用pipe()fork()我正在阅读以下琐碎的ruby程序的输出:

puts "success"

通过调用C:中的读取函数

n = read(fd[0], readbuffer, sizeof(readbuffer));
printf("received: %s", readbuffer);

然而,printf正在向控制台打印一堆“无法识别的字符”符号(如钻石中的问号)。此外,进行比较,如:

    if (strcmp(readbuffer, "success") == 0)
    {
        /* do something */
    }

失败。我做错了什么?

编辑:按要求声明。我不知道忘记了,我在C的第一天。

int fd[2], in;
pid_t pid;
char readbuffer[6];

编辑:

'mu太短'的答案也解决了这个问题。共识似乎是使用memset是过度的。我是新手C程序员所以我必须相信评论员的意见。然而,这是一个论点和广告,而且太短可能确实更加正确。在任何情况下,我建议阅读这两个答案,因为任何“过度杀伤”可能仍然是如此。

3 个答案:

答案 0 :(得分:2)

正如其他人所指出的那样,你的缓冲区不够大,无法保存你正在阅读的文本,而且你不能确保它的空终止。

但是在每次读取之前使用memset()将整个缓冲区归零是不必要的;你只需要确保在你读过的数据末尾有一个空值(并且当然会使你的缓冲区更大)。

如果您将readbuffer设置为至少9个字符,请替换:

n = read(fd[0], readbuffer, sizeof(readbuffer));

.. ..用

n = read(fd[0], readbuffer, sizeof(readbuffer) - 1);
readbuffer[n] = '\0';

..然后应该这样做(尽管你应该理想地检查n是> = 0以确保read()成功)。指定一个小于读取缓冲区的大小可确保readbuffer[n]不会溢出(但如果read()失败则可能会欠载)。

然后你必须在最后处理换行。

这也假定在一次读取调用中读取整个字符串。在这种情况下很可能,但通常在使用read来连接多个读取时,直到你读完了足够的数据。

答案 1 :(得分:1)

正如评论所指出的那样,readbuffer上没有空终结符,所以它实际上不是C字符串。你可以这样做:

#include <string.h>

/* ... */

memset(readbuffer, 0, sizeof(readbuffer));
n = read(fd[0], readbuffer, sizeof(readbuffer) - 1);

这将为您提供正确的以空字符结尾的字符串。但是,如果您确实需要长度为6的字符串,请将readbuffer的声明更改为:

char readbuffer[7];

如果您只需要readbuffer一次,可以说:

char readbuffer[7] = { 0 };

将其初始化为全零。但是,如果您在循环中执行read,那么您需要在每个memset(readbuffer, 0, sizeof(readbuffer))之前read,以确保您不会得到最后一个的剩余数据步骤

C不会自动初始化局部变量,你必须自己动手。

答案 2 :(得分:1)

据我所知,你的行:

puts "success"

将输出(以C语言表示)

success\n\0

我算作9个字符。

您仅将readbuffer声明为6.之前的答案仅将其提升为7。