Correct use of end-of-file validation

When using the code

while(!feof(file))
{
    // Чтение из файла
}

In C or

while(!file.eof())
{
    // Чтение из файла
}

In C++, you get trouble - an extra read string, for example. Why? How do I correctly check that the end of the file has been reached?

Author: Harry, 2018-05-27

2 answers

The flag for reaching the end of the file is set only after an unsuccessful attempt to read past the end of the file. Therefore, if the loop body does not check whether the read from the file was successful , the last read will be exactly that failed read, which will indicate that the end of the file has been reached (and for you, this will look like, for example, the last line read again, if it was in the read buffer).

It is better to perform the read itself in the loop header while with by checking - for example, in a C program it might look like

while(fread(&data,sizeof(data),1,file)==1)
{
    // Обработка считанных данных
}

/* Или, скажем,
while(fgets(buf, bufsize, file)) { .... }
*/


if (feof(file)) // Достигнут конец файла
    puts("Ошибка чтения: достигнут конец файла");
else if (ferror(file)) {
    puts("Ошибка чтения файла");

Or in C++ - like

for(int n; file >> n; ) 
{
   // Обработка считанного значения n
}

if (file.bad())
    std::cout << "Ошибка ввода-вывода при чтении\n";
else if (file.eof())
    std::cout << "Достигнут конец файла\n";
else if (file.fail())
    std::cout << "Неверный формат данных\n";
 24
Author: Harry, 2021-01-28 10:01:24

Also, in addition to the eof flag, after reading the entire file, the fail flag can also be set, and if we want to set the cursor to the beginning of fin. seekg(0, fin.beg), then we will not read anything, because the fail flag is not reset. You can reset it using fin.clear(). The current state can be output fin. rdstate():

ifstream fin;
fin.open("E://1.txt", ios_base::in);
string str;

while(getline(fin, str)) {
    cout<< str<< " " << fin.rdstate() << endl ;
}

if (fin.bad())
    std::cout << "bad" << endl;
if (fin.eof())
    std::cout << "eof" << endl;
if (fin.fail())
    std::cout << "bad | fail" << endl;

fin.clear();
fin.seekg(0, fin.beg);

if (fin.bad())
    std::cout << "bad" << endl;
if (fin.eof())
    std::cout << "eof" << endl;
if (fin.fail())
    std::cout << "bad | fail" << endl;

while(getline(fin, str)) {
    cout<<str<< " " << fin.rdstate() << endl ;
}
 6
Author: magrif, 2018-08-11 23:31:05