Программирование >>  Разработка устойчивых систем 

1 ... 38 39 40 [ 41 ] 42 43 44 ... 196


basicstreambuf<charT>

basic filebuf<charT>

basic strinfbuf<charT>

Указатель на объект streambuf потока возвращается с помощью функции rdbuf() класса потока. Через полученный указатель можно вызывать любые функции streambuf. Но из всех операций, которые могут выполняться с указателем на streambuf, наибольший интерес представляет возможность присоединения указателя к другому потоку ввода-вывода оператором . В результате все символы из потока, расположенного справа от , передаются в поток, расположенный в левой части выражения. Если потребуется переместить все символы из одного потока в другой, вам не придется прибегать к утомительному (и чреватому ошибками) процессу посимвольного или построчного чтения. Такое решение гораздо элегантнее.

Следующая программа открывает файл и передает все его содержимое в стандартный выходной поток (по аналогии с предыдущим примером):

: C04:Stype.cpp

Направление файла в стандартный выходной поток linclude <fstream> linclude <iostream> linclude . ./require.h using namespace std:

int mainO { ifstream in( Stype.cpp ): assure(in, Stype.cpp ): cout in.rdbufO: Вывод всего файла

} III:-

Объект ifstream создается на базе файла с исходным кодом программы. Функция assertO сообщает о неудачной попытке открытия файла. Вся настоящая работа выполняется следующей командой, передающей все содержимое файла в cout:

cout in.rdbufO:

Программа получается не только более компактной, но обычно и более эффективной по сравнению с побайтовым копированием символов.

Одна из форм функции get() записывает данные непосредственно в объект streambuf другого потока. Первым аргументом этой функции является ссылка на приемный объект streambuf, а вторым - символ-завершитель, прерывающий работу get() (\п по умолчанию). Так что можно рассмотреть еще один способ направления содержимого файла в стандартный выходной поток:

обращаться напрямую, например, напрямую читать и записывать байты без их форматирования потоком. Для этой цели используются функции объекта streambuf.

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



: С04:Sbufget.срр

Копирование файла в стандартный выходной поток #1nclude <fstream> linclude <iostrean)> linclude ../require.h using namespace std:

int mainO { ifstream in( Sbufget.cpp ): assureCin):

streambufS sb - *cout.rdbuf(): while (!in.get(sb).eofO) {

if (in.failO) Обнаружена пустая строка

in.clearO:

cout char(in.get()): Обработка \n

} III:-

Функция rdbuf() возвращает указатель, поэтому для получения объекта результат ее вызова необходимо разыменовать. Копирование потоковых буферов не предусмотрено (у них отсутствует копирующий конструктор), поэтому мы определяем sb как ссылку на потоковый буфер cout. Вызовы faU() и с1еаг() необходимы на случай, если во входном файле присутствует пустая строка (в нашем примере она есть). Когда эта конкретная перегруженная версия get() встречает два символа перевода строки подряд (признак пустой строки), она устанавливает флаг failbit для входного потока. Мы должны сбросить этот флаг функцией с1еаг(), чтобы продолжить чтение из потока. Второй вызов get() извлекает и воспроизводит каждый завершитель строки (помните, что функция get(), в отличие от getline(), не извлекает из потока символ-завершитель).

Вряд ли вам придется часто использовать этот прием, но все равно полезно знать, что он существует.

Поиск в потоках ввода-вывода

у каждого потока имеется свое представление о том, в какой позиции будет прочитан (для istream) или записан (для ostream) следующий символ. Иногда эту текущую позицию требуется сместить, что можно сделать двумя способами. В первом способе задается абсолютная позиция в потоке (streampos). Второй способ работает по аналогии с библиотечной функцией fseek() языка С для файлов: смещение производится на заданное количество байтов от начала, конца или текущей позиции в файле.

Вариант со streampos требует предварительного вызова специальной функции: tellpO для ostream или tellg() для istream. Функция возвращает объект streampos, который передается при вызове функции seekp() для ostream или seekg() для istream. Заданная позиция становится текущей позицией потока.

Во втором варианте с относительным позиционированием используются перегруженные версии seekpO и seekg(). Первый аргумент содержит смещение в символах, положительное или отрицательное. Второй аргумент определяет базу смещения:

ios::beg

От начала потока.



ios::cur

От текущей позиции потока.

ios::end

От конца потока.

Следующий пример демонстрирует позиционирование в файле. Помните, что позиционирование в потоках не ограничивается файлами, как в библиотеке stdio языка С. С++ позволяет выполнять позиционирование в любых потоках ввода-вывода (хотя для стандартных потоков, таких как cin и cout, позиционирование запрещено):

: С04:Seeking.срр

Позиционирование в потоках ввода-вывода

linclude <cassert>

linclude <cstddef>

linclude <cstring>

linclude <fstream>

linclude ../require.h

using namespace std:

int mainO { const int STR NUM = 5. STR LEN = 30: char or1gData[STR NUM][STR LEN] = {

Hickory dickory dus. . . .

Are you tired of С++? .

Well. if you have. .

Thats just too bad, .

Theres plenty more for us!

char readData[STR NUM][STR LEN] = {{ 0 }}: ofstream out( Poem.bin . 1os::out ios::binary): assure(out. Poem.bin ): for(s1ze t 1 = 0: 1 < STR NUM: 1++) out.wr1te(or1gData[i], STR LEN): out.closeO:

ifstream 1n( Poem.bin , 1os::1n 1os::b1nary): assureCin. Poem.bin ): in.read(readData[0]. STR LEN):

assert(strcmp(readData[0]. Hickory dickory dus. . . ) == 0):

Смещение на -STR LEN байтов от конца файла in.seekg(-STR LEN, ios::end): in.read(readData[l]. STR LEN):

assert(strcmp(readData[l], Theres plenty more for us! ) == 0):

Абсолютное позиционирование (no аналогии с operator[]) in.seekg(3 * STR LEN): in.read(readData[2], STR LEN):

assert(strcmp(readData[2]. Thats just too bad, ) == 0): Смещение в обратном направлении от текущей позиции in.seekg(-STR LEN * 2. ios::cur): in.read(readData[3]. STR LEN):

assert(strcmp(readData[3], Well, if you have. ) == 0): Позиционирование от начала файла in.seekgd * STR LEN. 1os::beg): in.read(readData[4], STR LEN): assert(strcmp(readData[4], Are you tired of С++? ) == 0): } /:-



1 ... 38 39 40 [ 41 ] 42 43 44 ... 196

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