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'. Поэтому его нужно добавлять явно, если в дальнейшем требуется использовать буфер потока в качестве строки. Числовая информация, включаемая в поток операцией <<, форматируется. При этом знак + для чисел заменяется пробелом, вещественные числа, заданные в экспоненциальной форме (в научной нотации), переводятся в форму с фиксированной точкой. Выполняется округление дробной части вещественного числа. Перечисленные и проиллюстрированные результатами особенности форматирования могут быть изменены с помощью средств управления форматом как и для стандартных потоков.
На следующем шаге мы рассмотрим двунаправленные строковые потоки.
Основной конструктор строковых потоков, создаваемых как для чтения, так и для записи, имеет следующий формат:
strstream имя_потока (char *buf, int lenBuf, int mode);
где
buf - указатель на участок памяти (буфер потока, обычно символьный массив), для которого создается поток;
lenBuf - длина в байтах участка памяти;
mode - индикатор режима обмена с создаваемым потоком. В качестве индикатора режима обмена используется дизъюнкция флагов, принадлежащих классу ios. Флаги ios::in и ios::out определяют направление обмена. Флаги ios::ate и ios::арр влияют на размещение указателя позиции чтения/записи в буфере и т.д.
В следующей программе с символьным массивом buffer[] связывается двунаправленный поток string. Затем последовательно выполняются операции записи в поток и чтения из потока.
//OOР16_1.СРР - ввод и вывод для двунаправленного строкового потока.
#include <strstrea.h>