Правильное использование проверки конца файла

132
22 июня 2019, 07:30

При использовании кода

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

в C или

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

в C++ получаются неприятности - лишняя считанная строка, например. Почему? Как правильно проверить, что достигнут конец файла?

Answer 1

Признак достижения конца файла выставляется только после неудачной попытки чтения за его концом. Поэтому, если в теле цикла нет проверки, успешно ли выполнено чтение из файла - последнее чтение окажется именно тем неудачным чтением, которое выставит признак достигнутого конца файла (а для вас это будет выглядеть как, например, еще раз считанная последняя строка, если она находилась в буфере для чтения).

Лучше в заголовке цикла while выполнять само чтение с проверкой - например, в программе на C это могло бы выглядеть как

while(fread(&data,sizeof(data),1,file)==1)
{
    // Обработка считанных данных
}
if (feof(file)) // Достигнут конец файла
    puts("Ошибка чтения: достигнут конец файла");
else if (ferror(file)) {
    puts("Ошибка чтения файла");

или на C++ - наподобие

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";
Answer 2

Также помимо флага eof после чтения всего файла может также выставиться флаг fail, и если мы захотим установить курсор на начало fin.seekg(0, fin.beg), то ничего не прочитаем, т.к. флаг fail не сброшен. Сбросить можно с помощью fin.clear(). Текущее состояние можно вывести 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 ;
}
READ ALSO
Явный вызов конструктора по умолчанию [закрыт]

Явный вызов конструктора по умолчанию [закрыт]

Что это такое? Может ли кто-нибудь привести пример? Решение через указатель не подходит

112
Ошибка с массивом error: invalid conversion from &#39;int&#39; to &#39;int*&#39;

Ошибка с массивом error: invalid conversion from 'int' to 'int*'

Ошибку ловлю на строке 'int *mass1= ArrayGenerate(raz);':

126
Не правильно работает структура

Не правильно работает структура

У меня есть класс, но программа вылетает после создания объекта его типа

119