2015-10-08 5 views
2

Рассмотрим следующую простую программу, которая расщепляет вход на пробельных и печатает непробельных маркеры по одному в строке:Использование станд :: IStream :: часовому с станд :: IStream

#include <iostream> 
int main(int argc, char* argv[]) 
{ 
     while (std::cin) 
     { 
       std::string s; 
       std::cin >> s; 
       std::cout << "-" << s << "-\n"; 
     } 
     return 0; 
} 

это работает штраф - за исключением того, что, так как входной поток указывает только EOF после мы попытались прочитать из нее, когда она достигает конца входного потока (^D) он читает и выдает пустую строку:

[begin] 
< a b c 
> -a- 
> -b- 
> -c- 
< (^D) 
> -- 
[end] 

Мы может справиться с этим, сделав выходную строку условной на !s.empty().

Однако есть еще один вариант. Мы можем заменить строку:

while (std::cin) 

с:

while (std::istream::sentry(std::cin)) 

Караульного объект (который обычно используется внутри operator>>) имеет эффект потребляющих пробелов и затем проверки для EOF или другого потока гласит:

[begin] 
< a b c 
> -a- 
> -b- 
> -c- 
< (^D) 
[end] 

Мой вопрос состоит из трех частей:

  • Есть ли причина, почему эта конструкция не будет работать должным образом?
  • Является ли это уже идиоматическим?
  • Если нет, то почему бы и нет?
+1

Это изобретательный поворот в традиционном «почему мой цикл while (! Strm.eof()) не работает?» вопрос! Хотя, в конечном счете, ответ тот же. –

ответ

2

The std::istream::sentry предназначен для использования внутри входных функций. Правильное исправление вашей проблемы в всегда проверки, что поток хорошо, то есть чтение было успешным после чтения:

for (std::string s; std::cin >> s;) { 
    std::cout << '-' << s << "-\n"; 
} 

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

Подход, использующий sentry, обычно работает для строк, но может быть неудачным для типов, требующих какого-либо форматирования. Например, если вам нужно прочитать int, пропуская пробел с sentry, это не означает, что можно прочитать int. Даже с std::string s подход может завершиться неудачно: поток может обеспечить персонажа при первом доступе, но сбой при втором доступе. Первым доступом является fir, определяющее, что символ не является пространством от конструктора sentry, представленного неудачным чтением из строки.

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