Нижняя строка: при правильной обработке белого пространства, как eof
можно использовать (и даже более надежно, чем eof()
для проверки ошибок):
eof()
( Спасибо Tony D за предложение выделить ответ. См. Его комментарий ниже, чтобы привести пример, почему это более надежное. )
Главный аргумент против использования, похоже, не содержит важной тонкости в отношении роли белого пространства. Мое предложение состоит в том, что проверка явно не только не всегда « всегда ошибочна », что, по-видимому, является преобладающим мнением в этой и подобных потоках SO, но при правильном обращении с белым пространством оно обеспечивает более чистую и надежную обработка ошибок и всегда правильное решение (хотя и не обязательно tersest).int data; while(in >> data) { /* ... */ } // which is equivalent to while( !(in >> data).fail() ) { /* ... */ }
1 2 3 4 5<eof>
Подводя итог тому, что предлагается в качестве «правильного» завершения и порядка чтения, является следующее:
1 2 a 3 4 5<eof>
Неисправность из-за попытки чтения за пределами eof принимается за условие завершения. Это означает, что нет простого способа отличить успешный поток и тот, который действительно терпит неудачу по другим причинам, кроме eof. Возьмите следующие потоки:
a<eof>
while(in>>data)
failbit
eofbit
заканчивается набором для всех трех входных данных. В первом и третьем также задано. Таким образом, за циклом нужна очень уродливая дополнительная логика, чтобы отличить правильный вход (1-й) от неправильных (2-й и 3-й).while( !in.eof() ) { int data; in >> data; if ( in.fail() ) /* handle with break or throw */; // now use data }
in.fail()
Принимая во внимание следующее:
eof()
Здесь проверяется, что до тех пор, пока есть что прочитать, он правильный. Цель - не просто терминатор цикла.while( !in.eof() ) { int data; in >> data >> ws; // eat whitespace with std::ws if ( in.fail() ) /* handle with break or throw */; // now use data }
До сих пор так хорошо, но что происходит, если в потоке есть конечное пространство - что звучит как главная проблема против std::ws
терминатора?
Нам не нужно сдавать нашу обработку ошибок; просто съешьте пустое пространство:
eofbit
failbit
пропускает любое потенциальное (ноль или более) конечное пространство в потоке при установке in.fail()
, а неwhile( !(in>>ws).eof() ) { int data; in >> data; if ( in.fail() ) /* handle with break or throw */; /* this will never fire if the eof is reached cleanly */ // now use data }
. Таким образом, while(!eof)
работает, как ожидалось, пока есть хотя бы одна информация для чтения. Если все пустые потоки также приемлемы, то правильная форма:
while(!fail)
Резюме. Правильно построенная while(stream >> n)
не только возможна, но и ошибочна, но позволяет локализовать данные в пределах области действия и обеспечивает более четкое разделение проверки ошибок от бизнеса, как обычно. Это, как говорится, является, несомненно, более распространенным и кратким идиомом, и может быть предпочтительным в простых (единичных данных для типа чтения).while(!stream.eof()) { stream >> n; //some work on n; }