Когда новичок начинает читать ifstreams, его / ее инстинкт должен прочитать файл, используя цикл, который обычно выглядит следующим образом:
while (!ifstream.eof()
{
...
}
Однако, когда я использовал этот код, я заметил, что он не остановился, пока не прочитал последнюю строку файла дважды. Программисты C ++ отмечают, что на самом деле это не то, как нужно читать файл. Вместо этого они обычно рекомендуют, чтобы тот, кто должен прочитать файл, использовал цикл, подобный этому:
while (ifstream >> someVar)
{
...
}
Почему первый кусок кода всегда не работает должным образом?
Ответы:
while (!ifstream.eof())
Цикл не работает, потому что потоки / файлы в C и C ++ не предсказать , когда вы достигли конца файла, а скорее указать , если вы пробовали читать мимо конца файла.Если последняя строка файла заканчивается символом newline (
\n
), то большинство действий чтения прекратят чтение, когда встретят этот символ, и не обнаружат, что это последний символ в файле. При следующем действии чтения может даже случиться так, что будет добавлено больше символов и что чтение сможет их извлечь.Цикл с использованием оператора извлечения потока (
while (ifstream >> someVar)
) работает, потому что результат от оператора извлечения потока оценивается как ложный, если он не может извлечь элемент правильного типа. Это также происходит, если не осталось символов для чтения.источник
Это не то, что происходит. Игра не
eofbit
играет никакой роли в преобразовании в логическое значение (stream::operator bool
(илиoperator void*
в более старом c ++)). Толькоbadbit
иfailbit
участвуют.Предположим, вы читаете файл, содержащий числа, разделенные пробелами. Цикл, основанный вокруг
cin.eof()
, неизбежно будет либо неправильным, либо переполненнымif
тестами. Вы не читаете до EOF. Вы читаете цифры. Сделайте так, чтобы ваш код выражал эту логику:Это будет работать независимо от того, заканчивается ли последняя строка файла
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 как условие цикла. Условие цикла должно выражать то, что вы пытаетесь сделать, например, извлечь числа из потока.
источник