Jaki jest prawdziwy powód, aby nie używać bitu EOF jako warunku ekstrakcji strumienia?

Zainspirowany moimpoprzednie pytanie

Powszechnym błędem dla nowych programistów C ++ jest czytanie z pliku z czymś w rodzaju:

std::ifstream file("foo.txt");
std::string line;
while (!file.eof()) {
  file >> line;
  // Do something with line
}

Często zgłaszają, że ostatni wiersz pliku został odczytany dwukrotnie. Powszechne wyjaśnienie tego problemu (jeden, który podałem wcześniej) wygląda następująco:

Ekstrakcja ustawi tylko bit EOF w strumieniu, jeśli spróbujesz wyodrębnić koniec pliku, a nie jeśli ekstrakcja zatrzyma się tylko na końcu pliku.file.eof() powie tylko, czy poprzedni odczyt trafił na koniec pliku, a nie jeśli następny. Po wyodrębnieniu ostatniej linii bit EOF nadal nie jest ustawiony i iteracja występuje jeszcze raz. Jednak w tej ostatniej iteracji ekstrakcja kończy się niepowodzeniem iline nadal ma tę samą zawartość, co poprzednio, tj. ostatnia linia jest zduplikowana.

Jednak pierwsze zdanie tego wyjaśnienia jest błędne, więc wyjaśnienie tego, co robi kod, jest również błędne.

Definicja sformatowanych funkcji wejściowych (któreoperator>>(std::string&) is) definiuje ekstrakcję jako użycierdbuf()->sbumpc() lubrdbuf()->sgetc() aby uzyskać znaki wejściowe. Stwierdza, że ​​jeśli jedna z tych funkcji powrócitraits::eof(), a następnie ustawiany jest bit EOF:

Jeślirdbuf()->sbumpc() lubrdbuf()->sgetc() zwracatraits::eof(), następnie funkcja wejściowa, z wyjątkiem przypadków, w których wyraźnie zaznaczono inaczej, kończy swoje działania i robisetstate(eofbit), który może rzucićios_base::failure (27.5.5.4), przed powrotem.

Widzimy to za pomocą prostego przykładu, który używa astd::stringstream zamiast pliku (oba są strumieniami wejściowymi i zachowują się tak samo podczas wyodrębniania):

int main(int argc, const char* argv[])
{
  std::stringstream ss("hello");
  std::string result;
  ss >> result;
  std::cout << ss.eof() << std::endl; // Outputs 1
  return 0;
}

Jasne jest, że uzyskuje się pojedyncze wydobyciehello od sznurkai ustawia bit EOF na 1.

Więc co jest nie tak z wyjaśnieniem? Co różni się od plików, które powodują!file.eof() aby powtórzyć ostatnią linię? Jaki jest prawdziwy powód, dla którego nie powinniśmy używać!file.eof() jako nasz warunek ekstrakcji?

questionAnswers(2)

yourAnswerToTheQuestion