GIDNetwork > Things to Avoid in C/C++ -- feof(), Part 3
Register
« Things to Avoid in C/C++ -- fflush(stdin), Part 2 Things to Avoid in C/C++ -- system("pause"), Part 4 »

Things to Avoid in C/C++ -- feof(), Part 3

by: WaltP - Sep 20, 2005

feof() to exit a loop

You should never use feof() as the exit indicator for a loop. feof() is TRUE only after the end of file (EOF) is read, not when EOF is reached. To test this, create a normal text file (mine is feof.fil):

Generic Code Example:

4 Walking
3 Working
2 Eating
1 Sleeping

Then compile and run this code:

C/CPP/C++ Code Example:

#include <stdio.h>

int main()
{
    FILE *st;
    char  buf[20];
    
    st = fopen("feof.fil", "r");
    if (st != NULL)
    {
        while (!feof(st))
        {
            fgets(buf, 20, st);
            puts(buf);
        }
        fclose(st);
    }
    return 0;
}

You should see the following output:

Generic Code Example:

D:\C\GIDForum>feof
4 Walking

3 Working

2 Eating

1 Sleeping

1 Sleeping


D:\C\GIDForum>

What has happened is the last line of the file was read, but not the EOF. When the loop returns, the fgets() attempts to read one more record and failed. Since no error checking was done, whatever was left in the buffer is still there and the loop continues.

Two ways pop into mind to solve this. Your read must test for an error.

Fix 1A:

C/CPP/C++ Code Example:

while (!feof(st))
{
    if (fgets(buf, 20, st) != NULL)
    {
        // process your buffer
        puts(buf);
    }
}
fclose(st);

Fix 1B:

C/CPP/C++ Code Example:

while (!feof(st))
{
    if (fgets(buf, 20, st) == NULL)
    {
        // exit the loop when done
        break;
    }
}
fclose(st);

You'll notice a fair amount of code has been added to solve the problem, and you are now making TWO tests. One for feof() in the while, another for fgets() inside the loop. The preferred way (assuming your read is the first thing in the loop) is Fix 2:

C/CPP/C++ Code Example:

while (fgets(buf, 20, st) != NULL)
{
    // process your buffer
    puts(buf);
}
fclose(st);

Short and succinct.

Would you like to comment? This story has been viewed 99,386 times.
« Things to Avoid in C/C++ -- fflush(stdin), Part 2 Things to Avoid in C/C++ -- system("pause"), Part 4 »

__top__

Copyright © GIDNetwork™ 2001 - 2017

Another website by J de Silva

Page generated in : 0.03874 sec.