2

I just read in a string using the following statement:

fgets(string, 100, file);

This string that was just read in was the last line. If I call feof() now will it return TRUE? Is it the same as calling feof() right at the start before reading in any lines?

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Brandon
  • 401
  • 5
  • 20
  • No, `feof()` only returns non-zero after the first read past `EOF`. – Iharob Al Asimi Jan 19 '16 at 23:18
  • Possible duplicate of [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – user3386109 Jan 19 '16 at 23:20
  • @iharob that's when it's guaranteed to be non-zero; it may or may not be if the last character was read exactly by fgets – M.M Jan 19 '16 at 23:21
  • @user3386109 I thought of marking it as duplicate but it's not the same question. This one is asking specifically about the behavior of `feof()`. – Iharob Al Asimi Jan 19 '16 at 23:21
  • @M.M I don't see the contradiction. If `fgets()` reads exactly up to the last character in the file, you will need to call it again to make `feof()` return a non-zero value. – Iharob Al Asimi Jan 19 '16 at 23:22
  • 1
    *"Is it the same as calling feof() right at the start before reading in any lines?"* Even if the file size is 0 `feof` will be false just after the file is opened. The man page explains why. – Weather Vane Jan 19 '16 at 23:23

3 Answers3

2

No, don't use feof() to detect the end of the file. Instead check for a read failure, for example fgets() will return NULL if it attempts to read past the end of the file whereas feof() will return 0 until some function attempts to read past the end of the file, only after that it returns non-zero.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • 1
    `fgets()` returns `NULL` in at least 2 situations: End-of-file, Input error. (maybe a [3rd](http://stackoverflow.com/q/23388620/2410359)) Using `feof()` is a **good** way to detect the end-of-file (after `fgets()` returned NULL.) – chux - Reinstate Monica Jan 20 '16 at 00:02
  • @iharob If I call fgets to check and see if the reutrn value is NULL and in reality it is not end of file, then I would have skipped a line. Is there a way to avoid this? Perhaps a way to go back to the beginning of the previous line after calling fgets to check and see if the output is NULL? – Brandon Jan 20 '16 at 00:32
2

Does feof() work when called after reading in last line?

No.

feof() becomes true when reading past the end of data. Reading the last line may not be pass the end of data if the last line ended in '\n'.

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

The short answer is NO. Here is why:

If fgets successfully read the '\n' at the end of the line, the end-of-file indicator in the FILE structure has not been set. Hence feof() will return 0, just like it should before reading anything, even on an empty file.

feof() can only be used to distinguish between end-of-file and read-error conditions after an input operation failed. Similarly, ferr() can be used to check for read-error after an input operation failed.

Programmers usually ignore the difference between end-of-file and read-error. Hence they only rely on checking if the input operation succeeded or failed. Thus they never use feof(), and so should you.

The behavior is somewhat similar as that of errno: errno is set by some library functions in case of error or failure. It is not reset to 0 upon success. Checking errno after a function call is only meaningful if the operation failed and if errno was cleared to 0 before the function call.

If you want to check if you indeed reached to the of file, you need to try and read extra input. For example you can use this function:

int is_at_end_of_file(FILE *f) {
    int c = getc(file);
    if (c == EOF) {
        return 1;
    } else {
        ungetc(c, file);
        return 0;
    }
}

But reading extra input might not be worthwhile if reading from the console: it will require for the user to type extra input that will be kept in the input stream. If reading from a pipe or a device, the side effect might be even more problematic. Alas, there is no portable way to test if a FILE stream is associated with an actual file.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • so does this mean that the reutrn of getc will aslo be NULL if the end of file has been reached? – Brandon Jan 20 '16 at 01:01
  • @Brandon: no, the return value of `getc()` at end of file (or upon read error) is `EOF`, a specific negative `int` value defined in ``. – chqrlie Jan 20 '16 at 01:03
  • I assume you mean fgetc() right? Also does fgets() return and EOF too? Thanks for your help. – Brandon Jan 20 '16 at 01:14
  • @Brandon: `getc` and `fgetc` are equivalent. `getc` can be implemented as a macro on some systems and might be more efficient. `fgets()` returns `NULL` if it cannot read anything, otherwise it returns the pointer to the destination array. – chqrlie Jan 20 '16 at 01:28
  • @Brandon: can you please check this answer as accepted? You asked a separate question on the same subject, what did you miss here? – chqrlie Jan 20 '16 at 03:31