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

1 ... 199 200 201 [ 202 ] 203 204 205 ... 239


и ios::ate символы, записанные в строковый поток данных, присоединяются к существующей строке:

std::string s;

std::ostr1ngstream os (s. ios::outiosapp): OS 77 std::hex 77:

Однако строка, возвращаемая функцией str(), представляет собой копию строки s с присоединенными значениями 77 в десятичном и шестнадцатеричном виде. Сама строка s остается неизменной.

Потоковые классы char !

Потоковые классы char* поддерживаются только в целях обратной совместимости. Их интерфейс иногда порождает ошибки, с зтими классами часто работают неправильно. Тем не менее они продолжают широко использоваться, поэтому далее приводятся их краткие описания. Учтите, что в описываемой здесь стандартной версии прежний интерфейс был слегка изменен.

Далее вместо термина строка будет использоваться термин последовательность символов. Дело в том, что последовательность символов, поддерживаемая потоковыми классами char*, не всегда заканчивается символом завершения строки (а следовательно, не является строкой в обычном понимании).

Потоковые классы char* определены только для символьного типа char. К этой категории относятся следующие классы:

О istrstream для чтения из последовательностей символов;

О ostrstream для записи в последовательности символов;

О strstream для чтения из последовательностей символов и записи в последовательности символов;

О strstreambuf используется как потоковый буфер для потоков char*.

Потоковые классы char* определяются в заголовочном файле <strstream>.

Поток данных istrstream может инициализироваться последовательностью символов (типа char*), либо завершенной символом \0, либо имеющей длину, переданную в аргументе. Типичный пример чтения и обработки строк:

char buffer[1000]: Буфер, в котором могут храниться

до 999 символов

Чтение строки

std::Cln.get(buffer.s1zeof(buffer)):

Чтение/обработка строки как потока std::Istrstream 1nput(buffer):

input x:

Поток данных char*, предназначенной для записи, поддерживает последовательность символов, растущую по мере необходимости, или инициализируется



буфером фиксированного размера. При помощи флагов ios::app и io5::ate можно дописывать выводимые символы к последовательности, уже хранящейся в буфере.

При строковой интерпретации потока данных char* необходима осторожность. В отличие от строковых потоков данных потоки типа char* не всегда следят за использованием памяти, в которой хранится последовательность символов.

Функция str() предоставляет вызывающей стороне доступ к последовательности символов вместе с ответственностью за управление соответствующей памятью. Если поток данных не был инициализирован буфером фиксированного размера (за который поток никогда не отвечает), должны соблюдаться следующие трн правила.

О Поскольку права владения памятью передаются вызывающей стороне (если поток данных не был инициализирован буфером фиксированного размера), символьная последовательность должна освобождаться. Но так как не гарантируется, что память выделялась вызов delete[] не всегда безопасен. Лучше всего вернуть память в поток данных вызовом функции freeze с аргументом false (пример приводится далее).

О Вызов str() запрещает потоку данных дальнейшее изменение последовательности символов. Функция неявно вызывает функцию freeze(), которая фиксирует ( замораживает*) последовательность символов. Это делается для того, чтобы избежать трудностей при недостаточном размере буфера и необходимости выделять новую память.

О Функция str() не присоединяет символ завершения строки (\0). Это символ приходится отдельно присоединять к потоку данных для завершения последовательности символов. Задача решается при помощи манипулятора ends. Некоторые реализации присоединяют символ завершения строки автоматически, но это поведение нарушает переносимость программы.

Пример использования потока char*: float X;

/* Создание и заполнение потока char* * - не забывайте о ends или \0!!1 */

std:;ostrstream buffer; Динамический потоковый буфер buffer float х: х std;:ends:

Передача полученной С-строки функции foo() и возвращение памяти в буфер

char* S - buffer.strO;

foo(s):

buffer.freeze(fa1se):

Зафиксированный поток char* можно привести в обычное состояние для дополнительной обработки. Для этого следует вызвать функцию freeze() с аргу-

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



ментом false. При выполнении этой операции право владения последовательностью символов снова возвращается объекту потока данных. Это единственный безопасный способ освобождения памяти для последовательности символов. В следующем примере показано, как это делается:

float X:

std:;ostrstream buffer: Динамический поток char*

Заполнение потока char*

buffer float x: x std::ends;

/* Передача итоговой С-строки функции fooO

* - фиксация потока char* */

fooCbuffer.strO);

Снятие фиксации с потока char* buffer.freeze(false):

Установка позиции записи в начало buffer.seekp (О, ios::beg);

Повторное заполнение потока char*

buffer once more float x: x std::ends:

/* Повторная передача полученной С-строки функции foo()

* - фиксация потока char*; */

fooCbuffer.strO);

Возвращение памяти в буфер buffer.freeze(false);

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

Операторы ввода-вывода для пользовательских типов

Как упоминалось ранее, главным преимуществом потокового ввода-вывода перед средствами ввода-вывода языка С является возможность расширения потокового механизма для пользовательских типов. Расширение основано на перегрузке операторов << и >>. Далее рассматривается пример использования потоков данных для вывода правильных дробей.



1 ... 199 200 201 [ 202 ] 203 204 205 ... 239

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