c++filebinaryfilesfeof

feof() doesn´t detect end of file when i'm updating a binary file in C/C++


I have a binary file with registries of the Student struct form. And I have this code in my .cpp file:

#include <iostream>
#include <stdio.h>

struct Student
{
    int id;
    int age;
    char name[50+1];
    int dateOfBirth;
};

bool mustIncrementAge(int dateOfBirth)
{   // a silly function, only for the example.

    return true;
}
int main()
{
    FILE* fileStudents;
    fileStudents = fopen("Students.dat", "rb+");

    Student regStudent;
    fread(&regStudent, sizeof(Student), 1, fileStudents);

    while(!feof(fileStudents)) // The cycle never ends. feof() doesn't detect end of file.
    {
        if(mustIncrementAge(regStudent.dateOfBirth))
        {
            regStudent.age++;
            fseek(fileStudents, (-1)*sizeof(Student), SEEK_CUR);
            fwrite(&regStudent, sizeof(Student), 1, fileStudents);
        }

        fread(&regStudent, sizeof(Student), 1, fileStudents);
    }

    fclose(fileStudents);

    return 0;
}

I want to update the file, incrementing the ages of Students if they verify the mustIncrementAge(dateOfBirth) function (I put it always true).

The problem is that the while loop never ends. feof() doesn't detect the end of file.

If the file is empty, feof() works and the while never executes. But if the file has at least 1 Student registry, then it gets stuck in an infinite loop.

I understand that the feof() function need a previous read, and that it's that I have done. But it looks like when I write (updating Student), the end of file it moves away. That´s is what I don't understand. Why this occurs? If I'm overwriting the registry.


Solution

  • With C stdio functions, you have to be careful when you switch back and forth between reading from and writing to the same file. You need to call a file-positioning function at each switch, except that you may substitute an fflush() call when switching from writing to reading, and you don't need to do anything when switching to writing immediately after a read reports EOF. (C17 7.21.5.3/7)

    You do fseek() when switching from reading to writing, but in the event that you write, you fail to fflush() or reposition the file when switching from writing back to reading. An fflush() immediately after the fwrite() seems sensible, but even a nullary position-setting such as fseek(fileStudents, 0, SEEK_CUR); should do.