Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 159
Текст из файла (страница 159)
Строковые потоки Поток можно прикрепить к строке типа ягг(пя. То есть мы можем читать и писать в строку при помощи средств форматирования потоков. Такие потоки называют (обобщенно) яп!ияззгеат, Они определяются в <яяггеат>: гетр!иге<с!аяя СЬ, с(ат Тг = сбег !га(П<СЬ>, сгат А = а!1оса1ог<СЬ» сгаяз Ьаяс тг!пятгеат: риЫ(е бал!с !оя1геат<СЬ, Тг> ( риЫ1с: ехр1(е(! Ьаяс я!пиал!геат ( !оя базе:: орептоае т = ои1 ( (н ) ! ехрдсй ьапс я!пиал!геат (соня! ьая!с ягппа<сь, тг,А>я я, ореитойе гп = ои!(п1) Ьаяс я!г(пя<СЬ, Тг,А> ягг() сопи; //получить копию строки иоЫя!г(солт Ьамс я!ппа<СЬ, Тг,А>ь я); //установить значение копии я Ьапс ягпнябиЯСЬ, Тг,А>* гйбп/() сопя!! //получить указатель на текущий // файловый буфер )1 Класс Ьаис гапптиеат похож на Ьаяс яггзияязгеат за исключением того, что он наследуется от Ьапс (язгеат и по умолчанию открыт на чтение.
Класс Ьаягс ояМияяпеат похож на Ьаязс з*гияязгеат за исключением того, что он наследуется от Ьая(е оятгеапз и по умолчанию открыт на запись. Как обычно, с помощью операторов гуре!!е~'определяются наиболее распространенные специализации: гурейеГбая(с (я!г(пяя!геат<ебаг> (я!паяя!геат; гуреаеГбая(с оя!г!нея!геат<сбаг> оя!паяя!геат/ зурейеТ бая(с я!пнаяггеат < обаг> я!г(ияя!геат / гурейеТбая(с пттяяегеат<псбаг !> нюя!пиля!геат/ гурейе~ бая(с аз!иная!геат <ггебаг г> и ояГппея!геат / гуре!ге! Ьая(е я!ппдтгеат<юсбаг !> вз!г(наяггеат; Например, можно применить тип ояМпуггеат для форматирования строковых сообщений: зита сотрояе (тг п, соим я!пня я ея ) аегегп сопя! сбег* яа! теятяе [ ); оятпея(геа1и Озг; оя!« "епог(" « и « ") " « за! теязаае[и) « " (изег соттеп1: " « ся « ' ) гетгп ояг.
пг ( ); ) Нет необходимости следить за переполнением, поскольку оя! обеспечивает автоматическое расширение внутреннего хранилища. Этот прием может оказаться особо полезным в случаях копирования, когда требуется более сложное форматирование, чем то, что используется при выводе на строкоориентированные устройства. Начальное значение для строкового потока задается аналогично тому, как файл задается для файлового потока: я!ппд ситро!ел (1н! и, сопя! я!лиаз ся) ( ехгегп сопз! сбаг* яИ незвале [) ! Уйб Глава 21 Потоки отппдззгеат озз("епог(", 1оз Ьазе:: аге); озг «и « ") " «зат теззаее (и] « " (изег соттепг: " «сз « ' ) ге<иго оз1.зп (); ) Входной поток 1з(г1пяз)геат читает данные из своей инициализирующей строки (как поток (/ятеат читает из файла, для которого он инициализнрован): ()1пс!иде <ззпеат> У ио одному слову в одну строку гоЫ воат рег Епе(соптзгг(пей з) ( (аппязггеат 1зг (з); згппе ич нЬ11е(1зе»и ) сои( « и « ' Хи'; ) 1из гиа1и ( ) ( воат рег Еие ("(гуоп гйгп)г Сее Гз ЙЯ)си!б иу Епе(1зя" ); Инициализируюшая строка копируется в 1зптиазтгеат.
Завершение чтения отдельных слов из 1зг наступает по исчерпанию содержимого этой строки. Можно определить потоки, которые осушествляют чтение и запись в массивы символов (521.10[26)). Это бывает полезно при работе со старыми программами, тем более, что предназначенные для этого классы озпвггеат и 1зпвтгеат с самого начала входили в библиотеку потоков. 21.6.
Буферирование Вообще говоря, выходной поток кладет символы в буфер. Через какое-то время они попадают туда, куда нужно. Такой буфер называется ззгеатЬиУ62! .6.4), и определен он в заголовочном файле <зггеатЬиу>. различные реализации за еатЬиу" используют разные стратегии буферизации. В типичном случае зггеатЬиг'хРанит символы в массиве до тех пор, пока его переполнение не заставит вывести символы по назначению. В итоге, работа огигеагп может быть графически отображена следуюшим образом: 05(теапи з(геапзЬцб 757 2) .6.
Буферирование Шаблонные аргументы для ояггеат и яггеатйиу должны совпадать и определять тип символов. Поток (яггеат вполне аналогичен, просто символы передаются в ином направлении. Небуферированный ввод/вывод — это такой же ввод/вывод, только яггеатЬи/ немедленно передает каждый символ по назначению, а не ждет, когда накопится нужное число символов, оптимальное для дальнейшей передачи.
21.6.1. Потоки вывода и буферы Класс ояггеат определяет операции для преобразования значений разных типов в последовательности символов согласно принятым соглашениям (521.2,!) и явным директивам форматирования (521.4). кроме того, ояггеат предоставляет операции, напрямую работающие со яггеатЬгр"; гетр1аге<с1аяя СЬ, с1аяя Тг = сйаг иа!ь<СЬ» сйяяя Ьояс ояггеат: г(ггиа1 риЬ!!с Ьаяс 1оя<СЬ, Тг> ( риЫс: //... елрйсй Ьаяс оя(геат (Ьаяс яо еатЬиТ<СЬ, Тг> * Ь) ! роя (уре 1едр() 1 // получить текущую позицию Ьаяс ояггеатя яеейр (роя (уре); //установить текущую позицию Ьаяс ояггеатя яеейр (оЯ 1уре, юя Ьаяе:: яеейй!г) ! //установить текущую позицию Ьаяс ояггеать 7!ияЬ () 1 /У очистить буфер !гса! с(еяг/паг/оп! Ьаяс ояггеатя орегагог« (Ьаяс яягеатЬиг<СЬ, Тг>* Ь) ! г/писать из Ь )1 Конструктор класса ояггеат принимает яяуеатЬиу; который и определяет, как именно обрабатываются символы и куда они в конце концов уходят.
Например, ояв!итггеат (521.5.3) или о7яггеат (а21.5.1) создаются посредством инициализации потока оягеат подходящим яггеатйит (В21.б.4). Функции яее!ср() используются для установки в ояггеат позиции записи. Суффикс р здесь как раз и означает позицию для записи (вставки — рцп)пя) символа в поток. Эти функции не оказывают никакого эффекта до тех пор, пока поток не прикреплен к чему-либо, для чего позиционирование имеет смысл, например к файлу. тип роя гуре соответствует позициям в файле, а тип о(Г гуре характеризует смещения от точки, индицируемой с помощью !оя Ьаяе:: яее!с!а: с1ат гоя Ьаяе ( У.. ГурейеТ !тр1етепга1!оп ИеЯпей4 яеейа!гг я1аг!с сопя! яеейа!г Ьед, //от начала текущего файла сиг, У от текущей позиции епг!/ //с конца файла в обратном направлении Позиции в потоке нумеруются, начиная с нуля, так что мы можем думать о файле как о массиве из и символов.
Например; убВ Глава 21 Потоки 1пз Т'(о~ззгеат и зоиз) ( !оиз.зеейр (!0); 1оиз « '() '1 У добавляем символ и сдвигаем позицию Г+ !! Тоиз.зеейр(-2, 1оз Ьазе::сиг); гонт « '*'1 ) УУ)ои! ссылается на некоторый файл Этот код поместит символ () в уз!е(10), а символ * — в )т1е [ 9) . Ничего подобного вроде произвольного доступа к элементам «простых» потоков !з(геат или озп"еат нет (см. 521.10[13)).
Попытки установить позицию чтения вне действительного интервала элементов (до файла или за его конец) переводят поток в состояние Ьас!() (э21.3.3). Операция ууизЬ () позволяет очистить буфер, не дожидаясь его переполнения. Можно применить операцию «для непосредственного сброса содержимого зггеатЬиг в озггеат. Это полезно тем, кто реализует механизмы ввода/вывода. 21.6.2.
Потоки ввода и буферы Класс 1ззееат определяет операции для чтения символов и преобразования их в значения различных типов (э21.3.1), Кроме того, 1ззгеат предоставляет операции, напрямую работаюшими со зггеатЬиЯ гетр!асе<с1азз СЬ, с1азз Тг = сдаг ~га(зз<СЬ» с(азз Ьаяс 1ягеат: Иг!иа1 риЫ)с Ьаяс 1оз<СЬ, Тг> ( риЫ(с: уу... екр!к11 Ьаяс !ззгеат (Ьазк ззгеатЬиу<СЬ, Тг>* Ь) роз (уре те!!я(); УУ7получить текущую позицию Ьазк Вггеата зеейа(роз туре); УУусьпановить текущую позицию Ьаяс Взгеата зеейд(о(Т туре, !оз Ьазе::зеейдгг) г ууустоновить текущую позицию УУ поместить с обратно в буфер УУ возвратить последний считанный символ УУ взглянуть на символ, подлежащий чтению Ьаз(с Втгеать ризбасй (СЬ с); Ьаяс В1геать инде! (); !пс гуререеЬ(); т! зупс (); УУ очистить буфер ()!изб) Ьаяс кчаеата орегазог» (Ьаяс ззгеатЬи(<СЬ, Тг>* Ы ' уу читать в Ь Ьаяс !зсгеата лез(Ьаяс ззгеап1Ьи!<СЬ, Тг»а Ь, СЬ 1 = Тг::пеп11пе() ) УУ читать не более и симе ли еатз(се геадзоте (СЬ* р, зсгеатясе п); Функции позиционирования для 1з(геат работают точно так же, как их аналоги для озгееат (э21.б.1).
Суффикс д здесь как раз и означает позицию для чтения (реп!ад) символа из потока. Суффиксы р и д нужны потому, что мы можем создать поток класса 1озй еат, производного одновременно от !згееат и оззееат, и такой поток должен будет отслеживать как позицию для записи, так и позицию для чтения. Функция ригЬасЬ() позволяет программе положить символ в поток иггеаиз, чтобы он стал в нем «следующим символом для чтения», как это показано в Э21.3.5. Функция аиде!() возврашает назад самый последний из прочитанных из потока 759 21.6.
Буферирование символов. К сожалению, возврат назад прочитанных из входного потока символов не всегда возможен. Например, попытка вернуть назад прочитанный символ в начале буфера потока установит юз Ьазе::1аИЫ!. К тому же, гарантируется возможность возврата только одного символа после успешного чтения. Функция реей() читает символ и оставляет его в ззгеатЬи7'так, что его можно прочитать снова. Таким образом, с=рве!(() эквивалентно (с=де!(), ипЬег(), с), Заметьте, что установка уаИЬ!! может сгенерировать исключение (521.3.6).