Идиоматический цикл для чтения из потока 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.
Теперь мой вопрос: гарантированно ли это решение будет работать, или мне просто (не) повезло, что оно дало желаемый результат? Также: есть ли более простой (или, если мое решение неверно, правильный) способ получить желаемый результат?