Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 216
Текст из файла (страница 216)
(3] Локализация 1оса1е используется в операциях ввода/вывода, от которых требуют эффективности па этапе исполнения. [4] Локализация 1оса1е должна быть невидима для большинства программистов, желающих воспользоваться «правильно работающим> потоком ввода/вывода, и не желающих разбираться в том, что это значит и как достигается. (5] Локализация 1оса1е должна быть доступна разработчикам средств, зависящих от культурных особенностей, помимо библиотеки потоков ввода/вывода.
Проектирование программы, осуществляющей ввод/вывод, связано с выбором между управлением форматированием при помощи «ооычного кодаь или посредством локализаций. Первый !традиционный) подход приемлем в случаях, когда есть уверенность, что каждая операция ввода может быть легко преобразована из одной системы соглашений в другую. Однако, если требуется изменить формы отображения встроенных типов, или нужны различные наборы символов, или приходится иметь в виду расширяемый набор связанных со вводом-выводом соглашений, механизм 1оса1е выглядит более привлекательно. Локализация (!оса/е) состоит из фасетов !/асе1), управляющих отдельными со' глашениями, такими как символ-разделитель при отображении чисел с плавающей точкой 1с(ес!та1 ро/п1(); 9 ГА.2) и формат, используемый при чтении денежных величин /топеурипс1 9 Г.4З).
Фасет является объектом класса, производного от класса 1оса1е: /асе1 (ч Г.З). Мы можем рассматривать 1оса1е как контейнер фасетов Гасе! Я Г.2, ~ Г.3.1). Г.2. Класс 1оса1е Класс 1оса1е и связанные с гшм средства представлены в <1оса1ехз с!азз зШ !оса!е ( рибате. с1азз /асе1; // тип представления фасетовлокализации; у Г3 с1азз !с); // тип для идентификп иди локолизаь,ни; Э !.3 1уреь/е/гп1са1еуогу; // тип для разбиения грасетов на категории з!анс сопз1са1еуогу //настоян!ив значения определя~отся реоливациеи поае= О, соуа1е = 1, 0сравнения с1уре = 1«1, топе!агу = 1«2, питег/с = 1«3, йгпе =!«4, теззадез = 1«5, а!! = со!!а1е ) с1уре) топе!агу) питег!с(1/те ( теззауез, 1оса1е() %гасо(); // копия глобальной локализаиии !Э' Г 2.1) 1оса1е(сопя! !оса!ес,х) гйгого(1 // копия х Приложение П Локализация 952 ехр!(с(1 !оса(е(сопя( сбаг* р); // копил локализации с ииенел р Я Г 2!) 1етр(аге<с1аяя Гасе(> 1оса1е(сопя( (оса1ей х, Гасе(*/), // копил х плюс фасет/ (етр(а1е<с(аяя Гасе(> (оса1е сотбеае(сопя( 1оса(ей х); // копил *(бм плюс фасет // Гасе1 иэ х сопя((оса1ей орега1ог=(сопя1 (оса(ей х) 1Ьгота(), Ьоо( орега!от==(сопя11оса(ей) сопя!; //сравнениелокалиэаций ба о! орега1ог1=(сопя1 (оса(ей) сопя1; я(г!пупате() сопя1; //аил даннойлоквлиэации 1етр(а1е <с!аяя СЬ, с!аяз Тг, с1аяяА' // сравнение строк в данков локвлиэации боо( орега1ог() (сопя1 базис я1г(пд<СЬ,ТгА>й, сопя( бая!с я1г!пу<СЬ,ТгА>й) сопя(; я(а(!с1оса!еу!оба((сопя!(оса(ей); //устанавливает новую,медальную //локолиэицию и возвращает старую я!аис сопя! (оса!ей с(аяз!с('1 // воэврвп!ает классическую' // локализацию в стиле С рг(оа1е: // представление Класс 1оса1е можно рассматривать как интерфейс к тар<Ы, /асе('>, а именно, в каче- стве средства, позволя!ощего нзм пользоваться 1оса1есЫ для поиска соответствую- щего объекта класса, производного от (оса1е: /асс(.
Настоящая реализация 1оса(е яв- ляется эффективн!ям вариантом этой идеи. Схема выглядит примерно так: со11а1е<сйаг> 1оса1е сотраге() ЬаяЬ() Здесь со((а1е<сйаг> н питрипс1<сЬаг — стандартные библиотечные фасеты Я р.4). Как и все фзсеты, они произведены от (оса(е: /асе(. Предполагается, что локализации можно легко и лешево копировать. Следовательно, почти наверняка локализация реализована в виде вспомогательного класса 1(эапс((е) по. отношению к специализированному тар<Ы, /асе1">, представляющему собой основную часть реализации, Доступ к фасетам локализации должен осуществляться быстро, поэтому специализированный тар<Ы,Тасе~*> оптимизируется для -1оса1е() (бган(); (оса(е(сопя(! оса(ей х, сопя! сбаг* р, со1еуогу с); 1оса(е(сопя( (оса1ей х, сопя! !оса!ей у, са1еуогу с), трипс(<сйаг: о с(ес(та( ро(п1() (гиепате() // копил х плюс фа сети // категории с пэ р // копая х плюс фасети // категории с иэ у 953 Г2.
Класс !оса!е обеспечения быстрого доступа наподобие массива. Доступ к фасету локализации осуществляется при помощи нотации азе ~асе!«Расе(>((ос); см. 9 Г.З.1. Стандартная библиотека предоставляет богатый набор фасетов. Чтобы помочь программистам обращаться с фасетами, стандартные фасеты подразделяются на категории, такие как питег!с или со((а(е (9 Г.4). Программист может заменять фасеты в сушествуюших категориях (9 Г.4, 9 ГА.2.1), Однако невозможно добавить новые категории; не существует способа определить новую категорию программным путем.
Понятие «категория» применимо только к фасетам стандартной библиотеки и не является расширяемым. Таким образом, фасет не обязан принадлежать к какой-либо категории, и существует множество определенных пользователями фасетов, ие принадлежащих ни к одной из ннх. По большей части локализации используются (неявно) в потоке ввода/вывола. У каждого потока ввода !з! еат и потока вывода оз( еат имеется собственная локализация 1оса1е.
По умолчанию, локализацией потока является глобальная локкпьззация (ч Г.2.1) при его созлании. Задать локализацию потока можно прп помощи операции !тбае0, а извлекается копия локализации потока посредством де((ос() (ч 21.6.3). Г.2.1. Именованные локализации Локализация конструируется из некоторой другой локализации н пз фасетов. Самым простым способом создания локализации является копирование сушеству!ошей. Например: 1оса1е 1осй, // копия текущей глобальной локолизпции 15 Г23) (оса1е(ос1 = 1оса(е(); // копия текущей глорольной локализации Ц Г,2.3) (оса(е (ос2( "); // копия 'предпояитаелюй пользовагпелелслоксьзизаг!ии' !осо(е (ос3('С ); // копия локсыизиции О" (оса!е (осе = (оса!езс(азз!с() // копия локгь«изиции 'Г 1осо!е (осб("РОВ(Х ) // копи определяемой реализацией локплизоцип "РОЯХ" Значение 1оса1е("С") опрслелено стандартом в качестве «классической» локализации С; именно зта локализация подразумевалась на протяжении всей книги.
Все другие имена локализаций определяются реализацией. Выражение (оса(е('") считается «предпочитаемой пользователем локализацией» Эта локализация устанавливается неязыковымн средствами в среде исполнения программы. В большинстве операционных систем имеются способы установки локализации для программы. Часто подходящая для оператора локализация выбирается в момент начала работы с системой. Например, я полагаю, что пользователь, настроившийся на аргентинский испанский в качестве языка по умолчанию, обнаружит, что1оса1е("") означает для него 1оса1е("ез А(1').
Быстрая проверка обнаружила в одной из моих систем 51 локализацию с мнемоническими именами, такими как РОЯХ, г(е, еп ((К, еп (/Я,ез,ез АР, (г,зо,с(а,р(и(зо ВВ59 1. РОЯ!Хрекомендуетимена, начииаюшиеся с названия языка стро !ными буквами, за которым может следовать название страны прописными буквами, за которым может следовать спецнфикатор кодировки. Например, (р /Р(!!. Однако зги имена не стандартизованы для всех платформ. В другой системе, среди многих других имен локализаций, я обнаружил й, ий, из, з, /д 954 Приложение Г Локализация зш и ь!а. Стандарт Сз-.ь не опрелеляет смысл локализации для данной страны пли языка, хотя на конкретных платформах такие стандарты возможны.
Поэтому при обращении к именованным локализациям программисту следует полагаться на системную документацию и опыт. Как правило, нецелесообразно включать в текст программы строки имел локзлизаций, Ссылка па имя файла нли системную константу в тексте программы оз.раничивает переносимость этой программы и часто вынуждает программиста, желающего адаптировать программу к новой среде, искать и изменять подобные значения.
Использование строки с именем локализации влечет аналогичные последствия. С другой стороны, локалзизации можно получить из среды исполнения программы (например, воспользовавшись 1оса1е("')), или программа может предоставить опытному пользователю возможность задания альтернативной локализации путем ввода соот'ветствузощей строки. Например; ооЫизег зе1 1оса1е(сопз! зйдпуйдиеваоп зггепу) сои! «диезиоп згг!пу; // поприпер, 'Если требуепмя другая // локализация, введипзе ее илзя' зЖпуз; с1п» з; 1оса1егу1оба!(!оса1е(з.с згг0)); // установить в качестве глобальной // указанную пользователея локализацию ) Как правило, лучшим решением для менее опытного пользователя будет предоставление списка альтернатив. Соответствующая процедура должна знать, где и как система хранит свои локализации.
Если строковый аргумент не ссылается на реально определенную локализацию, конструктор генерирует исключение гипгипе еггог (9 14.10). Ншзример: оо!с!зе1 1ос(!оса!ей 1ос,сопя!айаг" пате) 1гу ( 1ос = 1оса1е(пате); са1с1з (гнийте еггог)( сегг « "локализация з" «пате « "1' не определена'зп'; // -. Если 1оса1е имеет имя, его можно получить в качестве возвращаемого значения функции пате(). Если нет, пате() вернет з1г!пу(чч ), Строка имени, во-первых, служит средством для образценпя к локализации, имеющейся в среде исполнения. Во-вторых, строку имени можно использовать для отладки.
Например; оо!дрг!пг 1оса!е патез(сопзг !оса!ей ту 1ос сои! « 'имя текущей глобальной локализации:" «1оса1е().пате() « "1п", сои! « "имя классической локализации Сг ' «!оса!есс1азз/с().пате() «1п'; сои! «имя предпочитаемой пользователем локализации «1оса/е("").пате() « "зп'; 955 Г 2, Класс (оса(е сои(« 'имя моей локализации: "«ту !оспате() « '~п'; Локализация Строка имени (оса(е("Роо") 1оса1е(1ос) 1оса1е(1ос, ГРоо", са() "Роо' (ос.пате() Новая строка имени, если таковая имеется у (ос; в противном случае — з(г(пЯ ") Новая строка имени, если таковые имеются у 1ос и (ос2; в противном случае — з(г(па('*") з(г(па("" ) з(г(пй("'") 1оса1е(1ос, 1ос2, са() (оса1е(1ос, Расе!) 1ос.сотб(пе((ос2) Не сугцествует средств, которыми программист мог бы задать имя вовой локализа- ции С-строкой.