Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 [ 189 ] 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

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

При чтении С-строк описанные здесь функции безопаснее оператора >>, поскольку они требуют явной передачи максимального размера читаемой строки. Хотя количество читаемых символов можно ограничить и при использовании оператора >> (см. с. 593), об этом часто забывают.

Вместо использования потоковых функций ввода часто удобнее работать с потоковым буфером напрямую. Функции потоковых буферов позволяют эффективно читать отдельные символы или последовательности символов без затрат на конструирование объектов sentry (см. с. 631). Интерфейс потоковых буферов более подробно рассматривается на с. 636. Также можно воспользоваться шаблонным классом istreambuf iterator, предоставляющим итераторный интерфейс к потоковому буферу (см. с. 638).

Функции tellgO и seekgQ предназначены для изменения текущей позиции чтения, в основном они используются при работе с файлами, поэтому их описание откладывается до с. 609.

Функции вывода

в следующих определениях ostream обозначает потоковый класс, используемый для записи. Это может быть класс ostream, wostream или любая другая специализация класса шаблона basic ostream. Параметр char обозначает соответствующий тип символов (char для ostream, wchar t для wostream). Другие типы и значения, выводимые курсивом. Зависят от определения типа символов или класса трактовок, связанного с потоком данных.

ostream ostream:-.put {char с)

О Записывает аргумент с в поток данных.

О Возвращает объект потока данных, по состоянию которого можно проверить, успешно ли выполнена запись.

ostream ostream::write (const char* str. streamsize count)

О Записывает count символов строки str в поток данных.

О Возвращает объект потока данных, по состоянию которого можно проверить, успешно ли выполнена запись.

О Символ завершения строки не останавливает запись и выводится вместе с остальными символами.

О Перед вызовом необходимо убедиться в том, что str содержит не менее count символов, иначе вызов приводит к непредсказуемым последствиям.

ostream ostream::f]ush О

Очищает потоковые буферы (принудительная запись всех буферизованйых данных на устройство или в канал ввода-вывода, с которым связан буфер).

Функции tellpO и seekpO предназначены для изменения текущей позиции записи. В основном они используются при работе с файлами, поэтому их описание откладывается до с. 609.



По аналогии с функциями ввода иногда бывает удобно работать с потоковым буфером напрямую или воспользоваться шаблонным классом ostreambufjterator для неформатированного вывода. Функции неформатированного вывода не дают особых преимуществ, если не считать того, что они могут обеспечивать синхронизацию в многопоточных средах с использованием объектов sentry. За дополнительной информацией обращайтесь к с. 655.

Пример использования

Классический фильтр, который просто выводит в выходной поток данных все прочитанные символы, выглядит на С++ так:

1o/charcatl.cpp #1nclude <iostreani> using namespace std:

int mainO {

char c;

Пока удается прочитать символ while (cin.get(c)) {

Вывести прочитанный символ в выходной поток

cout.put(c):

При каждом вызове cin.get(c) следующий символ присваивается переменной с, которая передается но ссылке. Функция get() возвращает объект потока данных; таким образом, условие while остается истинным до тех пор, пока поток данных находится в нормальном состоянии.

Чтобы повысить эффективность программы, можно работать напрямую с потоковыми буферами. На с. 641 приведена версия этого примера, в которой при вводе-выводе используются буферные итераторы, а в версии на с. 656 все входные данные копируются одной командой.

Манипуляторы

Потоковые манипуляторы упоминались на с. 561. Это объекты, которые при применении к ним стандартных операторов ввода-вывода изменяют поток дан-

В данном случае речь идет не об описываемых в этой главе потоках данных (streams), а о потоках выполнения (threads). - Примеч. перев.

Такой интерфейс лучше классического интерфейса фильтров в языке С. В С вам пришлось бы использовать функцию getchar() или getc(), которая возвращает как следующий символ, так и признак конца файла. В этом случае возвращаемое значение пришлось бы обрабатывать как тип iiit, чтобы отличить символ от признака конца файла.



ных. В табл. 13.8 перечислены основные манипуляторы, определенные в заголовочных файлах <istream> и <ostream>.

Таблица 13.8. Манипуляторы, определенные в заголовках <i5tream> и <05tream>

Манипулятор

Класс

Описание

flush

basic ostream

Принудителы1ый вывод выходного буфера на устройство

endl

basic ostream

Запись символа новой строки в буфер и принудительный вывод выходного буфера на устройство

ends

basic ostream

Запись символа завершения строки в буфер

basic istream

Чтение с игнорированием пропусков

Помимо перечисленных манипуляторов, существуют и другие, например, предназначенные для смены формата ввода-вывода. Они представлены на с. 589.

Принципы работы манипуляторов

Реализация манипуляторов основана на очень простом приеме, который не только упрощает управление потоками данных, но и наглядно демонстрирует мощь механизма перегрузки функций. Манипуляторы представляют собой обычные функции, передаваемые операторам ввода-вывода в аргументах. Оператор вызывает переданную функцию. Например, оператор вывода класса ostream перегружается примерно так:

ostreem ostream::operator « ( ostream i*op)iostream)) I

Вызов функции, передаваемой в параметре, с аргументом-потоком return (*op)(*this):

Аргумент ор представляет собой указатель на функцию. Точнее говоря, это функция, которая получает и возвращает поток данных ostream (предполагается, что возвращается тот же объект ostream, который был получен при вызове). Если второй операнд оператора << является такой функцией, то при ее вызове в аргументе передается первый операнд оператора <<.

На первый взгляд описание кажется очень сложным, но в действительности все относительно просто. Следующий пример поможет лучше разобраться в происходящем. Манипулятор (то есть функция) endl() для объекта ostream реализуется примерно так:

std::ostream& std::endl (std::ostreani& strm) {

Запись признака конца строки strm.put(\n):

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



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 [ 189 ] 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239