Программирование. Принципы и практика использования C++ Исправленное издание, стр. 429

Программирование. Принципы и практика использования C++ Исправленное издание - _410.png

Объект класса

istream
преобразовывает поток символов (байтов) в объекты, имеющие тип.

Программирование. Принципы и практика использования C++ Исправленное издание - _411.png

Объект класса

iostream
— это поток, который может действовать и как объект класса
istream
, и как объект класса
ostream
. Буфера, изображенные на диаграмме, являются потоковыми буферами (
streambuf
). Если читателям потребуется перейти от потоков класса
iostream
к новым видам устройств, файлов или памяти, они смогут найти их описание в профессиональных учебниках.

Существуют три стандартных потока.

Программирование. Принципы и практика использования C++ Исправленное издание - _412.png

Б.7.1. Иерархия потоков ввода-вывода

Поток

istream
можно связать с устройством ввода (например, клавиатурой), файлом или объектом класса
string
. Аналогично поток
ostream
можно связать с устройством вывода (например, текстовым окном), файлом или объектом класса
string
. Потоки ввода-вывода образуют иерархию классов.

Программирование. Принципы и практика использования C++ Исправленное издание - _413.png

Поток можно открыть либо с помощью конструктора, либо вызова функции

open()
.

Программирование. Принципы и практика использования C++ Исправленное издание - _414.png

Для файловых потоков имя файлов представляет собой строку в стиле языка С.

Открыть файл можно в одном из режимов, приведенных ниже.

Программирование. Принципы и практика использования C++ Исправленное издание - _415.png

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

good()
. Рассмотрим пример.

void my_code(ostream& os); // функция my_code может использовать

                           // любой поток вывода

ostringstream os;          // буква "o" означает "для вывода"

ofstream of("my_file");

if (!of) error("невозможно открыть 'my_file' для записи");

my_code(os); // используется объект класса string

my_code(of); // используется файл

См. раздел 11.3.

Б.7.2. Обработка ошибок

Поток

iostream
может пребывать в одном из четырех состояний.

Программирование. Принципы и практика использования C++ Исправленное издание - _416.png

Используя функцию

s.exceptions()
, программист может потребовать, чтобы поток
iostream
сгенерировал исключение, если из состояния
good()
он перешел в другое состояние (см. раздел 10.6).

Любая операция, в результате которой поток не находится в состоянии

good()
, не имеет никакого эффекта; такая ситуация называется “no op”.

Объект класса

iostream
можно использовать как условие. В данном случае условие является истинным (успех), если поток
iostream
находится в состоянии
good()
. Это обстоятельство стало основой для распространенной идиомы, предназначенной для считывания потока значений.

X x; // "буфер ввода" для хранения одного значения типа X

while (cin>>x) {

  // какие-то действия с объектом x

}

// мы окажемся в этой точке, если оператор >> не сможет прочитать

// очередной объект класса X из потока cin

Б.7.3. Операции ввода

Почти все операции ввода описаны в заголовке

<istream>
, за исключением операций ввода в объект класса
string
; эти операции описаны в заголовке
<string>
:

Программирование. Принципы и практика использования C++ Исправленное издание - _417.png

Если не указано иное, операция ввода возвращает ссылку на объект класса

istream
, поэтому можно создавать цепочки таких операций, например
cin>>x>>y
;.

Программирование. Принципы и практика использования C++ Исправленное издание - _418.png

Функции

get()
и
getline()
помещают после символов, записанных в ячейки
p[0]
и т.д., число
0
(если символы были введены); функция
getline()
удаляет признак конца ввода (
t
из потока ввода, если он обнаружен, а функция
get()
этого не делает. Функция
read(p,n)
не записывает число
0
в массив после считанных символов. Очевидно, что операторы форматированного ввода проще в использовании и менее уязвимы для ошибок, чем операции неформатированного ввода.

Б.7.4. Операции вывода

Почти все операции вывода описаны в заголовке

<ostream>
, за исключением операции записи в объекты класса
string
; такие операции описаны в заголовке
<string>
.

Программирование. Принципы и практика использования C++ Исправленное издание - _419.png

Если не указано иное, операции вставки в поток

ostream
возвращают ссылку на его объекты, поэтому можно создавать цепочки операций вывода, например
cout << x<<y
;.

Б.7.5. Форматирование

Формат потока ввода-вывода управляется комбинацией типа объекта, состояния потока, информацией о локализации (см. раздел

<locale>
) и явными операциями. Большая часть информации об этом изложена в главах 10-11. Здесь мы просто перечислим стандартные манипуляторы (операции, модифицирующие поток), поскольку они обеспечивают наиболее простой способ изменения формата.