代码之家  ›  专栏  ›  技术社区  ›  N 1.1

为什么此代码不输出预期的输出?

  •  2
  • N 1.1  · 技术社区  · 14 年前

    这是一个很好的问题,可以找到错误。 不?至少初学者可以。

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

    使用上述代码,我试图使用重定向从文件中读取 ./a.out < data . 输入文件的内容:

    1line
    2line
    3line
    4line
    

    但我没有得到预期的输出,而是一些图形字符混合在一起。 怎么了?


    提示:(礼貌的阿洛克)

    • sizeof('1') == sizeof(int)
    • sizeof(“1”)==sizeof(字符)*2

    所以,改用1:-)

    看一看 this post 对于使用fread的缓冲io示例。

    3 回复  |  直到 14 年前
        1
  •  9
  •   Alok Singhal    14 年前

    类型 '1' int 在C中,不是 char ,所以你在阅读 SIZE*sizeof(int) 每个字节 fread . 如果 sizeof(int) 大于1(在大多数现代计算机上是这样),则您正在读取 buffer . 这是C和C++不同的地方之一:在C中,字符文字是类型的。 int ,在C++中,它们是类型的 烧焦

    所以,你需要 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(Car) 是正确的。

    SiZeOf(“1”) 是2,因为 "1" 是一个 烧焦 包含两个元素的数组: “1” 0

        2
  •  0
  •   carlo    14 年前

    这里有一个逐字节的方法来使用重定向/a.out<data从文件中读取行。

    至少产生预期的输出…-)

    /*
    
    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;
    
    }
    
        3
  •  -1
  •   gregery    14 年前

    字符缓冲区[大小+1]={0};

    这并不是您所期望的那样,而是使缓冲区指向程序常量数据段中的一个字节区域。也就是说,这将损坏字节的大小和数量,并可能导致内存保护故障。始终使用strcpy()或等效方法初始化C字符串。