fgets to read line by line in files

codeara picture codeara · Jan 17, 2014 · Viewed 66.3k times · Source

I understand that fgets reads until EOF or a newline.

I wrote a sample code to read lines from a file and I observed that the fgets gets executed more than the desired number of times. It is a very simple file with exactly two blank lines, ie. I pressed enter once and saved the file.

Below is the code:

fp = fopen("sample.txt","r");
while (!feof(fp)) {
        fgets(line,150,fp);
        i++;
        printf("%s",line);
}
printf("%d",i);

Why is the while loop getting executed three times instead of 2, as there are only two blank lines in the file?

Answer

M Oehm picture M Oehm · Jan 17, 2014

In your case, the last line is seemingly read twice, except that it isn't. The last call to fgets returns NULL to indicate the the end of file has been read. You don't check that, and print the old contents of the buffer again, because the buffer wasn't updated.

It is usually better not to use feof at all and check return values from the f... family of functions:

fp = fopen("sample.txt", "r");
while (1) {
        if (fgets(line,150, fp) == NULL) break;
        i++;
        printf("%3d: %s", i, line);
}
printf("%d\n",i);

The function feof returns true after trying to read beyond the end of the file, which only happens after your last (unsuccessful) call to fgets, which tries to read at or rather just before the end of the file. The answers in this long SO post explain more.