Программирование >>  Операторы преобразования типа 

1 ... 208 209 210 [ 211 ] 212 213 214 ... 239


Как упоминалось выше, символы можно вернуть в буфер чтения с помощью функций sputbackcO и sungetc(). Функция sputbackcO получает возвращаемый символ в аргументе и проверяет, что именно этот символ был прочитан последним. Обе функции уменьшают указатель текущей позиции чтения, если это возможно. Очевидно, это возможно только в том случае, если указатель чтения не находится в начале буфера. При попытке возврата символа в начале буфера вызывается виртуальная функция pbackfaii(). Переопределяя эту функцию, можно реализовать механизм восстановления прежней позиции чтения даже в этом случае. В базовом классе basic streambuf соответствующее поведение не определено. Таким образом, на практике возврат на произвольное количество символов невозможен. Для потоков данных, не использующих буферизацию, следует реализовать функцию pbackfaii(), потому что в общем случае предполагается, что хотя бы один символ может быть возвращен в поток.

Когда буфер заполняется заново, возникает другая проблема: если прежние данные не были сохранены в буфере, возврат даже одного символа невозможен. По этой причине реализация underflow() часто перемещает несколько последних символов (например, четыре) в начало буфера и присоединяет читаемые символы после них. Это позволяет вернуть хотя бы несколько символов перед тем, как будет вызвана функция pbackfaii().

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

io/inbufl.hpp finclude <cstd1o> finclude <cstring> finclude <streafiibuf>

extern C {

int read (int fd. char* buf. int num):

class inbuf ; public std;;streambuf { protected: /* Буфер данных;

* - до четырех символов в области возврата.

* - до шести символов в обычной буфере ввода. */

static const int bufferSize = 10: Размер буфера данных char buffer[bufferSize]: Буфер

public: /* Конструктор

* - Инициализация пустого буфера

* - без области возврата

* > принудительный вызов underflowO* */



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, всегда используемая потоковьпли буферами для чтения следующих символов. Сначала функция проверяет наличие прочитанных символов в буфере ввода. Если такие символы есть, они перемещаются в область возврата функцией memcpy(). В буфере ввода хранятся не более четырех последних символов. Низкоуровневая функция ввода-вывода POSIX read() читает следующий символ из стандартного канала ввода. После того как указатели буфера будут настроены в соответствии с изменившейся ситуацией, возвращается первый прочитанный символ.

ЬаскО gptrO egptrO

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

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

ЬаскО gptrO

gptrO

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

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

back()

gptrO

gptrO

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

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

lo/unbufl.cpp Iinclude <iostreafii>



1 ... 208 209 210 [ 211 ] 212 213 214 ... 239

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