Почему этот код не выводит ожидаемый результат? - PullRequest
2 голосов
/ 04 марта 2010

Это может быть хорошим вопросом для поиска ошибок. Нет? Хорошо для начинающих, по крайней мере.

<code>#define SIZE 4
int main(void){
  int chars_read = 1;
  char buffer[SIZE + 1] = {0};  
  setvbuf(stdin, (char *)NULL, _IOFBF, sizeof(buffer)-1);  
  while(chars_read){
    chars_read = fread(buffer, sizeof('1'), SIZE, stdin);
    printf("%d, %s\n", chars_read, buffer);
  }
  return 0;
}<code>

Используя приведенный выше код, я пытаюсь прочитать файл с помощью перенаправления ./a.out < data. Содержимое входного файла:

1line
2line
3line
4line

Но я не получаю ожидаемый результат, скорее смешиваются некоторые графические символы. Что не так?


Подсказка: (любезно предоставлено Alok)

  • sizeof('1') == sizeof(int)
  • sizeof ("1") == sizeof (char) * 2

Итак, используйте 1 вместо: -)

Посмотрите этот пост для примера буферизованного ввода-вывода с использованием fread .

Ответы [ 3 ]

9 голосов
/ 04 марта 2010

Тип '1' - int в C, а не char, поэтому вы читаете SIZE*sizeof(int) байтов в каждом fread. Если sizeof(int) больше 1 (на большинстве современных компьютеров это так), то вы читаете мимо хранилища для buffer. Это одно из мест, где C и C ++ различны: в C символьные литералы имеют тип int, в C ++ они имеют тип char.

Итак, вам нужно chars_read = fread(buffer, 1, SIZE, stdin);, потому что sizeof(char) равно 1 по определению.

На самом деле, я бы написал ваш цикл так:

while ((chars_read = fread(buffer, 1, sizeof buffer - 1)) > 0) {
    buffer[chars_read] = 0; /* In case chars_read != sizeof buffer - 1.
                               You may want to do other things in this case,
                               such as check for errors using ferror. */
    printf("%d, %s\n", chars_read, buffer);
}

Чтобы ответить на ваш другой вопрос, '\0' - это int 0, поэтому {'\0'} и {0} эквивалентны.

Для setvbuf моя документация гласит:

Аргумент size может быть задан как ноль, чтобы получить отложенное выделение оптимального размера буфера как обычно.

Почему вы комментируете \\ вместо // или /* */? : -)

Редактировать : Исходя из вашего редактирования вопроса, sizeof("1") неверно, sizeof(char) правильно.

sizeof("1") равно 2, потому что "1" - это массив char, содержащий два элемента: '1' и 0.

0 голосов
/ 05 марта 2010

Вот побитовый способ, чтобы перечитать строки из файла с помощью перенаправления ./a.out Дает ожидаемый результат как минимум ...: -)

/*

Why does this code not output the expected output ?,
/2111194/pochemu-etot-kod-ne-vyvodit-ozhidaemyi-rezultat

compile with:
gcc -Wall -O3 fread-test.c

create data:
echo $'1line\n2line\n3line\n4line' > data

./a.out < data

*/

#include <stdio.h>

#define SIZE 5

int main(void) 
{

   int i=0, countNL=0;
   char singlechar = 0;
   char linebuf[SIZE + 1] = {0};
   setvbuf(stdin, (char *)NULL, _IOFBF, sizeof(linebuf)-1);  

   while(fread(&singlechar, 1, 1, stdin))     // fread stdin byte-by-byte
   {
      if ( (singlechar == '\n') )
      {
         countNL++;
         linebuf[i] = '\0';
         printf("%d:  %s\n", countNL, linebuf);
         i = 0;
      } else {
         linebuf[i] = singlechar; 
         i++;
      }
   }

   if ( i > 0 )    // if the last line was not terminated by '\n' ...
   {
      countNL++;
      linebuf[i] = '\0';
      printf("%d:  %s\n", countNL, linebuf);
   }

 return 0;

}
0 голосов
/ 05 марта 2010

буфер символов [SIZE + 1] = {0};

Это не делает то, что вы ожидаете, оно создает буферную точку для однобайтовой области в сегменте постоянных данных программ. Т.е. это повредит РАЗМЕРУ количество байтов и, возможно, вызовет сбой защиты памяти. Всегда инициализируйте строки C с помощью strcpy () или эквивалентного.

...