На этом шаге мы рассмотрим представление потоковых буферов с точки зрения пользователя.
Напомним, что потоки данных не выполняют непосредственные операции чтения и записи, а поручают их потоковым буферам. Начиная с этого шага, мы будем изучать работу классов буферов. Этот материал не только поможет глубже разобраться в том, как работают потоки данных при вводе-выводе, но и заложит основу для определения новых каналов ввода-вывода. Прежде чем переходить к подробному описанию потоковых буферов, рассмотрим их открытый интерфейс.
С точки зрения пользователя потокового буфера, класс basic_streambuf представляет собой нечто, принимающее н отправляющее символы. В таблце 1 приведены версии открытых функций для вывода символов.
Функция | Описание |
---|---|
sputc(c) | Выводит символ с в потоковый буфер |
sputn(s, n) | Выводит n символов из последовательности s в потоковый буфер |
Функция sputc() возвращает traits_type::eof() в случае ошибки, где traits_type - определение типа в классе basic_streambuf. Функция sputn() выводит количество символов, заданное вторым аргументом, если только выводу не помешают недостаточные размеры строкового буфера. Символы завершения строк при выводе не учитываются. Функция возвращает количество выведенных символов.
Интерфейс чтения символов из потокового буфера устроен несколько сложнее (таблица 2). Дело в том, что при вводе иногда требуется узнать символ без его извлечения из буфера. Кроме того, желательно предусмотреть возможность возврата символов в потоковый буфер. Соответствующие функции поддерживаются классами потоковых буферов.
Функция | Описание |
---|---|
in_avail() | Возвращает нижнюю границу доступных символов |
sgetc() | Возвращает текущий символ без его извлечения из буфера |
sbumpc() | Возвращает текущий символ с извлечением из буфера |
snextc() | Извлекает текущий символ из буфера и возвращает следующий символ |
sgetn(b,n) | Читвет n символов и сохраняет их в буфере b |
sputbackc(c) | Возвращает символ с в потоковый буфер |
sungetc() | Возвращается на одну позицию к предыдущему символу |
Функция in_avail() проверяет минимальное количество доступных символов. Например, с ее помощью можно убедиться в том, что чтение не будет заблокировано при вводе с клавиатуры. С другой стороны, количество доступных символов может быть больше значения, возвращаемого этой функцией.
Пока потоковый буфер не достигнет конца потока данных, один из символов считается "текущим". Функция sgetc() используется для получения текущего символа без перемещения к следующему символу. Функция sbumpc() читает текущий символ и переходит к следующему символу, который становится текущим. Последняя из функций чтения отдельных символов, snextc(), переходит к следующему символу и читает новый текущий символ. Для обозначения неудачи все три функции возвращают traits_type::eof(). Функция sgetn() читает в буфер последовательность символов, максимальная длина которой передается в аргументе. Функция возвращает количество прочитанных символов.
Функции sputbackc() и sungetc() возвращаются на одну позицию в потоке данных, вследствие чего текущим становится предыдущий символ. Функция sputbackc() может использоваться для замены предыдущего символа другим символом. При вызове этих функций необходимо соблюдать осторожность: нередко возврат ограничивается всего одним символом.
Отдельная группа функций используется для подключения объекта локального контекста, для смены позиции и управления буферизацией. Эти функции перечислены в таблице 3.
Функция | Описание |
---|---|
pubimbue(loc) | Ассоциирует потоковый буфер с локальным контекстом loc |
getloc() | Возвращает текущий локальный контекст |
pubseekpos(pos) | Перемещает текущую позицию в заданную абсолютную позицию |
pubseekpos(pos, which) | To же с указанием направления ввода-вывода |
pubseekoff(offset, rpos) | Перемещает текущую позицию по отношению к другой позиции |
pubseekoff(offset, rpos, which) | To же с указанием направления ввода-вывода |
pubsetbuf(b,n) | Управление буферизацией |
Функции pubimbue() и getloc() используются при интернационализации (смотри 492 шаг). Функция pubimbue() подключает новый объект локального контекста к потоковому буферу и возвращает ранее установленный объект локального контекста. Функция getloc() возвращает текущий объект локального контекста.
Функция pubsetbuf() позволяет в определенной степени управлять стратегией буферизации потоковых буферов. Тем не менее ее возможности зависят от конкретного класса потокового буфера. Например, вызов функции pubsetbuf() для буферов строковых потоков данных не имеет смысла. Даже для буферов файловых потоков данных применение этой функции переносимо лишь в том случае, если она вызывается перед выполнением первой операции ввода-вывода в формате pubsetbuf(0,0) (то есть буфер не используется). Функция возвращает объект потокового буфера при успешном завершении или 0 в случае неудачи.
Функции pubseekoff() и pubseekpos() используются для управления текущей позицией чтения и/или записи. Позиция зависит от последнего аргумента, который относится к типу ios_base::openmode и по умолчанию равен ios_base::in | ios_base::out. При установленном флаге ios_base::in изменяется позиция чтения, а при установленном флаге ios_base::in - позиция записи. Функция pubseekpos() перемещает поток данных в абсолютную позицию, заданную первым аргументом, тогда как функция pubseekoff() использует смещение, заданное по отношению к другой позиции. Смещение передается в первом аргументе. Позиция, по отношению к которой задается смещение, передается во втором аргументе и может быть равна ios_base::cur, ios_base::beg или ios_base::end (за продробностями обращайтесь к 496 шагу). Обе функции возврашают новую текущую позицию или признак недействительной позиции. Чтобы обнаружить недействительную позицию, следует сравнить результат с объектом pos_type(off_type(-1)) - типы pos_type и off_type используются для определения позиций в потоках данных. Текущая позиция потока возвращается функцией pubseekoff():
sbuf.pubseekoff (0, std::ios::cur)
На следующем шаге мы рассмотрим итераторы потоковых буферов.