Анимация
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

) НЕ ЗАКРЫВАЕТ буфер int mainO

using namespace std; int num - 5;

cout « "We print " « num

« " lines hexadecimal" « endl:

hexMulti pli cati опТаЫ e(cout,rdbuf().num):

cout « "That was the output of " « num « " hexadecimal lines " « endl;

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

We print 5 lines hexadecimally

0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 Oxa

0x2 0x4 0x6 0x8 Oxa Oxc Oxe 0x12 0x14

0x3 0x6 0x9 Oxc Oxf Ox 12 0x15 0x18 Oxlb Oxle

0x4 0x8 Oxc 0x10 0x14 0x18 Oxlc 0x20 0x24 0x28

0x5 Oxa Oxf 0x14 0x19 Oxle 0x23 0x28 0x2d 0x32

That was the output of 5 hexadecimal lines

Впрочем, наряду с достоинствами имеется и недостаток - конструирование и уничтожение объекта потока данных обходится дороже, чем простая установка и восстановление форматных флагов. Также следует помнить, что уничтожение объекта потока данных не приводит к очистке буфера. Очищать выходной буфер необходимо «вручную»-.

Замечание о том, что потоковый буфер не уничтожается, относится только к классам basicjstream и basic ostream. Другие потоковые классы уничтожают буферы, созданные ими же, но оставляют буферы, назначенные функцией rdbuf() (см. далее).

Перенаправление стандартных потоков данных

В старых реализациях библиотеки 1031геаш глобальные потоки данных cin, cout, сегг и clog были объектами классов istream withassign и ostream withassign. Это позволяло перенаправлять потоки данных, присваивая одни потоки другим. Этот механизм был исключен из стандартной библиотеки С++. Тем не менее сама возможность перенаправления потоков данных была сохранена и расширена так, что теперь она может применятьсяко всем потокам данных. Перенаправление потока данных осуществляется назначением потокового буфера.



В механизме назначения потоковых буферов перенаправление потоков данных находится под управлением программы, операционная система здесь не участвует. Например, в результате выполнения следующего фрагмента данные, отправлеиные в поток данных cout, будут передаваться не в стандартный выходной канал, а в файл cout.txt:

std::ofstream file ("cout.txt"); std::cout.rdbuf (fUe.rdbufO);

Для передачи всей форматной информации между потоками данных можно воспользоваться функцией copyfmt():

std:lofstream file ("cout.txt"); filG.copyfmt (std::cout); std::cout.rdbuf (fUe.rdbufO);

ВНИМАНИЕ-

Объекг file является локальным и уничтожается в конце блока, что также приводит к уничтожению соответствующего потокового буфера. В этом отношении файловые потоки данных отличаются от «обычных», поскольку они создают свои объекты потоковых буферов во время консфуиро-вания и уничтожают их при уничтожении.

Учитывая это замечание, в приведенном примере дальнейшее использование объекта cout для записи невозможно. Более того, его даже нельзя безопасно уничтожить при завершении программы. По этой причине прежний буфер следует всегда сохранять с последующим восстановлением! В представленном ниже примере это делается в функции redirect():

io/redirect.cpp finclude <iostreani> finclude <fstrGain> using namespace std:

void redirect(ostream&);

int mainO

cout « "the first row" « end1:

redirect(cout);

cout « "the last row" « endl;

void redirect (ostream& strm) {

ofstream fileCredirect.txt"):

Сохранение выходного буфера потоке! streambuf* strm buffer * strm.rdbufО:



Перенаправление вывода в файл strm.rdbuf (file.rdbufO);

file « "one row for the file" « endl; strm « "one row for the stream" « endl;

Восстановление старого выходного буфера strm.rdbuf (strm buffer);

} Автоматическое закрытие файла И буфера

Результат выполнения программы выглядит так:

the first row the last row

Содержимое файла redirect.txt:

one row for the file one row for the stream

Как видите, данные, записанные в поток данных cout внутри функции redirect(), были переданы в файл (по имени параметра strm), а даииые, записанные в main() после вьшолнения redirect(), попали в восстановленный выходной канал.

Потоки чтения и записи

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

std;;fstream file ("example.txt". std::ios::in std;;ios::out):

Также можно использовать два разных потоковых объекта, по одному для чтения и записи. Соответствующий фрагмент может выглядеть примерно так:

std:iOfstream out ("example.txt". 1os:;in ios::out); std::istream in (out.rdbuf0);

Объявление out открывает файл. Объявление in использует потоковый буфер out для чтения из него. Обратите внимание: поток данных out должен открываться для чтения и записи. Если открыть его только для записи, чтение из потока данных приведет к непредсказуемым последствиям. Также обратите внимание на то, что in определяется не с типом ifstream, а только с типом istream. Файл уже открыт, и у него имеется соответствующий потоковый буфер. Все, что требуется, - это второй потоковый объект. Как и в предыдущих примерах, файл закрывается при уничтожении объекта файлового потока данных.

Также можно создать буфер файлового потока данных и назначить его обоим потоковым объектам. Решение выглядит так:

std::filebuf buffer: std::ostream out(&buffer):



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