Гибберши в буфере чтения ()? - PullRequest
0 голосов
/ 22 сентября 2011

Я новичок в 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 */
    }

выходит из строя. Что я делаю не так?

Редактировать: объявления по запросу. Я понятия не имею о memsetting, мой первый день в C.

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

Edit:

Ответ «слишком короткий» также решает проблему. Похоже, консенсус заключается в том, что использование memset является излишним. Я начинающий программист на Си, поэтому мне придется поверить мнению комментаторов. Это, однако, аргумент ad populum, и мю слишком короткий, действительно может быть больше прав. В любом случае, я рекомендую прочитать оба ответа, так как любое «излишество», вероятно, все еще тривиально.

Ответы [ 3 ]

2 голосов
/ 22 сентября 2011

Как уже отмечали другие, ваш буфер недостаточно велик, чтобы вместить текст, который вы читаете, и вы не гарантируете, что он обнуляется.

Но использование 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() не удастся, он может опустошиться).

Тогда вам просто придется иметь дело с переводом строки вend.

Это также предполагает, что вся строка читается за один вызов чтения.Вероятно, в этом случае, но часто при использовании чтения необходимо объединить несколько операций чтения, пока вы не прочитаете достаточно данных.

1 голос
/ 22 сентября 2011

Насколько я понимаю, ваша строка:

puts "success"

будет выводить (в C-терминах)

success\n\0

, который я считаю 9 символами.

Вы объявили readbuffer как только 6. Предыдущий ответ только увеличил его до 7.

1 голос
/ 22 сентября 2011

Как отмечается в комментариях, у вас не будет нулевого терминатора на 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 не будет автоматически инициализировать локальную переменную, вам придется сделать это самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...