Reading from file and exiting loop using feof()

read until end of file c
eof in c tutorialspoint
while feof php
feof(stdin)
eof c
fgets
using fgetc to read a file
feof documentation

This link tells about why feof() is a bad thing to use as an exit indicator for a loop.

Unsafe ==> having an feof() check in the while, and an fgets() inside the while.

Safe ==> having the fgets()!=NULL check in the while itself.

I'm supposed to see the unsafe code doing an extra while loop iteration, but both do the same(and correct) number of loops. Can someone help me understand what's happening here ?

EDIT : The link actually did say why this is happening, but it took for the correct answer below for me to understand exactly what i was reading. My file did not have a '\n' at the last line, so got same results.

This is the file contents :

abcd
efgh
ijkl

And Here's code :

void testUnsafe(void) {
    FILE *f;
    char buf[20];
    f = fopen("fil.txt", "r");
    while (!feof(f)) {
        fgets(buf, 20, f);
        if (buf[strlen(buf) - 1] == '\n') //cleaner
            buf[strlen(buf) - 1] = '\0';
        printf("%s , %d\n", buf, strlen(buf));
    }
    fclose(f);
}

void testSafe(void) {
    FILE *f;
    char buf[20];
    f = fopen("fil.txt", "r");
    while (fgets(buf, 20, f) != NULL) {
        if (buf[strlen(buf) - 1] == '\n') //cleaner
            buf[strlen(buf) - 1] = '\0';
        printf("%s , %d\n", buf, strlen(buf));
    }
    fclose(f);
}

Output is :

******unsafe test********
abcd , 4
efgh , 4
ijkl , 4
********safe test********
abcd , 4
efgh , 4
ijkl , 4

If your text file ends without a newline after the last line of text, the testUnsafe() function will reach end-of-file when it reads the last line, and produce the three lines of output you have shown.

If your text file does have a newline after the last line of text, the function will read the last line, including the newline, without reaching end-of-file. When it enters the while() loop again, it reads zero characters, sets the end-of-file flag, and outputs the last line which is still in the buffer from the last round.

The while (!feof(f)) construction is not unsafe in itself. It's neglecting to check the return value of fgets() that is unsafe.

Why it's bad to use feof() to control a loop, Why it's bad to use feof() to control a loop. This item was added on: 2003/02/28. When reading in a file, and processing it line by line, it's logical to think of the  This function returns a non-zero value when End-of-File indicator associated with the stream is set, else zero is returned. Example The following example shows the usage of feof() function.

I tried your two examples and got different results to yours. Function testUnsafe() printed the last line of my file twice. There are two reasons for this.

  1. The feof() function returns a nonzero value if a read operation has attempted to read past the end of the file.

  2. Function testUnsafe() does not check the return value of fgets() and so repeats the previously read string before hitting the feof() condition.

I copied your functions into my test program

#include <stdio.h>
#include <string.h>

void testUnsafe(void) {
    FILE *f;
    char buf[20];
    f = fopen("fil.txt", "r");
    while (!feof(f)) {
        fgets(buf, 20, f);
        if (buf[strlen(buf) - 1] == '\n') //cleaner
            buf[strlen(buf) - 1] = '\0';
        printf("%s , %d\n", buf, strlen(buf));
    }
    fclose(f);
}

void testSafe(void) {
    FILE *f;
    char buf[20];
    f = fopen("fil.txt", "r");
    while (fgets(buf, 20, f) != NULL) {
        if (buf[strlen(buf) - 1] == '\n') //cleaner
            buf[strlen(buf) - 1] = '\0';
        printf("%s , %d\n", buf, strlen(buf));
    }
    fclose(f);
}

int main()
{
    testUnsafe();
    printf ("\n\n");
    testSafe();
    return 0;
}

Test file:

Line 1
Line 2
Line 3

Output of testUnsafe():

Line 1 , 6
Line 2 , 6
Line 3 , 6
Line 3 , 6

Output of testSafe():

Line 1 , 6
Line 2 , 6
Line 3 , 6

EOF, getc() and feof() in C, getc() also returns EOF when it fails. So, only comparing the value returned by getc() with EOF is not sufficient to check for actual end of file. To solve this problem,  The loop is entered, fgetc()is called (and returns EOF), and count is incremented. Then feof()is called and returns true, causing the loop to abort. This happens in all such cases. feof()does not return true until aftera read on the stream encounters the end of file.

Basically, to read all your lines you must use algo like that. With ou without newline at end of file,you are sure to load all lines.

The exception here is the last line are not sure to have a LF at the end.

Except thing, like checking buffer overflow, to optimize the memory usage, you can also call realloc() to trim the buffer before adding it in a array.

buffer = (char*)malloc(bufferSize);
while(fgets(buffer, bufferSize, file) != NULL) {
    //here store your pointer in array...
    buffer = (char*)malloc(bufferSize);
};
free(buffer);

Read an input file- process it line by line, process it line by line. Learn more about input, feof never predicts. The loop will be exited by the "break" statement in the "if" inside the loop. fgetl() returns a  To solve this problem, C provides feof() which returns non-zero value only if end of file has reached, otherwise it returns 0. For example, consider the following C program to print contents of file test.txt on screen. In the program, returned value of getc() is compared with EOF first, then there is another check using feof().

PHP feof() Function, eval() exit() get_browser() __halt_compiler() highlight_file() highlight_string() hrtime() ignore_user_abort() pack() Open file, read lines - until EOF is reached: The feof() function checks if the "end-of-file" (EOF) has been reached for an open file. Tip: This function is useful for looping through data of unknown length. There is a list of 80 test subject names in a text file, and I have to use the for loop function to read the names of the first 40 subjects using fgetl function. How do I write the code in MATLAB.

Quickly Learn Programming in C, fp=fopen("1.dat","r"); if(fp==NULL) { printf("Error Openning File for Read!\n"); exit(​1); } for(i=0;i<5;i++) { fscanf(fp,"%f",&score); printf("%f\n",score); feof() function In previous example we used a “for loop” to read data from file as we knew the  In the loop, it creates z and y vectors for the data points. It will loop until the end of the file is reached. The number of points should be in the plot title.

An Introduction to PHP for Scientists and Engineers: Beyond JavaScript, The feof() function is used to test for an end-of-file mark that, when found, terminates the program. Thus, a conditional loop is most often the appropriate approach. file, the alternative is to use break rather than exit: while (!feof($in)) { // Read  In a C program, we use feof() function as below. feof(fp); where, fp – file pointer Example program for feof() function in C programming language: This file handling C program illustrates how to read the contents of a file. Assume that, a file called “test.c” contains

Comments
  • Try putting your file on a netwrok drive, make some kind of pause in the loop, and disconnect the network cable while reading the file.
  • Sorry, as you can see , i'm not that much good at C to understand the problem here, if, that is, this wasn't sarcasm to begin with.
  • Good comment about "neglecting to check the return value of fgets() that is unsafe."
  • Following @NisseEngström comment, that's why it is unsafe.
  • With no newline after the last line, the correct 3 lines were printed.
  • In select situations (embedded null character), strlen(buf) is 0, thus if (buf[strlen(buf) - 1] is UB.
  • @chux : can you give a link where i can learn (easily) about embedded nulls ? my google results are turning out a bit too hard for me.
  • @chux means a line such as "\0some text\n" where fgets() will read up to and including the newline, but after reading it the string functions will see an empty string. I noticed the potential flaw, but thought that in this example it can't happen, as even a blank line will have a newline, and if the final text line lacks a newline it must have at least one other character. But as @chux says, it can.