C Function Feof
[ C Standard Library - ](#)
feof() is used to detect whether the end of a file has been reached.
We can think of it as an "endpoint detector" β after reading each part of the content, we ask it: "Is it the end yet?"
* * *
## Description
The C library function `int feof(FILE *stream)` tests the end-of-file indicator for the given stream.
Two new concepts appear here, let's explain them separately:
**Stream (stream)** is C's abstraction for input and output. Whether it's a file on the hard disk, keyboard input, or network data, in C, they are all uniformly treated as "streams." You can imagine a stream as a pipe, with data flowing from one end to the other.
**End-of-file indicator (EOF marker)** is a status flag built into each file stream. It's like a bookmark that automatically flips to the "finished reading" page when the file content has been read completely.
The purpose of `feof()` is to check this bookmark β if the bookmark shows "finished reading," `feof()` returns a non-zero value. If the bookmark is still on "not finished reading," `feof()` returns 0.
* * *
## Declaration
Below is the declaration of the `feof()` function, with a breakdown of its meaning:
```c
int feof(FILE *stream)
- `int` is the return type β `feof()` returns an integer; non-zero means the end has been reached, 0 means it hasn't.
- `FILE *stream` is the parameter β you need to pass a file pointer (the one returned by `fopen()` when opening a file) to tell `feof()` which file stream to check.
* * *
## Parameters
`feof()` accepts one parameter:
| Parameter | Type | Description |
| --- | --- | --- |
| stream | FILE * | A file pointer returned by the `fopen()` function, pointing to the opened file to be checked. |
* * *
## Return Value
The return value is explained as follows:
| Return Value | Meaning |
| --- | --- |
| Non-zero value | The file has been read to the end; there is no more content to read. |
| 0 | The file has not been read to the end; reading can continue. |
> Key Point: `feof()` only returns a non-zero value *after* an attempt has been made to read past the end of the file. If you have just finished reading the last character but haven't tried to continue reading, `feof()` will still return 0. This timing issue will be explained in detail in the next section.
* * *
## Example
The following example demonstrates the correct usage of the `feof()` function.
The program reads the file content character by character, using `feof()` to check if the end has been reached after each read.
## Example
```c
#include
int main ()
{
// FILE * is the file pointer type, used to point to an opened file.
FILE *fp;
// fgetc() returns an int, not a char, because it might need to return EOF (-1).
int c;
// fopen() opens the file; "r" indicates read-only mode.
fp = fopen("file.txt", "r");
// If the file doesn't exist or there's no permission, fopen() returns NULL.
if(fp == NULL)
{
// perror() prints the system error message, helping to locate the problem.
perror("Error opening file");
return(-1);
}
// Using an infinite loop with an internal check.
// This ensures "read first, then check," avoiding reading extra content.
while(1)
{
// Step 1: Read one character from the file.
c = fgetc(fp);
// Step 2: Immediately after reading, use feof() to check if the end has been reached.
if(feof(fp))
{
// End reached, break out of the loop, don't process c.
break;
}
// Step 3: Only after confirming the end hasn't been reached, use the value of c.
printf("%c", c);
}
// fclose() closes the file and releases system resources.
fclose(fp);
return(0);
}
Assume we have a text file `file.txt` with the following content:
This is .com
Compile and run the above program, the output will be:
This is .com
The program correctly prints the entire content of the file without any extra garbled characters.
* * *
## Common Pitfall: Why You Shouldn't Put `feof()` in the Loop Condition
Many beginners write code like the following, which looks more concise but is actually incorrect:
## Incorrect Example
```c
#include
int main ()
{
FILE *fp;
int c;
fp = fopen("file.txt", "r");
if(fp == NULL)
{
perror("Error opening file");
return(-1);
}
// Error: Using feof() as the loop's entry condition.
while(!feof(fp))
{
c = fgetc(fp);
printf("%c", c);
}
fclose(fp);
return(0);
}
The output of this incorrect code will be:
This is .com
There is an extra garbled character at the end. Why does this happen? Let's trace the loop execution process round by round:
| Loop Iteration | `feof()` at Loop Entry | `fgetc()` Reads | `printf()` Outputs | Explanation |
| --- | --- | --- | --- | --- |
| 1st | Returns 0 (hasn't read yet) | 'T' | T | Normal |
| 2nd | Returns 0 (hasn't reached end) | 'h' | h | Normal |
| ... | ... | ... | ... | Intermediate characters output normally |
| Last Normal | Returns 0 (hasn't reached end) | 'm' | m | Last normal character |
| Extra Iteration | Returns 0 (Note! Just read 'm', feof doesn't know the end has been reached yet) | EOF (-1) | (Garbled) | Bug! Read one extra time |
The root of the problem is: when you have just read 'm' (the last character of the file), `feof()` still returns 0.
It must wait until you "try to read one more time," discover there is no more content to read, and then flip its internal flag to "finished."
Therefore, the `while(!feof(fp))` pattern causes the loop to run one extra time. In that extra iteration, `fgetc()` returns EOF (-1), and `printf` tries to print -1 as a character, resulting in garbled output.
> Remember in one sentence: `feof()` is a "post-report," not a "pre-warning." It answers "Did the last read hit the end?" not "Will the next read hit the end?" Therefore, never use `feof()` as the loop's entry condition.
The correct pattern is the one shown in the earlier example β read first, then check, and only use the read content after confirming it's safe.
* * *
## When to Use `feof()`
`feof()` is primarily used in the following two scenarios:
| Scenario | Usage | Example |
| --- | --- | --- |
| Loop reading a file | Read first, then check (Recommended) | `while(1) { c = fgetc(fp); if(feof(fp)) break; ... }` |
| Troubleshooting read errors | Distinguish between "normal end" and "read error" | `if(feof(fp)) { /* Normal end */ } else if(ferror(fp)) { /* Read error */ }` |
In the second scenario, `fgetc()` returning EOF has two possibilities: it really finished reading (check with `feof()`), or an error occurred during reading (check with `ferror()`). These two cases need to be handled separately.
[ C Standard Library - ](#)
YouTip