Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КРАТКИЙ ОБЗОР С.doc
Скачиваний:
1
Добавлен:
26.10.2018
Размер:
2.11 Mб
Скачать

10.3.2 Состояния потока

С каждым потоком (istream или ostream) связано определенное состояние. Нестандартные ситуации и ошибки обрабатываются с помощью проверки и установки состояния подходящим образом. Узнать состояние потока можно с помощью операций над классом ios:       class ios { //ios является базовым для ostream и istream       //...       public:       int eof() const; // дошли до конца файла       int fail() const; // следующая операция будет неудачна       int bad() const; // поток испорчен       int good() const; // следующая операция будет успешной       //...       }; Последняя операция ввода считается успешной, если состояние задается good() или eof(). Если состояние задается good(), то последующая операция ввода может быть успешной, в противном случае она будет неудачной. Применение операции ввода к потоку в состоянии, задаваемом не good(), считается пустой операцией. Если произошла неудача при попытке чтения в переменную v, то значение v не изменилось (оно не изменится, если v имеет тип, управляемый функциями члена из istream или ostream). Различие между состояниями, задаваемыми как fail() или как bad() уловить трудно, и оно имеет смысл только для разработчиков операций ввода. Если состояние есть fail(), то считается, что поток не поврежден, и никакие символы не пропали; о состоянии bad() ничего сказать нельзя.       Значения, обозначающие эти состояния, определены в классе ios:       class ios {       //...       public:       enum io_state {       goodbit=0,       eofbit=1,       filebit=2,       badbit=4,       };       //...       }; Истинные значения состояний зависят от реализации, и указанные значения приведены только, чтобы избежать синтаксически неправильных конструкций.       Проверять состояние потока можно следующим образом:       switch (cin.rdstate()) {       case ios::goodbit:       // последняя операция с cin была успешной       break;       case ios::eofbit:       // в конце файла       break;       case ios::filebit:       // некоторый анализ ошибки       // возможно неплохой       break;       case ios::badbit:       // cin возможно испорчен       break;       } В более ранних реализациях для значений состояний использовались глобальные имена. Это приводило к нежелательному засорению пространства именования, поэтому новые имена доступны только в пределах класса ios. Если вам необходимо использовать старые имена в сочетании с новой библиотекой, можно воспользоваться следующими определениями:       const int _good = ios::goodbit;       const int _bad = ios::badbit;       const int _file = ios::filebit;       const int _eof = ios::eofbit;       typedef ios::io_state state_value ; Разработчики библиотек должны заботится о том, чтобы не добавлять новых имен к глобальному пространству именования. Если элементы перечисления входят в общий интерфейс библиотеки, они всегда должны использоваться в классе с префиксами, например, как ios::goodbit и ios::io_state.       Для переменной любого типа, для которого определены операции << и >>, цикл копирования записывается следующим образом:       while (cin>>z) cout << z << '\n'; Если поток появляется в условии, то проверяется состояние потока, и условие выполняется (т.е. результат его не 0) только для состояния good(). Как раз в приведенном выше цикле проверяется состояние потока istream, что является результатом операции cin>>z. Чтобы узнать, почему произошла неудача в цикле или условии, надо проверить состояние. Такая проверка для потока реализуется с помощью операции приведения (7.3.2).       Так, если z является символьным вектором, то в приведенном цикле читается стандартный ввод и выдается для каждой строки стандартного вывода по одному слову (т.е. последовательности символов, не являющихся обобщенными пробелами). Если z имеет тип complex, то в этом цикле с помощью операций, определенных в 10.2.2 и 10.2.3, будут копироваться комплексные числа. Шаблонную функцию копирования для потоков со значениями произвольного типа можно написать следующим образом:       complex z;       iocopy(z,cin,cout); // копирование complex       double d;       iocopy(d,cin,cout); // копирование double       char c;       iocopy(c,cin,cout); // копирование char       Поскольку надоедает проверять на корректность каждую операцию ввода- вывода, то распространенным источником ошибок являются именно те места в программе, где такой контроль существенен. Обычно операции вывода не проверяют, но иногда они могут завершиться неудачно. Потоковый ввод- вывод разрабатывался из того принципа, чтобы сделать исключительные ситуации легкодоступными, и тем самым упростить обработку ошибок в процессе ввода-вывода.