Различие между ошибкой и концом файла в цикле чтения

Идиоматический цикл для чтения из потока is

while (thestream >> value)
{
  // do something with value
}

Теперь у этого цикла есть одна проблема: он не распознает, завершился ли цикл. из-за конца файла или из-за ошибки. Например, возьмем следующую тестовую программу:

#include <iostream>
#include <sstream>

void readbools(std::istream& is)
{
  bool b;
  while (is >> b)
  {
    std::cout << (b ? "T" : "F");
  }
  std::cout << " - " << is.good() << is.eof() << is.fail() << is.bad() << "\n";
}

void testread(std::string s)
{
  std::istringstream is(s);
  is >> std::boolalpha;
  readbools(is);
}

int main()
{
  testread("true false");
  testread("true false tr");
}

Первый вызов testread содержит два допустимых логических значения и, следовательно, не является ошибкой. Второй вызов завершается третьим неполным логическим значением и, следовательно, является ошибкой. Тем не менее, поведение обоих одинаково. В первом случае чтение логического значения завершается неудачно, потому что его нет, а во втором случае происходит сбой, потому что оно является неполным, и в обоих случаях происходит попадание в EOF. Действительно, приведенная выше программа выводит дважды одну и ту же строку:

TF - 0110
TF - 0110

Чтобы решить эту проблему, я подумал о следующем решении:

while (thestream >> std::ws && !thestream.eof() && thestream >> value)
{
  // do something with value
}

Идея состоит в том, чтобы обнаружить обычный EOF, прежде чем фактически пытаться извлечь значение. Поскольку в конце файла может быть пробел (что не будет ошибкой, но приведет к тому, что чтение последнего элемента не попадет в EOF), я сначала отбрасываю все пробелы (что не может завершиться ошибкой), а затем проверяю EOF. Только если я не в конце файла, я пытаюсь прочитать значение.

В моем примере программы это действительно работает, и я получаю

TF - 0100
TF - 0110

Итак, в первом случае (правильный ввод) fail () возвращает false.

Теперь мой вопрос: гарантированно ли это решение будет работать, или мне просто (не) повезло, что оно дало желаемый результат? Также: есть ли более простой (или, если мое решение неверно, правильный) способ получить желаемый результат?

11
задан celtschk 11 November 2011 в 22:35
поделиться