Однако программисты на C ++ отмечают, что всегда происходит то, что cin.eof () не возвращает «true» до тех пор, пока последняя строка не будет прочитана дважды.
Это не то, что происходит. Игра не eofbitиграет никакой роли в преобразовании в логическое значение ( stream::operator bool(или operator void*в более старом c ++)). Только badbitи failbitучаствуют.
Предположим, вы читаете файл, содержащий числа, разделенные пробелами. Цикл, основанный вокруг cin.eof(), неизбежно будет либо неправильным, либо переполненным ifтестами. Вы не читаете до EOF. Вы читаете цифры. Сделайте так, чтобы ваш код выражал эту логику:
while (stream >> some_var) {
process_value(some_var);
}
Это будет работать независимо от того, заканчивается ли последняя строка файла 0 42\nили 0 42нет (новой строки в конце последней строки в файле нет). Если файл заканчивается на 0 42\n, при последнем удачном прочтении будет получено значение 42 и будет считан последний маркер конца строки. Обратите внимание, что маркер EOF еще не прочитан. Функция process_valueвызывается с помощью 42. Следующий вызов оператора извлечения потока >> читает EOF, и, поскольку ничего не было извлечено, оба eofbitи failbitбудут установлены.
Предположим, с другой стороны, файл заканчивается на 0 42(без новой строки в конце последней строки). Последнее хорошее чтение извлечет значение 42, оканчивающееся на маркере EOF. Предположительно, вы хотите обработать это 42. Вот почему eofbitон не играет роли в операторе логического преобразования входного потока. При следующем вызове оператора извлечения потока >> базовый механизм быстро увидит, что eofbitон уже установлен. Это быстро приводит к настройке failbit.
Почему первый кусок кода всегда не работает должным образом?
Потому что вы не должны проверять EOF как условие цикла. Условие цикла должно выражать то, что вы пытаетесь сделать, например, извлечь числа из потока.