简体   繁体   中英

Why does this code not output the expected output?

This can be a good question for finding bugs. No? Okay for beginners at least.

#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)

 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) 

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)


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 :-)

Take a look at this post for buffered IO example using fread.

The type of '1' is int in C, not char , so you are reading SIZE*sizeof(int) bytes in each fread . If sizeof(int) is greater than 1 (on most modern computers it is), then you are reading past the storage for buffer . This is one of the places where C and C++ are different: in C, character literals are of type int , in C++, they are of type char .

So, you need chars_read = fread(buffer, 1, SIZE, stdin); because sizeof(char) is 1 by definition.

In fact, I would write your loop as:

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

To answer your another question, '\\0' is the int 0, so {'\\0'} and {0} are equivalent.

For setvbuf , my documentation says:

The size argument may be given as zero to obtain deferred optimal-size buffer allocation as usual.

Why are you commenting with \\\\ instead of // or /* */ ? :-)

Edit : Based upon your edit of the question, sizeof("1") is wrong, sizeof(char) is correct.

sizeof("1") is 2, because "1" is a char array containing two elements: '1' and 0 .

Here's a byte-by-byte way to fread the lines from a file using redirection ./a.out < data.

Produces the expected output at least ... :-)

/*

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;

}

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

This isn't doing what you expect, it is making buffer point to a one byte region in the programs constant data segment. Ie this will corrupt SIZE amount of bytes and possibly cause a memory protection fault. Always initialize C strings with strcpy() or equivalent.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM