No entanto, os programadores de C ++ observam que o que sempre acontece é que cin.eof () não retorna "true" até que a última linha tenha sido lida duas vezes.
Não é isso que está acontecendo. Ele eofbitnão desempenha nenhum papel na conversão para um booleano ( stream::operator bool(ou operator void*em c ++ mais antigo)). Somente o badbite failbitestã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 de iftestes. Você não está lendo até EOF. Você está lendo números. Portanto, faça seu código expressar essa lógica:
while (stream >> some_var) {
process_value(some_var);
}
Isso funcionará se a última linha do arquivo terminar com 0 42\nou apenas 0 42(nenhuma nova linha no final da última linha do arquivo). Se o arquivo terminar com 0 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ção process_valueé chamada com 42. A próxima chamada para o operador de extração de fluxo >> lê o EOF e, como nada foi extraído, ambos eofbite failbitserã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 isso eofbitque 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 que eofbitjá está definido. Isso resulta rapidamente na configuração de failbit.
Por que o primeiro trecho de código sempre falha ao funcionar corretamente?
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.