Выходные строковые потоки

   
На этом шаге мы рассмотрим создание и использование выходных строковых потоков.

   
Выходные строковые потоки обычно создаются с помощью такого конструктора класса ostrstream:

    ostrstream имя_потока(char *str, int len, int mode);

Необязательное имя_потока - это идентификатор, произвольно выбираемый программистом. Указатель str должен адресовать уже существующий
участок памяти. Параметр int len определяет размеры этого участка (буфера). Последний параметр - индикатор режима обмена mode. Режим
обмена строкового потока при выводе определяет размещение информации в связанной с потоком строке. Для задания
конкретного режима используется флаг или дизъюнкция нескольких флагов:

ios::out
строковый поток создается для вывода, запись информации ведется с начала строки;
ios::ate
позиция записи устанавливается в месте размещения нулевого признака конца строки ' \0' (запись в продолжение);
ios::арр
для строковых типов этот флаг действует аналогично флагу ios::ate, но в конкретных реализациях могут
быть отличия, обычно отражаемые в документации.

   
Вместе с флагом ios::out могут быть указаны (в дизъюнктивной форме) флаги ios::ate или ios::арр. В
обоих случаях при формировании потока позиция записи устанавливается на нулевой признак '\0' конца строки (буфера потока),
т.е. предполагается запись в конец потока.

   
По умолчанию выбирается ios::out, т.е. строковый поток создается для вывода (записи) информации с начала строки (буфера).

   
Начнем рассмотрение основных возможностей выходных строковых потоков с их безымянного варианта. В следующей программе
значение строки обязательного аргумента функции main с помощью операции вставки << переносится в безымянный строковый поток,
связанный с символьным массивом path[]:

//OOР15_1.СРР - запись в безымянный выходной строковый поток (<<).
#include <strstrea.h>
void main(int Narg,  char  *arg[])
{
  char path [80] ;
  ostrstream(path,sizeof(path))  << arg[0] <<  '\0';
  cout<< "\nПолное имя программы:   "  << path << endl;
}

Текст этой программы можно взять здесь.

   
Результат выполнения программы:

    Полное имя программы:   D:\WWP\TESTPROG\OOP52_1.EXE

   
Так как операция включения << не переносит в выходной поток признак конца строки '\0', то его пришлось явным
образом поместить в выходной поток (тем самым в буфер path[]).

   
Функция write() применительно к выходному потоку позволяет записывать в него данные без форматирования, т.е. строка
записывается вместе с пробельными символами и символом конца строки '\0'. Чтобы продемонстрировать особенности ее
применения к безымянным выходным строковым потокам, рассмотрим следующую программу:

//OOР15_2.СРР - запись в безымянный выходной строковый
//  поток; копирование строки с использованием 	функции write().
#include <strstrea.h> 
void main ()
{
  char lat[] = "Quod erat demonstrandum!"; 
  char rus[] = " - Что и требовалось доказать!";
  char result[60];
  ostrstream(result, sizeof (result)) .write (lat, sizeof (lat));
  ostrstream(result, sizeof (result) , ios::ate) .write (rus, sizeof (rus)); 
  cout  <<  "\n"  << result  <<  endl; 
}

Текст этой программы можно взять здесь.

   
Результат выполнения программы:

    Quod erat demonstrandum!   -  Что и требовалось  доказать!

   
В программе два безымянных потока, каждый из которых "настроен" на символьный массив result[]. При создании
первого безымянного потока в качестве параметров конструктора указываются - массив result[] и его размеры, т.е. длина массива
в байтах. Функция write() "присоединяется" с помощью операции "точка" непосредственно к конструктору и тем самым вызывается
для созданного им безымянного потока. В качестве фактических параметров функции write() используются указатель lat на
строку и количество записываемых символов. Так как длина строки меньше длины буфера result, то буфер не заполняется
целиком. При создании второго безымянного потока, кроме буфера result и его длины, в конструкторе (в качестве третьего параметра) использован
флаг ios::ate, под действием которого поток создается как "дополняемый". Тем самым последующая запись в поток выполняется не с начала
потока, а начиная с позиции окончания предыдущей записи '\0'. Именно тут функция write() помещает строку,
адресованную указателем rus. Та самым в массиве result[] осуществляется конкатенация строк, что видно из результатов.
Из массива result [] вывод в поток cout выполняется до появления символа конца строки ' \0' в массиве result.

   
Следующая программа иллюстрирует особенности последовательного вывода в строковый поток данных разных типов
с помощью операции включения:

//OOР15_3.СРР - вывод в строковый поток операцией <<.
#include <strstrea.h>
void main()
{ 
  char buffer[180];
  ostrstream outstring(buffer, sizeof(buffer), ios::out | ios::ate);
  outstring << "\nБез явного включения разделителей" 
                   << " текст в потоке\n\"сливается\":\n ";
  outstring << 123456789 << -456 << +1.23456789;
  outstring << -0.123456789e+1 << +123.456789e-3 << ends;
  cout << "\n" << buffer << endl; 
}

Текст этой программы можно взять здесь.

   
Результат выполнения программы:

    Без явного включения разделителей текст в потоке
    "сливается":
    123456789-4561.23456789-1.23456780.123457

   
Как показывают результаты, последовательное обращение к строковому потоку приводит к записи "в продолжение",
т.е. указатель позиции записи при создании потока устанавливается на его начало, а затем перемещается на длину каждой новой записи.
Никаких промежутков или разделителей между выводимыми данными не добавляется. Более того, операция включения в поток <<
даже не переносит в него нулевой ограничитель конца строки '\0'. Поэтому его нужно добавлять явно, если в дальнейшем требуется использовать
буфер потока в качестве строки. Числовая информация, включаемая в поток операцией <<, форматируется. При этом знак + для чисел
заменяется пробелом, вещественные числа, заданные в экспоненциальной форме (в научной нотации), переводятся в форму с фиксированной точкой.
Выполняется округление дробной части вещественного числа. Перечисленные и проиллюстрированные результатами особенности форматирования могут
быть изменены с помощью средств управления форматом как и для стандартных потоков.

   
На следующем шаге мы рассмотрим двунаправленные строковые потоки.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий