Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Cpp_Страуструп.doc
Скачиваний:
16
Добавлен:
03.05.2015
Размер:
3.2 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

Поскольку надоедает проверять на корректность каждую операцию ввода-

вывода, то распространенным источником ошибок являются именно те места в

программе, где такой контроль существенен. Обычно операции вывода не

проверяют, но иногда они могут завершиться неудачно. Потоковый ввод-

вывод разрабатывался из того принципа, чтобы сделать исключительные

ситуации легкодоступными, и тем самым упростить обработку ошибок

в процессе ввода-вывода.