Quando um iniciante começa a ler os fluxos de if, seu instinto é ler o arquivo usando um loop que geralmente se parece com isso:
while (!ifstream.eof()
{
...
}
No entanto, quando usei esse código, notei que ele não parava até ter lido a última linha do arquivo duas vezes. Os programadores de C ++ observam que não é assim que se deve ler um arquivo. Em vez disso, eles geralmente recomendam que quem precisa ler um arquivo use um loop como este:
while (ifstream >> someVar)
{
...
}
Por que o primeiro trecho de código sempre falha ao funcionar corretamente?
Respostas:
o
while (!ifstream.eof())
loop não funciona, porque os fluxos / arquivos em C e C ++ não prevêem quando você atingiu o final do arquivo, mas indicam se você tentou ler além do final do arquivo.Se a última linha do arquivo terminar com um
\n
caractere newline ( ), a maioria das ações de leitura interromperá a leitura quando o encontrarem e não detectarem que esse é o último caractere do arquivo. Na próxima ação de leitura, pode até ser que mais caracteres tenham sido anexados e que a leitura tenha sucesso em extraí-los.O loop que usa o operador de extração de fluxo (
while (ifstream >> someVar)
) funciona porque o resultado do operador de extração de fluxo foi avaliado como falso se não pudesse extrair um item do tipo certo. Isso também acontece se não houver caracteres para ler.fonte
Não é isso que está acontecendo. Ele
eofbit
não desempenha nenhum papel na conversão para um booleano (stream::operator bool
(ouoperator void*
em c ++ mais antigo)). Somente obadbit
efailbit
estão envolvidos.Suponha que você esteja lendo um arquivo contendo números separados por espaços em branco. Um loop baseado
cin.eof()
inevitavelmente estará errado ou cheio deif
testes. Você não está lendo até EOF. Você está lendo números. Portanto, faça seu código expressar essa lógica:Isso funcionará se a última linha do arquivo terminar com
0 42\n
ou apenas0 42
(nenhuma nova linha no final da última linha do arquivo). Se o arquivo terminar com0 42\n
, a última boa leitura recuperará o valor 42 e lerá o marcador final de linha final. Observe que o marcador EOF ainda não foi lido. A funçãoprocess_value
é chamada com42
. A próxima chamada para o operador de extração de fluxo >> lê o EOF e, como nada foi extraído, amboseofbit
efailbit
serão definidos.Suponha, por outro lado, que o arquivo termine com
0 42
(nenhuma nova linha no final da última linha). A última boa leitura recuperará o valor 42 terminando no marcador EOF. Presumivelmente, você deseja processar esses 42. É por issoeofbit
que não desempenha um papel no operador de conversão booleana do fluxo de entrada. Na próxima chamada para o operador de extração de fluxo >>, o mecanismo subjacente vê rapidamente queeofbit
já está definido. Isso resulta rapidamente na configuração defailbit
.Porque você não deve verificar EOF como a condição do loop. A condição do loop deve expressar o que você está tentando fazer, que é (por exemplo), extrair números de um fluxo.
fonte