The other day I was working on a code where in I was doing some file related operations. I used the function feof() to test whether the end of file has been reached or not. I got into some trouble over the way I used this function in my code, after debugging a bit I found the problem. The problem was very much related to the understanding of the feof() API.
So, I thought to share it with all the members and visitors of G4E.
Lets first look at the code snippet :
The code above :
Lets first see the text file :
Lets see the output I was getting :
If you analyze the output above, you will see that the line 'ghi' is displayed twice. Well, this was the cause of concern to me that why the last line is being displayed twice. I kept on debugging the problem for some time and very soon I zeroed down to the function feof(). Then I started studying the the function feof().
As a first step I visited the man page of function feof() but he man page did not have anything to contribute to the solution of this problem. Only the following definition was present there :
In the second step, I thought of using the errno variable to see if some error occurred or not. So I changed the code to something like :
In the above code I introduced the usage of a global variable 'errno' which contains the error code in case some error occurred in this API. The function strerror() takes the variable 'errno' as argument and returns a string of error description. If no error occurred, the string returned by this API is 'Success'.
The output of the above code was :
This concluded that the API feof() never failed during the execution.
After the second step(mentioned above), I was again in a fix. Then suddenly I thought to trace the forward movement of file descriptor in the file. So, now firstly I found the exact number of bytes in the text file. It came out to be 12 bytes(see the command below).
Now I changed the code to something like :
This time I introduced a call to ftell() that will let the print() display the file position indicator value.
The output of the above code was :
The last two lines had my eyes stuck on them. This gave me an idea that despite of reaching the EOF, something is happening due to which feof() is not detecting that EOF is reached and it takes one more iteration for feof() to detect it.
Then In the final step I researched a bit on INTERNET and found that feof() function sets the end of file indicator when the EOF character is actually read. This means when 'ghi' is read for the first time, then EOF is not read along with it. So, no end-of-file indicator is set and feof() returns zero and hence the flow enters the while loop again and then fgets comes to know that the next character is EOF and hence it discards it and returns NULL but sets end-of-file indicator but since the buffer 'buff' that is passed to fgets() was not flushed and hence it still contains the last read in value 'ghi' so it seemed that fgets() returns 'ghi' again. Now feof() detects end-of-file indicator is set and it returns a non zero value and so the while loop breaks.
Ohh...I said and that cleared all my doubts :-)
When you know a problem in and out then it rarely happens in software development that you can't find the solution. Same was the situation here, since now the whole problem was clear so it did not take much time to solve it. Here is the code :
In the above code, I completely got away with the function feof() since I came to know that fgets() returns NULL when EOF is read. Here is the output :
The output this time was expected.
To conclude, this article gives a good overview of how feof() works internally and how we can use it.
Stay tuned for more!!!
So, I thought to share it with all the members and visitors of G4E.
The code
Lets first look at the code snippet :
Code:
#include<stdio.h>
int main(void)
{
FILE *fd = NULL;
char buff[20];
fd = fopen("data.txt","r");
if(fd)
{
while(!feof(fd))
{
fgets(buff, sizeof(buff), fd);
puts(buff);
}
fclose(fd);
}
return 0;
}
- Tries to open a text file data.txt in the read only mode.
- If the file is successfully opened for reading then a while loop is started.
- The loop runs until all the lines in the text file are read and displayed.
- Finally, the file is closed.
Lets first see the text file :
Code:
abc def ghi
Code:
~/practice $ ./feof abc def ghi ghi
The Debugging
As a first step I visited the man page of function feof() but he man page did not have anything to contribute to the solution of this problem. Only the following definition was present there :
Quote:
The function feof() tests the end-of-file indicator for the stream pointed to by stream, returning non-zero if it is set. The end-of-file indicator can only be cleared by the function clearerr().
Code:
#include<stdio.h>
#include<errno.h>
#include<string.h>
int main(void)
{
FILE *fd = NULL;
char buff[20];
fd = fopen("data.txt","r");
if(fd)
{
errno = 0;
while(!feof(fd))
{
printf("\n [%s] \n", strerror(errno));
fgets(buff, sizeof(buff), fd);
puts(buff);
errno = 0;
}
fclose(fd);
}
return 0;
}
Code:
#include<stdio.h>
#include<errno.h>
#include<string.h>
int main(void)
{
FILE *fd = NULL;
char buff[20];
fd = fopen("data.txt","r");
if(fd)
{
errno = 0;
while(!feof(fd))
{
printf("\n [%s] \n", strerror(errno));
fgets(buff, sizeof(buff), fd);
puts(buff);
errno = 0;
}
fclose(fd);
}
return 0;
}
The output of the above code was :
Code:
~/practice $ ./feof [Success] abc [Success] def [Success] ghi [Success] ghi
After the second step(mentioned above), I was again in a fix. Then suddenly I thought to trace the forward movement of file descriptor in the file. So, now firstly I found the exact number of bytes in the text file. It came out to be 12 bytes(see the command below).
Code:
~/practice $ ls -lart data.txt -rw-r--r-- 1 himanshu family 12 2011-11-16 21:25 data.txt
Code:
#include<stdio.h>
int main(void)
{
FILE *fd = NULL;
char buff[20];
fd = fopen("data.txt","r");
if(fd)
{
while(!feof(fd))
{
fgets(buff, sizeof(buff), fd);
printf("\n The file position indicator is at : [%lu]\n",ftell(fd));
puts(buff);
}
fclose(fd);
}
return 0;
}
The output of the above code was :
Code:
~/practice $ ./feof The file position indicator is at : [4] abc The file position indicator is at : [8] def The file position indicator is at : [12] ghi The file position indicator is at : [12] ghi
Then In the final step I researched a bit on INTERNET and found that feof() function sets the end of file indicator when the EOF character is actually read. This means when 'ghi' is read for the first time, then EOF is not read along with it. So, no end-of-file indicator is set and feof() returns zero and hence the flow enters the while loop again and then fgets comes to know that the next character is EOF and hence it discards it and returns NULL but sets end-of-file indicator but since the buffer 'buff' that is passed to fgets() was not flushed and hence it still contains the last read in value 'ghi' so it seemed that fgets() returns 'ghi' again. Now feof() detects end-of-file indicator is set and it returns a non zero value and so the while loop breaks.
Ohh...I said and that cleared all my doubts :-)
The Solution
When you know a problem in and out then it rarely happens in software development that you can't find the solution. Same was the situation here, since now the whole problem was clear so it did not take much time to solve it. Here is the code :
Code:
#include<stdio.h>
int main(void)
{
FILE *fd = NULL;
char buff[20];
fd = fopen("data.txt","r");
if(fd)
{
while(fgets(buff, sizeof(buff), fd))
{
puts(buff);
}
fclose(fd);
}
return 0;
}
Code:
~/practice $ ./feof abc def ghi
Conclusion
To conclude, this article gives a good overview of how feof() works internally and how we can use it.
Stay tuned for more!!!
lionaneesh, Scripting
likes this


