Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 158
Текст из файла (страница 158)
Этот прием может оказаться очень полезным лля копирования в случаях, Глава 21. Потоки 706 когда требуется форматирование более сложное, чем построковый вывод в устройствах тслетайпного типа. Обращение с начальным значением для строкового потока аналогично обращснию файлового потока со своим файлом: //эквнеплеытно сотрояе() ягг(ай сотрозе2 ((и! и, сопя! ягг!пуе, сз) ( ехтегп сопят сйаг* йй теязайеЦ; оябйпуяггеат оя! ("ошибка (, юз 6аяесате); // пшиелт в конец оя! «и « ") "«зтт! теязауе(п) «" (комментарий пользователя; ' «сз « ')', ге!игл ояйятг (), ) Класс (з!г(пил!геат — зто входной поток, который считывает ланпые из своей строки инициализации (точно так же, как ф!ез!геат считывает из файла): Ф(пс(ит(е<зя! еат> //вывод по одному слову в строке ооЫтоогс! рег (те',сопя!я!с(пййз) ( !я!с(пяяггеат (я ! (я); зтг!пд то; то!и!е ((з!»то)сои!«то «тп'; тт тата () ( шогт(рег !(пе (' Если вы считаете, что Сч+ труден, попытайтесь выучить английский" ); Строка-инпциализатор копируется в (з!г(пйз!геат.
Вывод заканчивается по символу конца строки. Можно определить потоки, которые осуществляют непосредственное считывание и запись в массивы символов Я 21.10(261). Часто зто полезно при работе с устаревшими программами, тем более, что делающие зто классы оз!гз! еат и (я!гя! еат были частью изначальной библиотеки потоков. 21.6. Буферизация Вообще говоря, выходной поток кладет символы в буфер. Через какое-то время они переписываются туда, куда нужно. Такой буфер называется з!геатби/'Я 21.6А). Его определение находится в <з!геатби(>. Различные реализации буферов з!геатби/'используют различные стратегии. Как правило, з(геатби/хранттт символы в массиве, пока переполнение не вынудит его очиститься и записать символы по назначению.
Таким образом, оя!геат можно представить графически следующим образом: озтгеанк 21.6. Буферизация Набор аргументов шаблона для оя1геат и его я1геатби~'должен быть один и тот же; он определяет тип символов в буфере символов. Класс !я1геат похож на оя1геат за исключением того, что символы передаются в другую сторону. Небуферизованный ввод/вывод — это просто ввод/вывол, в котором буфер сразу же передает каждый символ, не ожидая, пока их наберется достаточно для того, чтобы сделать передачу эффективной.
21.6.1. Потоки вывода и буфера К.ласс оя1 еат вводит операции для преобразования значений различных типов в последовательность символов в соответствии с общепринятыми соглашениями Я 21.2.1) и явными директивами форматирования Я 21А). Кроме того, оя1геат прелоставляет операции, имеющие дело напрямую со я1геатби/. гетр!аге<с1аяя СЬ, с!аяз Тг= сЬаг Ьаия<СЬ» сРам Ьая!с оз1геат: о!гтиа!риЫ!сЬатс !оз<СЬ, ТГ> ( риЫ!с: ехр!тн Ьаыс отгеат (Ьая!с я1геатби/<СЬ, Тгхл 6); роз 1уре 1е1!р (); О получение гпекущвй позиции Ьая!с озггеатйзееур (роя гуре) //установки текущей позиции Ьая1с оз1геатй лесур (о// 1уре, !оз Ьаяесяееусуг) // установки текущей позиции Ьая!с оя1геатй/(ияЬ ((; // очистка буфера (запись в реал ьныи пр велта к ) Ьая!с оз1геатй орега1ог«(6аз!с я1геатби/<СЬ, Тг>*6( //зипись из 6 )) Конструктор класса оя1геат имеет аргументом объект я1геатбиЯ который определяет, как записанные символы обрабатываются, и купа они в конце концов уходят.
Например, оя1г!пуя1геат (з 21.5.3) или о/я1геат Я 21.5.1) создаются инициализацией оя1геат полхолящим буфером я1геатби/Я 21,6А). Функции зеейр () используются для того, чтобы установить позицию записи в оз1геат. Суффикс р указывает, что эта позиция используется для записи (рпШпй) символов в поток.
Эти функции не оказывают никакого эффекта, если поток не прикреплен к чему-нибудь такому, для чего позиционирование имеет смысл — например, к файлу, роя 1уре представляет позицию символа в файле, а оЯ 1уре — его смещение от точки, на которую указывает яоя Ьаяесяеей1!г. с!аяя!оз Ьазе( 1уреде/!тр!степ!одоп де/~пед4 яееус!!г; з1адс сопз1 зееус!!гбеу, //поиск от начала текущегофийлв сий // поиск от текуи!ей позиции епа; // поиск назад от конца текущего фвила Позиции в потоке нумеруются, начиная с нулевой, поэтому мы можем представить себе файл как массив из и символов. Например; 710 Глава 21. Потоки ///от ссылается на некоторый файл т1/(%1геатй 1ои1) ( /ои1зеебр (!0); // добпвляеч сильвол и сдвигаемся но (И! ) /ои1« 'и'; /ои1.яеебр ( — 2,!оябаяе:сит); /ои1 «'"; Б результате выполнения этой функции в Яе(10) запишется 41, а в Ще(Я) — " .
Но никакого подобного способа для произвольного доступа к элементам простых потоков ля1геат и оз1геат не сушествует (см. 21.10(131). Попытка поиска до начала или после копна фай.ла приводит поток в состояние Ьас( () (э 21З.З). Операция/1изй () позволяет пользователю очишать буфер, не ожидая персполнсния. Для непосредственной записи з1геатби~в озбгеат можно воспользоваться оператором «.
Это удобно прежде всего для тех, кто реализует механизмы ввода/вывода. 21.6.2. Потоки ввода и буфера Класс гзтгеат вводит операции для чтения символов и преобразования нх в значения разли шых типов ((1 21.3.1), Кроме того, (з1геат предоставляет операции, которые имелот дело напрямую со з1геатЬи/: 1етр!асе<с1аяз СЬ, с!аяз Тг= сбаг бгапя<СБ» с1азя Ьазлс 1я1геат;о1ггиа!риб!!сЬаис !оз<СЬ, Тг>( риб!1с. екр!1с!1 Ьаис аггеат (баис з1геатЬи/<СЬ, Тг>* Ь); роз глуреге!!у(); 0 получение текущей позшрии батс 1я1геатй яеебу(роя 1уре), О установка текущей позьщии баис (яггеатй зеебу (о// 1уре, лоя Ьаяесзеебдтг).: // установка текущей позсщии батс М1геатй ри16асб (СЬ с); // пол ожить с обратно в буфер Ьаягс !яггеатй ллпуе1 (); // положилльь обратно в буфер //последний смотанный символ !п1 буререеб(); // посльотретль кокос следующий // символ прочтется ьт яупс (); // очистить буфер (сброс) Ьаис !яггеатй орега1ог» (баис зггеатби/<СЬ, Тг>* 6); //чтение в Ь бак!с 1яггеатй уе! (Ьаялс яггеатЬи/<СИ, Тг>й Ь, СЬ 1=Тглпелойпе ()); зггеапмсее геадяоте (СЛ'р, Игеатзие и); //считывание льаксиллулл и символов Функции позиционирования работают так же, как и их аналоги из оз! еат (э 21.6.1).
СуффИКС ЬлуКаЗЫВаст, Чта Этн ПОЗИЦИИ ИСПОЛЬЗуЮтСя дЛя Чтвиия (яет1)П(() СИМВОЛОВ из потока. Суффиксы р и д нужны потому, что мы можем создать класс (оз1геат, производный и от !я1геат, и от оз! еат, а такой поток должен отслеживать как записьь так н чтение символов по данной позиции. Функция ри1Ьас/с () позволяет программе возвраьцать ненужный символ в поток, чтобы прочитать его в другой раз, как показано л ч 21.3.5. Функция ипйе1 () помеша- 711 21.6. Буферизация ет последний считанный символ обратно. К сожалению, возвращение в поток вводл не всегда возможно.
Например, попытка вернуть первый считанный символ устано- . вит бит !оя Ьаяе:~а!!Ы1. Все, что гарантируется — это воэможность возврата одного символа после благополучного считывания. Функция реей() читает следующий символ, но оставляет его в я!геатЬи/, так что его можно прочитать снова. Таким образом, с=рее/с () означает то же самое, что (с=уе! (), ипуе1 (), с) п (ри1Ьас/с (с уе! ()), с). Отметим, что установка /а!!Ы! может вызвать исключение Ц 21.3.6). Синхронизация потока !я1геат и буфера осуществляется при помощи яупс ().
Это не всегда выполняется правильно. Для некоторых потоков нам бы пришлось повторно считывать символы с действительного источника, а это не всегда возможно и желательно. Поэтому яупс () при успешном выполнении возвращает О, а в противном случае устанавливает бит !оя Ьаяехбас(Ы! Я 21.3.3) и возвращает -!. И снова напомню, что установка Ьас(Ы! может вызвать исключение Я 213.6). Функция яупс () для буфера, связанного с оя!гент, сбрасывает содержимое буфера на устройство вывода. Операции» и уе! (), читающие в я1геатби/, полезны прежде всего для тех, кто реализует средства ввода/вывода, и только им следует напрямую манипулировать со я1геатЬиХ Функция геас(яоте () является операцией нижнего уровня, которая позволяет пользователю посмотреть, есть ли в потоке символы, доступные для считыванию Это может очень пригодиться, когда нежелательно ждать ввода, например с клавиатуры.
Посмотрите также функцию !п аоа!! () (!у 21.6А). 21.6.3. Потоки и буФера Связь между потоком и его буфером поддерживается в Ьая!с !оя данного потока; гетр1аге<с1аяя Сб, с!аяя Тг = сбаг 1га!уя<СЬ» с!аяя Ьаягс !оя риЫ!с!оя Ьаяе( рибйс. //.. Ьаяьс я1геатби/<Сб, Тг>* гь!Ьи/() соая1; //получение буфера //ус<поповка и очистка буфера, возвраи1ает указатель на с<парий буфер Ьая1с яггеатби/<СЬ, Тг>* гс!Ьи/ (Ьая!с я1геатби/<С!ь Тг *6); !оса!е 1тЬие (сопз1!оса!ей !ос); //установка наь1ионг~ гьньа //особенностей (и получение спьарььк) сбаг ааггот (сбаг 1уре с, сбагь1) соая1; // получение символьного //значения из сбаг !урес сбаг 1уре инс!еп(сбагс) соней // полу пение значение типа // сбаг !уре по силволу с рго1ес1еь1: Ьая!с еоя () оосй ьгп11 (бая!с яггеатби/<Сб, Тг ' 6); // установка начального буфера В дополнение к чтению и установке буфера данного потока Я 21.6А) шаблон Ьая!с !оя вводит ипЬие, чтобы читать и заново устанавливать национальные особенности потока Я 21.7) путем вызова ипЬие() для его !оя Ьаяе (Я 21.7.1) ирибипЬие () для его буфера (ф 21.6А).
Глава 21. Потоки 712 Функции пиггонз(( и щЫеп (( используются для преобразования символа сЬаг в символьный тнп сЬиг 1уре буфера и обратно. Второй аргумент функции парсов (с, с!( -- это символ, возвращаемый, если не существует символа, соответствуюгцего значению стипа сЬиг 1уре. 21.6.4. Буфера потоков 1етр1а1е<с1аяя СЬ, с!аяз тг= сЬаг 1гайз<СЬ» с1азя Ьагйс зггеатби/( рго1ес1ед СЬ' еЬасЬ (( сопя!; //нач СЬ* ургг (( сопз1; // след ало буфера чтения уюи<ий заносимый символ (чтение // следующегосиивола проискавши отсюда ! //элемент, следующий за концол~ буфера чтения // добавление п к ури !) СЬ'епд(, //установка еЬасЬО, ур1г!) и едр1г // начало буфера записи // следующий записываел~ый сил~вол пойдет сюда //злелсент, следующий за концом буфера записи //добавление п к ррсг/) // установкарЬизе!) ирр1гО в начало, // а ерр1г!) в конец СЬ' еур1г((сопя!; оо1г) уЬи тр (т1 и(; оо!д вегу (СЬ' Ьеу!и, СЬ* пех1 СЬ' рЬаяе (( сопя!; СЬ'рргг ((сопя!; СЬ' ерр1г (( сопля оо!д рбитр (!п1 и) оо!д яе1р (СЬ* беат, СЬ' епб( //- 1; Имея массив символов, функции яе1у(( и яе1р((могут соответствующим образом установить указатели.