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
This means that even a tab ( \t ) in the format string can match a single space character in the input stream. Each call to fscanf() reads one line from the file.
The fscanf() function reads data from the current position of the specified stream into the locations that are given by the entries in argument-list, if any. Each entry in argument-list must be a pointer to a variable with a type that corresponds to a type specifier in format-string.
fscanf returns EOF if end of file (or an input error) occurs before any values are stored. If values are stored, it returns the number of items stored; that is, the number of times a value is assigned with one of the fscanf argument pointers.
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, anderrno
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;
}
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With