11

I have the following simple program to read from a text file (num.txt). The text file has numbers 1 2 3 4 5 in each line. When I run the program, it prints 5 twice. Can anybody tell me why is this happening, and how to fix it? thanks in advance

int main(void)
{
   int number;
   FILE *file;

   int i = 0;;

   file = fopen("num.txt", "r");

   while (!feof(file)){

      fscanf(file, "%d", &number);
      printf("%d\n", number);
      }

   return 0;
}

Here's my text file num.xtx

1
2
3
4
5

And here's the program output

1
2
3
4
5
5

There is an extra 5

pdhimal1
  • 229
  • 4
  • 9
  • 19

3 Answers3

12

From the man page of scanf family of functions,

The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream is set, and errno is set to indicate the error.

This means that the last successful fscanf call reads the last line from the stream file after which the while loop condition !feof(file) is true because the end of file condition is not met yet. This means the loop is executed one extra time and the previous value of the variable number is printed again.

Please read this - while(!feof(file)) is always wrong

You should check the return value of scanf instead of checking the end of file indicator on the file stream.

#include <stdio.h>   

int main(void) {
   int number;
   FILE *file = fopen("num.txt", "r");

   // check file for NULL in case there
   // is error in opening the file
   if(file == NULL) {
      printf("error in opening file\n");
      return 1;
   }      

   // check if fscanf call is successful 
   // by checking its return value for 1.
   // fscanf returns the number of input
   // items successfully matched and assigned
   while(fscanf(file, "%d", &number) == 1)
      printf("%d\n", number);

   return 0;
}
Community
  • 1
  • 1
ajay
  • 9,402
  • 8
  • 44
  • 71
  • while(fscanf(file, "%d", &number) == 1) may confuse users reading more then 1 record per scanf call (for example " fscanf(file, "%d %d", &number1,&munber2)" ). I would use : while(fscanf(file, "%d", &number) != EOF). – Oren Fivlovich Aug 18 '19 at 01:29
5

The second time fscanf failed and didn't write anything to number, that's why it's still 5 from the last time. To know if fscanf succeeded, you have to check its return value.

fscanf returns the number of arguments that it wrote. In your case, if it returns 1, it worked; if it returns 0, it didn't. This is what you should check instead of feof.

while (fscanf(file, "%d", &number) == 1)
{
    printf("%d\n", number);
}
zneak
  • 134,922
  • 42
  • 253
  • 328
0

If you want to work with feof you need to add one more test inside the loop:

while (!feof(file)) {
      fscanf(file, "%d", &number);

      // add a second test before printing
      if (!feof(file))
        printf("%d\n", number);
}
DgrinderHZ
  • 84
  • 4