C ++: проверка std :: istream для EOF без чтения / использования токенов / использования оператора >> - PullRequest
4 голосов
/ 24 апреля 2011

Я бы хотел проверить, достиг ли конец std::istream, не читая с него.

Я знаю, что могу проверить EOF следующим образом:

if (is >> something) 

но у этого есть ряд проблем. Представьте, что есть много, возможно, виртуальных, методов / функций, которые ожидают, что std::istream& передается в качестве аргумента Это означало бы, что я должен выполнить «домашнюю работу» по проверке EOF в каждом из них, возможно, с другим типом переменной something, или создать какую-то странную оболочку, которая будет обрабатывать сценарий вызова методов ввода.

Все, что мне нужно сделать, это:

if (!IsEof(is)) Input(is);

метод IsEof должен гарантировать, что поток не будет изменен для чтения, так что строка выше эквивалентна:

Input(is)

относительно данных, прочитанных в методе Input.

Если не существует общего решения, которое бы обозначало слово и std::istream, есть ли способ сделать это для std::ifstream или cin?

EDIT: Другими словами, следующее assert должно всегда проходить:

while (!IsEof(is)) {
  int something;
  assert(is >> something);
}

Ответы [ 5 ]

7 голосов
/ 24 апреля 2011

Класс istream имеет бит eof, который можно проверить с помощью члена is.eof().

Редактировать: Итак, вы хотите увидеть, является ли следующий символ маркером EOF, не удаляя его из потока? if (is.peek() == EOF) это, вероятно, то, что вы хотите тогда. См. Документацию для istream :: peek

4 голосов
/ 24 апреля 2011

Это невозможно.Как функция IsEof должна знать, что следующий элемент, который вы намереваетесь прочитать, это int?

Если следующее также не вызывает никаких утверждений?

 while(!IsEof(in))
 {
    int x;
    double y;
    if( rand() % 2 == 0 )
    {
       assert(in >> x);
    } else {
       assert(in >> y);
    }
 }

При этом выможно использовать метод exceptions, чтобы сохранить "домашнее хозяйство" в одном месте.

Вместо

   if(IsEof(is)) Input(is)

try

   is.exceptions( ifstream::eofbit /* | ifstream::failbit etc. if you like */ )
   try {
     Input(is);
   } catch(const ifstream::failure& ) {
   }

Это неостановить вас от чтения, пока не стало «слишком поздно», но это избавляет от необходимости иметь if (is >> x) if (is >> y) и т. д. во всех функциях.

0 голосов
/ 24 апреля 2011

Нет, в общем случае нет способа узнать, достигнет ли следующая операция чтения eof.

Если поток подключен к клавиатуре, условие EOF заключается в том, что я наберу Ctrl + Z / Ctrl + D при следующем запросе.Как IsEof обнаружит это?

0 голосов
/ 24 апреля 2011

Существуют веские причины, по которым нет функции isEof: ее трудно определить удобным для использования способом.Например, оператор >> обычно начинается с пропуска пробелов (в зависимости от флага), в то время как некоторые другие функции ввода могут читать пробелы.Как бы вы справились с ситуацией?Начать с пропуска пробелов или нет?Зависит ли это от флага, используемого оператором >> или нет?Восстановит ли это пробелы в потоке или нет?

Мой совет - использовать стандартную идиому и характеризовать ошибки ввода вместо того, чтобы пытаться предсказать только одну причину их: вам все равно нужно охарактеризовать и обработатьдр.

0 голосов
/ 24 апреля 2011

Обычно

if (std::is)
{ 
}

достаточно. Также есть .good (), .bad (), .fail () для более точной информации

Вот ссылка на справку: http://www.cplusplus.com/reference/iostream/istream/

...