Программирование >>  Поддержка объектно-ориентированного программирования 

1 ... 82 83 84 [ 85 ] 86 87 88 ... 120


ostream). Различие между состояниями, задаваемыми как fail() или как bad() уловить трудно, и оно имеет смысл только для разработчиков операций ввода. Если состояние есть fail(), то считается, что поток не поврежден, и никакие символы не пропали; о состоянии bad() ничего сказать нельзя.

Значения, обозначающие эти состояния, определены в классе ios:

class ios {

...

public:

enum io state { goodbit=0, eofbit=1, filebit=2, badbit=4,

...

Истинные значения состояний зависят от реализации, и указанные значения приведены только, чтобы избежать синтаксически неправильных конструкций.

Проверять состояние потока можно следующим образом:

switch (cin.rdstateO) { 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

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

10.3.3 Ввод пользовательских типов

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

istream& operator>>(istream& s, complex& a)

формат input рассчитан на complex; f обозначает float: f

( f )

( f , f )

double re = 0, im = 0; char c = 0; s >> c;

if (c == () { s >> re >> c;

if (c == ,) s >> im >> c;

if (c != )) s.clear(ios::badbit); установим состояние

else {

s.putback(c); s >> re;

if (s) a = complex(re,im); return s;

Несмотря на сжатость кода, обрабатывающего ошибки, на самом деле учитывается большая часть ошибок. Инициализация локальной переменной с нужна для того, чтобы в нее не попало случайное значение, например (, в случае неудачной операции. Последняя проверка состояния потока гарантирует, что параметр a получит значение только при успешном вводе.

Операция, устанавливающая состояние потока, названа clear() (здесь clear - ясный, правильный), поскольку чаще всего она используется для восстановления состояния потока как good(); значением по умолчанию для параметра ios::clear() является ios::goodbit.



10.4 Форматирование

Все примеры из 1 0.2 содержали неформатированный вывод, который являлся преобразованием объекта в последовательность символов, задаваемую стандартными правилами, длина которой также определяется этими правилами. Часто программистам требуются более развитые возможности. Так, возникает потребность контролировать размер памяти, необходимой для операции вывода, и формат, используемый для выдачи чисел. Точно так же допустимо управление некоторыми аспектами ввода.

10.4.1 Класс ios

Большинство средств управления вводом-выводом сосредоточены в классе ios, который является базовым для ostream и istream. По сути здесь находится управление связью между istream или ostream и буфером, используемым для операций ввода-вывода. Именно класс ios контролирует: как символы попадают в буфер и как они выбираются оттуда. Так, в классе ios есть член, содержащий информацию об используемой при чтении или записи целых чисел системы счисления (десятичная, восьмеричная или шестнадцатеричная), о точности вещественных чисел и т.п., а также функции для проверки и установки значений переменных, управляющих потоком.

class ios {

...

public:

ostream* tie(ostream* s); связать input и output

ostream* tie(); возвратить tie

int width(int w); установить поле width

int width() const;

char fill(char); установить символ заполнения

char fill() const; вернуть символ заполнения

long flags(long f); long flags() const;

long setf(long setbits, long field); long setf(long); long unsetf(long);

int precision(int); установить точность для float

int precision() const;

int rdstate(); const; состояния потоков, см. $$10.3.2

int eof() const; int fail() const; int bad() const; int good() const; void clear(int i=0); ...

В 1 0.3.2 описаны функции, работающие с состоянием потока, остальные приведены ниже.

10.4.1.1 Связывание потоков

Функция tie() может установить и разорвать связь между ostream и istream. Рассмотрим пример:

main()

String s;

cout << Password: ; cin >> s; ...

Как можно гарантировать, что приглашение Password: появится на экране прежде, чем выполниться операция чтения? Вывод в cout и ввод из cin буферизуются, причем независимо, поэтому Password: появится только по завершении программы, когда закроется буфер вывода.



1 ... 82 83 84 [ 85 ] 86 87 88 ... 120

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика