2

I couldn't understand what is the difference between the feof() function and EOF ? Both represent the end of file, then how are they different and how would we know where to use what?

Where to use the feof() function and where to use EOF?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
sunflower
  • 21
  • 3
  • 3
    No, `feof()` does not represent end of file. It informs when *an attempt has been made to read past the end of a file*. Related: [Why is `while ( !feof (file) )` always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) Its main use is to disambiguate the reason when a file read function fails. – Weather Vane Mar 17 '23 at 18:42
  • `EOF` is a value. You can compare things to this value. `feof()` is a function, that returns a value. You can call `feof()`, and see what value it gives you. – Steve Summit Mar 17 '23 at 18:52
  • If you call `getchar`, and the value it gives you is equal to `EOF`, you've hit end-of-file. (That is, `getchar` didnt give you a real character, because there were no more to give.) Or, if you call `feof(stdin)`, and if it returns a true value, that means you've hit end-of-file. – Steve Summit Mar 17 '23 at 18:52

3 Answers3

3

feof and EOF are defined in <stdio.h>.

EOF is a macro that expands to an integer constant expression of type int with a negative value (usually -1). It is different from all valid byte values returned by getchar(), getc() and fgetc(). These functions return EOF if no byte could be read from the stream. The return value must be stored into an int for the comparison to EOF to reliably detect the end of file.

Regarding feof(), the quick answer is:

never use feof(file), always check the return value of all file reading functions to detect the end of stream:

for getchar(), getc() or fgetc():

int c;
while ((c = getchar()) != EOF) {
    // handle the byte read from the file
}
// end of file reached

for fgets():

char buf[100];
if (fgets(buf, sizeof buf, file)) {
    // a line was read into buf, or the initial portion of
    // the current line if longer than 99 bytes.
} else {
    // end of file has been reached.
}

for fread():

size_t nread = fread(buf, size_of_element, count_of_elements, file);
if (nread > 0) {
    // handle the elements read
} else {
    // end of file reached
}

for scanf() and fscanf():

int value;
int res = fscanf(file, "%d", &value);
if (res == 1) {
    // int value was read from the stream
} else {
    // no integer could be read: either input is not an integer or
    // end of file was reached.
    // read and discard the input line
    int c = EOF;
    if (res != EOF) {
        while ((c = getc(file)) != EOF && c != '\n')
            continue;
    }
    if (c == EOF) {
        // end of file reached
    } else {
        // try and recover from invalid input.
    }
}

Regarding scanf() and fscanf(): reading a string with %s is an error as any sufficient long input will cause a buffer overflow and could be used as an exploit. It is recommended to use fgets() or getline() to read a line into an array of char and use sscanf() to parse its contents carefully, specifying a maximum number of characters to store into the destination array for the %s and %[ conversions:

char line[100];
char player[20];
char eol;
int score;
while (fgets(line, sizeof line, file)) {
    if (sscanf(line, "%19s%d%c", player, &score, &eol) != 3 || eol != '\n') {
        fprintf(stderr, "invalid input: %s\n", line);
        if (!strchr(line, '\n')) {
            int c;
            while ((c = getc(file)) != EOF && c != '\n')
                continue;
            if (c == EOF)
                break;
        }
        continue;
    }
    // handle the player score...
}
// end of file has been reached.

You may want to read and understand Why is “while( !feof(file) )” always wrong? .

The long answer is:

the feof() function returns the value of the end-of-file indicator that may have been set by a previous file read operation upon reaching the end of file. Since you should always test for success of these file reading operations, this function is very rarely used, only to distinguish file read errors from reaching the end of file. File read errors are quite rare on desktop systems today so this distinction is usually unnecessary. 99% of code that uses feof() is misusing this function.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • So, it sounds like the various file read functions set a flag internally somewhere, and `feof()` just reads that previously-set flag and returns its value, right? So, a file read function can return an error _or_ the value `EOF`, whereas `feof()` just tells you if the `EOF` internal flag is set, I presume. – Gabriel Staples Mar 17 '23 at 19:12
  • 1
    @GabrielStaples: yes your interpretation is correct. There is no reason to use `feof()`, just test the return values of the file reading functions. – chqrlie Mar 17 '23 at 19:20
  • For an example of when `feof` can be useful, see the code in [this answer](https://stackoverflow.com/questions/75754361#75756400). – Steve Summit Mar 17 '23 at 19:31
  • 1
    @SteveSummit: I'm afraid this example is not a good illustration. The code would have undefined behavior upon read errors. Why not use `fread()` or check for `EOF` the proper way? – chqrlie Mar 17 '23 at 19:39
  • "It is different from all valid byte values returned by getchar()" --> except for those pesky 64-bit `int`, 64-bit `unsigned char` machines that get [no respect](https://www.youtube.com/watch?v=ZCVR_ajL_Eo) these days. – chux - Reinstate Monica Mar 17 '23 at 22:00
  • The `int value; if (fscanf(file, "%d", &value) == 1) { ...` code has a corner weakness. If `scanf(file, "%d", &value)` returns `EOF` due to a non-persistent input error, the discard loop may read into the next line. – chux - Reinstate Monica Mar 17 '23 at 22:03
  • @chux-ReinstateMonica: corner case corrected. – chqrlie Mar 17 '23 at 22:06
  • @chux-ReinstateMonica: absolutely pesky and no matter how wide the `int` is as long as `sizeof(int) == 1`... [C'est de la merde!](https://www.youtube.com/watch?v=CoB36zxT940) [or longer](https://www.youtube.com/watch?v=G4iIIatxTH8) – chqrlie Mar 17 '23 at 22:09
  • 1
    "File read errors are quite rare on desktop systems today" --> To test code for persistent read errors, simply use `FILE *file = fopen("abc.txt", "w");` and input functions will readily return `EOF` due to a read error. Non-persistent read errors are tricky. – chux - Reinstate Monica Mar 17 '23 at 22:17
0

Function feof(file) returns TRUE if the previous file operation has set the end of file flag.

EOF is an integer constant returned by many file I/O functions indicating that it is not possible to read more data from the file/stream.

Where to use feof() function and where to use of?

Basically you can use feof(file) after I/O operation to check if the end of file flag is set (ie if it is possible to read more data from the file/stream)

EOF is returned by many I/O functions - you need to read the function documentation. Example fscanf

0___________
  • 60,014
  • 4
  • 34
  • 74
0

What is the difference between feof() function and EOF ... ?

EOF is returned from various input functions to indicate:

  1. A read end-of-file condition just occurred when attempting to read with no other input. This sets the stream's end-of-file flag.

  2. The stream's end-of-file flag is set and no read attempt occurred.

  3. The stream detects an input error like trying to read from an output stream or (rarely) some communication error.

  4. Other*1.

feof() reports the stream's end-of-file flag.


Where to use the feof() function and where to use EOF?

Watch for a return value from an input function of EOF to detect a no-input condition.

Use feof() to detect why an input function returned EOF.

    int ch = fgetc(stream);
    if (ch == EOF) {
      if (feof(stream)) puts("End of file");
      else puts("Input error");
    }

*1 EOF is also returned on rare machines where sizeof(int) == 1 and can indicate a valid input character. Details here omitted for such a machine.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256