为什么这段代码没有输出预期的输出?

时间:2010-03-04 10:02:09

标签: c fread

这对于发现错误来说是一个很好的问题。 没有?好吧,至少对于初学者来说。

#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;
}

Using the above code, I am trying to read from a file using redirection ./a.out < data. Contents of input file:

1line
2line
3line
4line

But I am not getting the expected output, rather some graphical characters are mixed in. What is wrong?


Hint: (Courtesy Alok)

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

So, use 1 instead :-)

3 个答案:

答案 0 :(得分:9)

C中'1'的类型为int,而不是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

答案 1 :(得分:0)

这是使用重定向来从文件中传播行的逐字节方式./a.out&lt;数据

至少产生预期的输出......: - )

/*

Why does this code not output the expected output ?,
http://stackoverflow.com/questions/2378264/why-does-this-code-not-output-the-expected-output

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;

}

答案 2 :(得分:-1)

char buffer [SIZE + 1] = {0};

这不是你所期望的,它使缓冲区指向程序常量数据段中的一个字节区域。即,这将破坏SIZE字节数,并可能导致内存保护错误。始终使用strcpy()或等效函数初始化C字符串。