Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 221
Текст из файла (страница 221)
Очевидный способом хранения фасетов в среде исполнения — запись соответствующих данных в файл. Менее гибкая альтернатива — представление фасета в виде текста программы и данных в фаготе Ьупате. Класс соИа1е булате<с!саг> является примером фасета, у которого нет собственного илентификатора !с( Я Г.З). В рамках !оса!е фасеты сойа(е Ьуаате<СЬ> и соИаге<СЬ> взаимозаменяемы. Фассты со!!а(е и соИа1е Ьупате для одной локализации отличаются только дополнительным конструктором, предоставляемым соИа1е Ьупате, и семантикой, предлагаемой со!!а1е Ьупате. Обратите внимание, что деструктор Ьупате является защищенным. Значит нельзя объявить фасету Ьупате как локальную переменную. Например: ооЫ/() ( соИа1е Ьупате<сйаг> ту соИ(' ) // ошибка: невозяюзкно унинтозкить ту соу //-- ) Это отражает точку зрения, что локализациями и фасетами лучше пользоваться на достаточно высоком уровне программы, чтобы онн воздействовали на значительную часть кода.
1!римером является установка глобальной локализации Я Г.2З) или закрепление локализации за потоком (2 21;Ь.З, 2 1.1). При необходимости мы можем унаследовать от Ьупате производный класс с открытым деструктором и объявить локальные переменные этого класса. Г.4.2. Ввод и вывод чисел Вывод чисел осуществляется фасетом пиль ри1 путем записи в буфер потока Я 21.бА). Ввод чисел выполняется фасетом пит уе1 путем чтения из буфера потока. 973 Г4. Стандартные фасеты Формат, используемый пит ри1 и пит уе1, определяется фасетом «пунктуации чи- сель питрилс1. Г.4:2.1. Пунктуация чисел Фасет пипгрипс1 (пунктуация чисел) определяет формат ввода(вывода встроенных типов, таких как Ьоо!, 1п1 и г(оиб(е; гетр!аге<с!акк СЬ> с!акк кгггн питрипсг: риЫ!с !оса!е:,/асег ( рибйс, гурег!е/'СЬ сбаг гуре; 1урег!е/бак!с к1ппу<СЬ> кгппу 1уре; ехрИсй питрипсг(кие 1 г' = О); СЬ г(есгта! ро!лг() соле!, СЬ 1Ьоикалг/к кер() сопк1; к!пну угоир!ау() солкг; // '.' в с1актцс() // ', ' в с!акк!с() // "' в с!аккгс(), то есть отсутсгпвне // гРуппировки в1г!лд 1уре ггиепагпе() соле!, // *гаге'в с!акгОс() к1ппу !уре /а!велите() сопк1; // /аде' в с!агкгс() к1аис !оса1ес и! ий ргогес1ег(.
-питрилсг(); // идентификалгор фасета (у Е2, у !.3, т !'3.!) ,г/вггргпуальные гго функигги' (сл, к Е4.!) с1акк Му риис! риб!!с кгг(:питрипсг<сбаг> ( риЫи. гурег!е) сбаг сбаг 1уре; 1урег!е/ к!пну кгппу 1уре; ехр!гсИМу риасйк1ае гг= О) кггг: питрилс1<сбаг>(г) () Символы строки, возвращаемой ктоир(пй(), читаются как последовательность малых целых значений. Каждое число задает количество цифр в группе. Символ номер О определяет крайнюю справа группу (наименее значимые цифры), символ номер 1 определяет группу слева от нее и т.д.
Таким образом, '~004г,002г,003 описывает формат числа вида 123-45 — 6 < г(У (при условии, что вы используете '-' в качестве символа-разделителя). Если есть необходимость, последнее число образца (раыегп) группировки используется повторно, то есть >г,003 эквивалентно "г,003~003г,003'. Само название разделительного символа 1Ьоикапг(к кер() (разделитель тысяч) подсказывает, что группировка чаше всего применяется для более читаемого отображения больших целых. Функции Отоир(ггй() и 1Ьоикапг(к кер() определяют формат как ввода, так и вывода целых. Кроме того, огггл определяют формат для целой части чисел с плавающей точкой, но не цифр после г(ес1та1 рогп1().
Мы задаем новый стиль пунктуации, создавая производный от питрипс1 класс. ((а!гример, я мог бы определить фасет Му рипс1 для записи целых значений тройками цифр с пробелом между ними, а значений с плавающей точкой в европейском стиле — отделяя дробггую часть заггятой: 974 Приложение Г. Локализация рго1ес1е<1: слаг<(о с(ес!та! рош1) соля1( ге1игл '/) // запятая сЬагс(о 16оияапч(я яер()салМ(ге1игл'';) //пробел кгг!пу с!о Вгоир!пу() сопя! (~ егигл "ч003"; ) // группировка по 3 цифры иоЫЯ сои1 « "яе1ргес!к!оп (4) «/)хеч(; саи1 « 'формат А< ' «!2345678 « ' *"* ' «1234.5678 « '~л'; !аса!е1ос(!вса!е(), пеизМу риис!). сои!.илЬие(1ос); саиг« "фоРмат Вз "«!2345678 «" ***' «!234 5678 «нчл', На выходе будет: формат А: !2345б78 "'* !234.5б78 формалз Я: !2 345 б78 '"* ! 234,5б78 Отметим, что ипЬие() хранит копию аргумента в своем потоке. Так что поток может использовать приданную ему локализацию даже после уничтожения исходной копии этой локализации.
Если установлен флаг Ьоо1а1рЬа потока ввода/вывода (9 21.2.2, 9 21.4.1), то для символьного представления 1гие и /а(зе используются строки, возвращаемые 1 иепагпе() и/а(зепате() соответственно; в противном случае используются 1 и О. Имеется и Ьупате версия (() Г.4, 9 ГА.1) питрипсй гетр1асе <с1аяя СЬ> с!ияя яЫ литрипс1 булате: риб!!слитрипс1<СЬ> (/* ... */ ); Г.4.2.2. Вывод чисел Ири записи в о<уфер потока (9' 21.6А), оз1геа испольаует фасет пит ри(: гетр!асе <с1азз СЬ, с1аяя Оиг = ояггеитЬи! Вегасог<СЬ» с!аяя кЫ.пигп риг, риб!!с !оса!е:/асе1 ( рибдс: 1урег/е/СЬ сбаг !уре; 1уре<!еГОиг!1ег !уре.
ехр!(сп пит рис(я!хе 1г= 0), // поместить значение 'и' в позицию '6 буфера потока 'я' Ои1ри1(Ои16, !ая Ьаяей к, СЬ/1К Ьоо! и) солк1, Ои1 ри1(Ои1 6, юя Ьакей я, СЬ /!К !олу о) саля!; Оиг ри1(Ои1 6, !вз Ьаяей з, СЬ/)!!, ипк(уле<! !опи и) сапк1; Оис рис(Ои16, !оя Ьакейз, СЬ71!1, с!оиб!ее) соля!; Ои1 ри1(Ои1 Ь, (ая Ьакей з, СЬ/) !!, !опд доиЫе и) свпз1; Ои!ри1(ОигЬ, !ая Ьакей я, СЬ/)К сопз1 иоЫ' о) солк1, згаас !оса!езЫ Ы; // идентификатор фасета (3 Г,2, 3 ГЗ, 3 Г3. 1) рго1ес1е<1: 975 Г.4, Стандартные фасеты -пит рис)); //виртуозьнл~е "з!о фуннист" !ею у Г4.!) Аргумент Ои! !птератор вывода, см ~ 19.1, 19.2.1) определяет позицию буфера потока Ц 21.6.4), в которую ри1)) помещает символы, соответствующие выводимому числовому значению. Возвращаемое значение ри!() — итсратор, указывающий на позицию, следующую за последним записанным символом.
Отметьте, что специализация по умолчанию пит ри1 (та, чей итератор доступа к символам имеет тип оя1геатЬи/ !1ега1ог<СЬ>), является частью стандартной локализации Ц Г.4). Чтобы воспользоваться другой специализацией, придется создать ее самостоятельно. Например: 1етр!ате<с1азз СЬ> с!изя 51гспу питри1: риЬ!!с я!г!спит ри!<СЬ, 1урепате Ьаис я1алу<СЬ -!1ега1ог> ( риЬ!!с: $1Плу патри!)) за!спит рит<СЬ, турепате Ьаз!с яитпу<СЬ>:!1ега!ог>)!) 1) оо1з!Я!и! Ь я1г!пу' я, !и!роя) // форматирование ~ в з, начинив с познани роя 1 51г!пу питри1<сЬаг Я зоя ЬаяеЕ ххх= сои1; Яра~в Ьеу!п ))» роз, ххх, ' ', !); //форнотнровиние ! в з ) Аргумент юя Ьаяе используется для получения информации о состоянии форматирования и локализации. Например, если требуется заполнить место «водой», используется символ/з!!, как того требует аргумент юя Ьаяе.
Обычно буфер потока, куда пишут через Ь, является буфером, ассоциированным с оя! еагп, для которого я явля- етая базовым классом. Заметим, что сконструировать объект юя Ьаяе не просто. Он, в частности, управляет различными сторонами форматирования, которые должны быть согласованы для получения приемлемого вывода. Соответственно, у зоя Ьаяе нет открьггого конструктора Ц 21.3.3).
Функция ри!)) также пользуется аргументом юя Ьаяе для доступа к !оса!е() потока. Эта локализация нужна для определения пунктуации Ц ГА.2.1), символьного представления булевых значений и преобразований к СЬ, Например, предположим. что я яв.ляется зоя Ьаяе аргументом ри1)); тогда в кодс ри1)) мог бы присутствовать примерно такой фрагмент: сопз1 !оса!ео !ос = я уе!!ос)); звсЬаг 1т = ияе /асе1<с1уре<сЬаг >)!ос)т!с!еп)с)ь // преобразование спагв СЬ О-.
ясг!пури! = изе ~асе1<питрипсг<сЬаг»)!ос) с!ес!та! ро!пт)), // ло уиолнанню '.' П". ятг!пд/!яе = ияе /осе1<питрипс!<сааг»)!осДа!зените)) // ло унолнанию '/а!зе Стандартные фасеты, вроде пит ри1<сЬаг>, обычно использузотся неявно — в функциях стандартного ввода/вывода, — поэтому болыпинству программистов нет необ- Приложение Г Локализация холнмости знать о ннх. Тем не менее, применение подобных фасетов функциями стандартной библиотеки представляет интерес, потому что иллюстрирует работу потоков ввода-вывода н способы обращения с фасетами. Как всегда, стандартная библиотека предоставляет образцы любопытных технологий программирования. Используя пит ри1, разработчик потока вывода оя1геат мог бы реализовать его следующим образом: 1етр!а1е< е!акк СЬ, с1аяя Гг» ок1геа т З к1к!<Ьа к!с ояггеат <СЬ, Гг» серега 1ог«(Мои Ые <й ( яен1гу денга(*1Ь!я).