Однако программисты на 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 как условие цикла. Условие цикла должно выражать то, что вы пытаетесь сделать, например, извлечь числа из потока.