Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 155
Текст из файла (страница 155)
Максимальное число цифр определяется точностью, Это соответствует '/ и в рпл у" () (ф 21,8). ° Научный формат представляет число десятичной дробью с одной цифрой перед точкой и показателем степени. Это соответствует '/ье в рг(п(7 (). Фиксированный формат представляет число как целую часть с дробной частью, отделенной точкой. Точность определяет максимальное число цифр после ~очки.
Это соответствует %7 в рг/ау (), Мы управляем выводом чисел с плавающей точкой при помощи функций манипулирования состоянием. В частности, мы можем установить способ вывода числа с плавакзщей точкой, не влияя на другие аспекты состояния потока. Например, Глава 21. Потоки выведет 1234.567У 1234.5679 123456 1235 1235 123456 Отметим, что числа с плавающей точкой округляются, а не просто урезаются, и что функция ргес!к!оа () не влияет на вывод целых чисел. Флаг иррегсаке Я 21А.1) определяет, будет выводиться е или Е для обозначения порядка в научном формате. Более изящный способ для определения вида выводимых чисел с плавающей точкой предоставляют манипуляторы Я 21.4.б.2).
21.4.4. Поля вывода Часто мы хотим заполнить текстом определенное место в выходной строке. Скажем, мы хотим использовать ровно и символов и не меньше (а больше — только если текст не влезает). Чтобы это сделать, мы определим ширину поля и символ, используемый для его заполнения при необходимости; с!иве 1ок Ьазе( риЫол //- к!геатвуее ек!с!!й () сопз1; к!геатз1ее ьяс!!й (з!геатзгее ш!с!е); // получить ширину поля // установить ширину поля !етр1а1екс!авз Сй, с!акв Тг = сйаг 1га1!к<Сй > с!азк Ьав!с !ок: риЫ!с юк Ьазе ( риЫ!с: //- Сй/!11 () сопя!; СЬЯ!1 (Сй сй); //- // получить символ-заполнитель // установить сомоол-заполнитель соивияс!!й (4); сои!«12; выведется 12 с двумя пробелами впереди.
Символ-заполнитель можно определить функциейу!!! (), например: сои! ш!с!!й (4); сои!.6!! ('№'); сои! «аЬ"; выдаст строку (№№ай). Функция ш!с(!й () определяет минимальное число символов, которые выведутся сле- дующей операцией вывода «стандартной библиотеки для числа, логического зна- чения, строки в стиле С, символа, указателя Я 21.2.1), строки (з 20.3.15) или Ы!зе! Я 17.53.3). Например, в результате 697 21.4. Форматирование По умолчанию символом-заполнителем является пробел, а величина поля равна О, что означает «столько символов, сколько нужною Размер поля по умолчанию можно восстановить следующим образом; сои1 ыЫ1Ь (0); // «столько сил~волов, сколько нужно» Функция щЫ1Ь (и) устанавливает минимальное число символов в и.
Если строка или число длиннее, выведутся все их символы. Например, в результате сои1лоЫЙ (4); сои!«аЬсс!е~', и!, Ы1Ь (41; сои1/!!! ('и'); сои1«!2«' «И; Данные операции выведут оо!2:И, а вовсе не 11н!2ййй:з111ййИ, как можно было бы предположить, увидев в последовательности инструкций вЫИ (4). Если бы щи () влияла на все операции по выводу чисел и строк, нам пришлось бы явно указать тоЫ1Ь () практически для всех величин.
Стандартные манипуляторы Я 21.4.6.2) предоставляют более изящный способ определения ширины поля вывода. 21.4.5. Выравнивание поля Управлять выравниванием символов в поле можно, вызывая функции зе1/(): // влево // вправо // внутреннее соихзеЯ (!оз Ьизез!е!1,!оь' ЬазесасЦиз1!се!4); сои!ее!!'(1оз Ьазеспувб !оз Ьазесау!изЯе!с!); сои1зе1Х(!оз Ьазез1п1еспа1,1оз ЬазесаЯизЯе!с!); Эти установки выравнивания внутри поля вывода определяются функцией Ыз ЬазесщЫ1Ь () и не влияют на другие части состояния потока.
Выравнивание можно определить следующим образом: сои!/1!! ('и') сои! «'(', соиглоЫЙ (4), сои1 « — ! 2 « '), ("; соиглоЫ1Ь (4); сои!.зег/'(1оз Ьазе-!еД1оз Ьазесас)!из1/)е!4); сои1 « — ! 2 « "), ('; сои1лоЫЙ (4); сои1зе!ХЦоз Ьазет)п1еспа1,1оя Ьазе",ас(!из1ЯеЫ); сои! « — ! 2 « ")"; выведется аЬсс!е~ а не аЬсй Обычно лучше получить правильный вывод, ужасный с виду, чем прекрасный внешне, но неверный (см. также 5 21.10[21)). Обращение к функции щЫ1Ь (и) влияет только на непосредственно следующую за ней операцию вывода «: 698 Глава 21.
Потоки В результате выведется: (ят — !2), (-1211), ( — ЯГ!2). Внутреннее выравнивание располагает символы-заполнители между знаком и значением. Как показано, по умолчанию установлено выравнивание вправо. Что произойдет, если одновременно установлено более одного флага выравнивания, не определено. 21.4.6. Манипуляторы Чтобы избавить п рограммиста от необходимости иметь дело с состоянием потока посредством флагов, стандартная библиотека предоставляет набор функций для манипулирования этим состоянием. Ключевая идея заключается в том, чтобы вставлять между объектами (записываемыми или читаемыми) операцию, которая изменила бы состояние потока. Например, мы можем явно потребовать, чтобы выходной буфер очистился: сои1«х «ЯизЬ «у «1!изЬ; Здесь сои!,)7изЬ () вызывается в соответствующее время.
Это делается версией оператора «, который принимает в качестве аргумента указатель на функцию и вызывает ее: 1етр!а1е<с!акз СЬ, с1авз Тг = сЬаг 1га!!в<С!г > с!авкЬатс ов!геат тггиа1риЫ!сЬаи!с !ои<СЬ, Тг' ( риЫсс. Ьаз!с овггеатйорсга1ог (Ьаз!с ов1геатй ('/) (Ьаисс озггеаспй))(гвгигпД*1Ызя) Ьаисс оксгеатйарегагог«(саз баке& (*)) (!ок Ьазей)); Ьаз!с ов1геатйарега1аг (Ьаз!с !оз<СЬ, Тс й (*/) (Ьаиес сои<СЬ, Тг'й)) //...
); Чтобы это заработало, функция должна бьжь не-членом или статической функцией- членом правильного типа. В частности, ЯивЬ () определяется следующим образом; 1етр!а1е<с!авв СЬ, с!азв Тг = сааг 1гапи<СЬ» Ьаз!с ои1геат<СЬ, Тг>й/!ии!с (Ьаз!с оя1геасп<СЬ, Тги& з) ( ск1игп и/!икЬ (); // зивов фусскс!ии/)ииЬ~), члена ояйеассс ) Это гарантирует, что саи1 «ЯивЬ; разрешается как сои1арега1аг « (/!ииЬ) что вызывает Яизд (саи1); что в свою очередь вызывает саи131 икЬ (); Весь этот анализ происходит (во время компиляции) для того, чтобы было можно обращаться к Ьав/с ок1геат: ЯияЬ () при помощи записи сои1«(сизЬ.
2ца. Форматирование б99 Существует множество операций, которые нам бы хотелось выполнить непосредственно перед или после операции ввода/вывода. Например: сои! «х; сои!4!ияб (); сои!«у; с!свинке(/((оя Ьаве: яб(рщя); скп»х; // не пропускать с!и!волы-разделители Естественно, класс бак!с !яггеат, так же, как и Ьая!с ояггеат, обеспечивает операторы» для вызова манипуляторов; сетр!а!с<с!аяв Сб, с(аяк Тг = сбаг ггааякСЬ» с(аяя Ьатс (я!сват:1лг!иа!риб!!сЬатс !ов<СЬ, Тг>( риб((с.
Ьаясс гя!сеато орегагог> (Ьав(с !яггеакпй (*р/) (бак!с !яггеат!>)) бак!с (яггеатйорегагог > (Ьавгс гоя<СБ, Тг>8 (*р/) (Ьатс гоякСЬ, Тг>й)'! Ьаыс гяггеатйорегаГог» (!оя базен ('рЯ(гая бакен; // .. 21.4.6.1. Манипуляторы с аргументами Могут пригодиться и манипуляторы с аргументами. Например, нам может захотеть- ся написать: сои! «ргеса!оп (4) «апу(е; чтобы вывестн значение переменной с плавающей точкой апфе, состоящее из четырех цифр. Чтобы это сделать, ее!реев!в(оп должна вернуть объект, инициализированный числом 4 который при обращении к нему вызывает сои!ргес(я(оп (4). Таким манипулятором является объект-функция, который вызывается опера гором «, а пе ().
Точный тип этого объекта-функции определяется при реализации, но его можно определить следующим образом: я ггиз! я т атр ( !оя Ьавей (*Я (юк ЬаяеЬ, !и!) //узунк!(ия для вызова !пгк; яташр (!оя Ьаяей (т!) (соя Ьаяеб, т!), !пг(!):Х(О),(((!)() Когда операции записываются как отдельные инструкции, логические связи между ними не очевидны.
При потере логической связи код становится сложнее понимать. Введение манипуляторов позволяет вставлять такие операции, как!(ияй () и лояйлрвя () непосредственно в список операций ввода илн вывода. Например: сои!«хе Тсияб«у «/(ияб; с!п» ипяе(/((оя баяесябгргся)»х; Отметим, что манипуляторы находятся в пространстве имен яЫ, Поэтому там, где яИ не является частью текущей области видимости, они должны быть явно квалифицированы: яяс!. сои! «еп!!!; // ошибка: епд! вне области видш!ости ягдгсои! «вЫ:епс((; // правильно Глава 21. Потоки 700 1етр1а1е<с!вяз СЬ, с!азз Т оз1геат<СЬ, Тг>й орега1ог«(оз1гсат<СЬ, Тг>й ок, соаз1 кташрй т) ге1игп т/(ок, т.!); ) Конструктор ктапср хранит свои аргументы в/ и с, а орега1ог«вызываетЕ (!).
Теперь мы можем определить зе1ргесю)оп () следующим образом: сок Ьаке& ке1 ргес)поп (юк Ьаяе& з, спгп) //функция-помои)ник ( ге1и гп я.як1ргес!к(оп (а); // вызов функции-члсна ) Еп)те кташр зе1ргес(в(оп (1п1п) ( гс1игп зташр (ке1 ргесЕксоп, п); ) // создание объекта-функции И теперь мы можем написать: сои1 «зе1ргес!к(оп (4) «апу(с; В случае необходимости программист может определить новые манипуляторы в том же стиле, что и зташр Я 21.10(22)). Это не требует внесения изменений в опредечения шаблонов стандартной библиотеки и таких классов, как Ьак(с Ек1геаяп, Ьаксс ок1геат, Ьаз!с Еоки/оз Ьаке. !оз Ьазей кБаюрот1(!ок Ьикей'! Еоз Ьакейпоядаюрот1 (Еак Ьакейк) // киаяе1/(!оз Ьакенкдоюро!и!) зЬоюрок (Еаз Ьакей'! позЬоюрок (сок Ьакей к); кЬЕрюк йак Ьакей); аокЬЕртюв фок Ьаяе& к]; юк Ьазей юв Ьаксй // кипке1/(!оя Ьаяенялоюроя) //пропуск <символов-разделителей> // ялспзе1/(Еоя Ьазенйирсая) // Х и Е вл ~всто х и е //х и е вместо Хи Е //выравнивания (у 2!.4.5) //заполнители послеэначения Еок Ьакей юз базе& Еак Ьаксйиррегсаяе (юк Ьаяей); юк Ьазей паиррегсазе (Еоз Ьакей); юз Ьакей Еп1егпа! (юз Ьакей); юз Ьазей)е/Е(!ок Ьаксй); 21.4.б.2.