#c #filestream #iostream #eof
#c #поток файлов #iostream #eof
Вопрос:
Я хотел бы проверить, достигло ли std::istream
конца без чтения из него.
Я знаю, что могу проверить EOF следующим образом:
if (is >> something)
но у этого есть ряд проблем. Представьте, что существует множество, возможно виртуальных, методов / функций, которые ожидают std::istreamamp;
передачи в качестве аргумента.
Это означало бы, что я должен выполнять «домашнюю работу» по проверке EOF в каждом из них, возможно, с другим типом something
переменной, или создать какую-нибудь странную оболочку, которая обрабатывала бы сценарий вызова методов ввода.
Все, что мне нужно сделать, это:
if (!IsEof(is)) Input(is);
метод IsEof
должен гарантировать, что поток не изменен для чтения, так что приведенная выше строка эквивалентна:
Input(is)
что касается данных, считанных в Input
методе.
Если нет универсального решения, которое обозначало бы and std::istream
, есть ли какой-либо способ сделать это для std::ifstream
or cin
?
РЕДАКТИРОВАТЬ: Другими словами, всегда должно выполняться следующее assert
:
while (!IsEof(is)) {
int something;
assert(is >> something);
}
Комментарии:
1. Перечитывая вопрос, я не уверен, что понял с первого раза. Вы действительно имеете в виду
if (IsEof(is)) Input(is)
или там должно быть логическое «НЕ»?2. Логично, что нет. Но что важно, мне нужна проверка без предварительного использования каких-либо токенов (см. Редактирование выше), и вам все будет ясно.
3. После редактирования это утверждение очень сильное. В нем указано, что
IsEof
должен возвращать false только в том случае,int
если форматированное извлечение из, будет успешным. Вы уверены, что это то, что вы имеете в виду? Если это так, вы не можете сделать это с rawistream
; вам понадобится какой-то структурированный кэш, чтобы вы могли прочитать и кэшировать следующий int. В качестве альтернативы вам понадобится способ вернуть все символы, прочитанные при синтаксическом анализеint
иstd::istream
не гарантирует, что это всегда будет возможно.4. Это
int
всего лишь пример, я бы хотел, чтобы это работало независимо от того, какой следующий токен, всякий раз, когда достигается EOF. Да, я ищу функцию, которая сообщала бы мне, достиг ли я позиции после последнего токена в потоке (т. Е. EOF), не пытаясь прочитать следующий токен или, по крайней мере, прочитать его заранее и поместить обратно. Возможно ли это?5. Просто для пояснения, что именно вы подразумеваете под «токеном»? Если вы говорите о произвольно сложных типах, то — предположительно — следующий «токен» может состоять из произвольно большого количества символов, и вам придется попытаться подделать чтение всего объекта. Если это чтение завершится неудачей, вам придется сохранить все, что было прочитано, в кэше (возможно, структурированном, возможно, нет), потому что вы не сможете — в общем — перенести все это обратно в простой
istream
.
Ответ №1:
Класс istream имеет бит eof, который можно проверить с помощью is.eof()
члена.
Редактировать: Итак, вы хотите посмотреть, является ли следующий символ маркером EOF, не удаляя его из потока? if (is.peek() == EOF)
вероятно, это то, что вы хотите тогда. Смотрите документацию для istream::peek
Комментарии:
1. Это работает не так, как ожидалось, что-то должно быть прочитано сначала , чтобы eof() заработал. Рассмотрим следующий код: while (IsEof(is)) { int something; assert(is >> что-то); }
Ответ №2:
Это невозможно. Как 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)
попробуйте
is.exceptions( ifstream::eofbit /* | ifstream::failbit etc. if you like */ )
try {
Input(is);
} catch(const ifstream::failureamp; ) {
}
Это не мешает вам читать, пока не стало «слишком поздно», но это устраняет необходимость иметь if (is >> x), if (is >> y) и т.д. во всех функциях.
Ответ №3:
Обычно,
if (std::is)
{
}
этого достаточно. Для получения более точной информации также есть .good(), .bad(), .fail()
Вот справочная ссылка:http://www.cplusplus.com/reference/iostream/istream /
Ответ №4:
Есть веские причины, по которым отсутствует функция isEof: ее трудно указать удобным способом. Например, operator>> обычно начинается с пропуска пробелов (в зависимости от флага), в то время как некоторые другие функции ввода способны считывать пробелы. Как бы вы isEof () справились с ситуацией? Начинать с пропуска пробелов или нет? Будет ли это зависеть от флага, используемого operator>> или нет? Восстановит ли это пробелы в потоке или нет?
Мой совет — используйте стандартную идиому и характеризуйте сбой ввода вместо того, чтобы пытаться предсказать только одну их причину: вам все равно нужно будет охарактеризовать и обработать остальные.
Ответ №5:
Нет, в общем случае нет способа узнать, достигнет ли eof следующая операция чтения.
Если поток подключен к клавиатуре, условием EOF является то, что я наберу Ctrl Z / Ctrl D в следующем приглашении. Как бы IsEof (is) обнаружил это?
Комментарии:
1. @leden — Нет, у них одинаковый интерфейс. Это всего лишь причина, по которой это работает так, как работает.