2012-01-06 2 views
2

Я только что столкнулся с любопытной ситуацией на C++. Я делал что-то вроде:istream :: peek любопытное поведение wrt. EOF

istream in; 
// ... 
in.get();  // get a char (which turns out to be the last) 
       // curiously ios::eof bit doesn't get set just yet 

c = in.peek(); // attempt to peek, return EOF and now set ios::eof bit 

if(c == EOF) { 
    // realize shouldn't have gotten the last char for some reason 
    in.unget(): // attempt to unget, *fails* (because ios:eof bit was set) 
} 

Теперь мне любопытно, почему peek устанавливает бит eof; Я нахожу это очень неинтуитивным. Предполагается, что он просто заглянет, но на самом деле ничего не потребляет и не должен менять состояние потока. Кроме того, почему unget впоследствии не работает? Является ли стандарт обязательным для всех операций, когда good() является ложным или что-то еще?

ответ

4
in.get();  // get a char (which turns out to be the last) 
       // curiously ios::eof bit doesn't get set just yet 

Это не "любопытный". Биты EOF потока устанавливаются, когда считывание завершается с ошибкой из-за того, что достигнуто eof; это не означает «последнее чтение взяло нас на eof».

c = in.peek(); // attempt to peek, return EOF and now set ios::eof bit 

Как сейчас.

Кроме того, почему unget впоследствии не работает? Является ли стандарт обязательным для всех операций, когда good() является ложным или что-то еще?

... это то, что происходит. Вы не смогли иначе определить, что «не работает».

Вы должны очистить состояние потока, в себя, когда был достигнут конец файла, если вы хотите unget этот символ вы извлекаться на линии 3.

istream in; 
// ... 
in.get();  // assume this succeeds (*) 

c = in.peek(); // assume this fails and sets EOF bit 

if (!in) { 
    in.clear(); // clear stream error state for use 
    in.unget(); // "put back" that character (*) 
} 
else { 
    // next char from .get() will be equal to `c` 
} 
+0

Ваш ответ рода запутанным и неясным для меня. Похоже, что я (ошибочно) предположил, что бит eof был признаком того, что текущее положение потока было * в конце *. Ваш код не очистит только бит eof. Кроме того, на основании чего вы говорите, что 'unget' не имеет смысла после' peek', который возвращает 'EOF'? –

+0

@GiovanniFunchal: Мне жаль, что ты так себя чувствуешь. Если ваш 'peek' не смог получить символ из потока (потому что его больше не было), тогда как имеет смысл выполнять' unget'? Нечего забывать; вам не удалось получить символ из потока. А что касается вашего комментария о очистке состояния потока ... Я понятия не имею, почему это было бы проблемой для вас. –

+3

Флаг eof() указывает, что поток попытался прочесть последний символ. Прежде чем пытаться прочитать прошлый символ, поток не знает, что он был последним. Этот флаг хорош только для обнаружения ошибок чтения: вы не хотите сообщать об ошибке из-за того, что вы использовали весь файл. –

Смежные вопросы