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

mbufo {

setg (buffer+4. Начало области возврата buffer+4. Текущая позиция buffer+4): Конечная позиция

protected: Вставка новых символов в буфер virtual int type underflow О {

Текущая позиция чтения предшествует концу буфера? if (gptrO < egptrO) {

return tra1ts type::to 1nt type(*gptr()):

/* Обработка разиера области возврата

* - использовать количество прочитанных символов.

* - но не более 4 */

int numPutback;

numPutback = gptrO - ebackO; if (numPutback > 4) { numPutback « 4:

/* Копирование до четырех ранее прочитанных символов

* в область возврата (первые четыре символа) */

std::memmove (buffer+(4-numPutback). gptrO-numPutback. numPutback):

Чтение новых символов int num:

num = read (0. buffer+4. bufferSize-4): if (num <- 0) {

ОШИБКА или EOF

return EOF;

Сброс указателей

setg (buffer+(4-numPutback). Начало области возврата buffer+4. Текущая позиция чтения

buffer+4+num); Конец буфера

Вернуть следующий символ

return traits type::to int type(*gptr());



Констрзктор инициализирует все указатели так, что буфер остается абсолютно пустым (рис. 13.6). При попытке прочитать символы из этого буфера вызывается функция underflowO, всегда используемая потоковыми буферами для чтения следующих символов. Сначала функция проверяет наличие прочитанных символов в буфере ввода. Если такие символы есть, они перемещаются в область возврата функцией memcpyO. В буфере ввода хранятся не более четырех последних символов. Низкоуровневая функция ввода-вывода POSIX read() читает следующий символ из стандартного канала ввода. После того как указатели буфера будут настроены в соответствии с изменившейся ситуацией, возвращается первый прочитанный символ.

•ЬаскО gptrO egptrO

Рис 13.6. Буфер ввода после инициализации

Предположим, при первом вызове read() были прочитаны символы Н, а, I, I, о, w. Буфер ввода переходит в состояние, изображенное на рис. 13.7. Область возврата пуста, потому что буфер был заполнен в первый раз, и готовых к возврату символов еще нет.

•ЬаскО gptrO

•gptrO

Рис. 13.7. Буфер ввода после чтения символов Hallow

После извлечения этих символов последние четыре символа перемещаются в область возврата, после чего читаются новые символы. Допустим, при следующем вызове readO были прочитаны символы е, е, п, \п (рис. 13.8).

back()

gptrO

•gptrO

Рис 13.8. Буфер ввода после чтения еие четырех символов

Пример использования этого потокового буфера:

lo/unbufl.cpp linclude <iostreafii>



#include "inbufl.hpp"

int mainO {

inbuf ib: Создание специального потокового буфера

std::istream in(&ib); Инициализация выходного потока этим буфером

char с:

for (int i-1: 1<-20; i++) {

Чтение следующего символа (из буфера) in.get(c):

Вывод символа и очистка буфера std::cout « с « std::flush:

После вывода восьми символов

вернуть два последних символа в поток

if (i == 8) {

in.ungetO:

in.ungetO;

std::cout « Std::endl:

Программа в циЕсле читает символы и выводит их в поток данных cout. После чтения восьмого символа выполняется возврат на два символа, в результате чего седьмой и восьмой символы выводятся дважды.

Проблемы эффективности

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

Одна из проблем быстродействия уже упоминалась на с. 567: в программу должны включаться только заголовочные файлы, абсолютно необходимые для компиляции. В частности, следует избегать включения файла <iostream>, если в профамме не используются стандартные потоковые объекты.

Синхронизация со стандартными потоками данных С

По умолчанию восемь стандартных потоков данных С++ (четыре символьных потока с однобайтовой кодировкой dn, cout, сегг и ciog, а также четыре их аналога с расширенной кодировкой) синхронизируются с соответствующими каналами из стандартной библиотеки С (stdin, stdout и stderr). По умолчанию ciog и wciog



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