Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 228
Текст из файла (страница 228)
3Р.4.!) )< Вызов й ( т, с) проверяет, принадлежит ли символ с классификации т. Например; ш< соил< зрасея (сопел я<лиль з, соли <оса1еь 1ос) ( сот< с<уре<слаг> ь с< = ияе /асс«с<уре<слаг» (<ос) 1п<1 = О< )ог(я<с<ил«соля< 1<ега<огр = з.Ьел(л () < р ! = я.еп«О; ++р) (< (с<.1я(с<уре Ьаяе: <зрасе, *р) ) +я<! //символ пробела в соответствии с с< ге<игл «' ) Обратите внимание, что Ы() можно использовать для проверки принадлежности символа к одной из нескольких классификаций. Например: с<.Ь(обре Ьаы: <зрасе(сбрь Ь<пе::рипа<,с) < //с в с<-пробел симл или знак пунктуации? Вызов Ы(Ь, е, г) выявляет классификацию каждого символа из (Ь, е) и помещает ее в соответствующую позицию массива к Вызов звал Ь(т, Ь, е) возвращает указатель на первый символ из [Ь, е), который есть т.
Если нет символов, относящихся к классификации т, то возвращается е. Как всегда для стандартных фасетов, открытые функции-члены реализованы путем вызова своих виртуальных "<(о-функций". Простая реализация может выглядеть следующим образом: [).4 Стандартные фасеты 1065 гетр1аге<<1азз СЬ> соне( СЬ* зга'::е(уре<СЬ>::ао зсап 1з(таял т, еопзг СЬ* Ь, сопи СЬ* е) сопи ( вЫ(е(Ь! =е аз ! 1з(т, *Ь) ) ++Ьг ге(ига Ь; ) Вызов зсаи иот(т, Ь, е) возвращает указатель на первый символ из [Ь, е), который не есть т.
Если все символы относятся к классификации т, то возвращается е. Вызов тоиррег(с) возвращает с в верхнем регистре, если это допустимо в используемом наборе символов; или сам с в противном случае. Вызов(овррег(Ь,е) конвертирует каждый символ из интервала [Ь,е) в верхний регистр и возвращает е. Простая реализация может выглядеть следующим образом: гетр1аге<е1азз СЬ > еонзг СЬ* зЫ::е(уре<СЬ>::(о нррег(СЬ* Ь, еопзг СЬ* е) ( уог(; Ь(=ег +«Ь) *Ь = гоиррег(*Ь) г гиигп е; ) Функция то1овег() аналогична функции гоиррег(), но только конвертирует символы в нижний регистр.
Вызов вЫеп (с) преобразует символ с в соответствующее значение СЬ. Если набор символов СЬ располагает несколькими символами, соответствующими с, то согласно стандарту используется «простейшее разумное преобразование». Например; всои«<изегаеег<е(уре<велаг г» (вени(.ее(1ое () ) . вЫеп ( ' е' ); выведет разумный эквивалент символа е в контексте локализации потока всоиг. С помощью вЫеи () можно осуществлять и преобразования между не связанными друг с другом представлениями символов, например АБСП и ЕВСР[С. Например, предположим, что существует контекст локализации еЬсйс: слог ЕВСШС е = изегаеег<е(уре<елаг» (еЬ<аге) . вЫеп ( ' е' ) Вызов вЫеи (Ь, е, е) берет каждый символ из интервала [Ь, е) и помещает расширенную версию в соответствующую позицию массива к Вызов паееов(сЬ, з[ег) выдает значение айаг, соответствующее символу сЬ типа СЬ.
И снова используется «простейшее разумное преобразование». Если не существует айаг, соответствующего сЬ, то возвращается з(еу. Вызов иаггов(Ь, е, Нег', о) берет каждый символ из интервала [Ь, е) и помешает суженную версию в соответствующую позицию массива и Общая идея состоит в том, что пагеов( ) преобразует из более широкого набора символов в более узкий, а вЫеи () — наоборот. Для символа с из более узкого набора мы ожидаем, что е == паггов(вЫеп(с),а) ~Уне гарантируется Это справедливо при условии, что символ, соответствующий с, имеет единственное представление в более узком наборе символов. А это не гарантируется.
Если символы, представимые с помощью айаг, не составляют подмножества большего Приложение (). Локализация 1066 набора символов типа Сй, то следует ожидать проблем в коде, работающем с зсимволами вообще». Аналогично, мы могли бы ожидать для символа сй из более широкого набора символов, что югЫси(титан (сй,юЬ!) ) == ей )! вЫеп(лагююг(сй,ю(а1) ) == лаЬи(~Ц) Рнегарапли»ЮВетсз Тем не менее, хотя чаше всего зто и так, невозможно дать такую гарантию для символов, имеющих несколько значений в расширенном наборе и лишь одно— в более узком наборе символов. Например, число 7 часто имеет несколько представлений в расширенных наборах. Причина здесь в том, что, как правило, большие символьные наборы содержат несколько обычных наборов символов в качестве подмножеств, и символы из меньших наборов реплицируются для удобства преобразования.
Для каждого символа из базового наборам символов (ВС.З.З) гарантируется, что ю»Ыеи (паггоюг(сй Вю, О) ) == сй 1!ю Например: нЫеп(паггои ( 'х',О) ) == 'х' Функции па!тол () и иЫеп() соблюдают классификацию символов насколько возможно. Например, если справедливо Ь(а!рйа, с), то также справедливы Ь(а1- рйа, иаггоюз(с, 'а' ) ) и Ь(а!рйа, иЫеп(с) ), пока а1рйа является корректной маской для текущего контекста локализации. Основной причиной использования фасета сюуре вообще и функций паггоюз() и и1ю(еп () в частности является написание кода, который осуществляет ввод/вывод и манипулирует строками для любого набора символов. Отсюда следует, что реализации юозлеат сильнейшим образом зависят от зтих средств. Опираясь на <1ояюгеат> и <яюг!ид>, пользователь может избежать непосредственного использования фасета стуре.
Для фасета сзуре имеется и Ьупате-версия (ВР.4, Вюю.4.)): гетр!а(с<с!ам С1ю> сюазя яЫ:: сюуре Ьупатс: риЫюс сюуре<сй> (1*...*I ); 0.4.5.1. Вспомогательные шаблоны функций Наиболее типичным применением фасета с(уре является проверка принадлежности символа к некоторой классификации. Для решения этой задачи имеется целый набор шаблонов функций: юетр1аюс< с1ат юеюпр(аюе<с1ат юетр!аюе<с1ат юетр!а!с<с(ат гетр!а!с<с!азз юеюпр!а!с<с!ат юеюир1аюе<с1ат юетр1аюе<с1ат юетр1аюе<с1ат юетр1аюе<с1ат юеиюр1аюс<с!ат Сй> Ьоо1 СЬ> Ьоо1 Сй>Ь 1 Сй> Ьоо1 СЬ>Ь 1 СЬ> Ьоо( сь> ь Сй> Ьоо1 СЬ> Ьоо( сь> ь Сй> Ьоо1 Ьярасс (Сй с, солт 1оса1еь 1ос); Ьрппю(Сй с, солт 1осаюеь!ос) ю 1зспюг1 (Сй с, сопя! 1оса1еь 1ос) ю Ьиррег(Сй с, сопя! юоса1еь 1ос) ю Ь1оисг (Сй с, сопя! 1оса1еь 1ос) ю Ьа1рйа (Сй с, соля! 1оса!еь 1ос) ю (зюю(Л(ю(Сй с, солт юосаюеь 1ос) ю Ьрилсю(Сй с, сопи 1осаюеь 1ос) ю 1яхйя(ю (Сй с, сопя! 1оса1еь 1ос) ю Ьаюиит (Сй с, соиюю юосаюеь 1ос) ю (загарй (Сй с, солт юосаюеь 1ос); 1067 (з.4.
Стандартные фасеты Эти функции тривиально реализуются при помощи фасета иве 1асег. Например; гетрЬив<с(ат СЬ> 1п1те Ьоо( Ьврасе(СЬ с, сопят 1оса1ва 1ос) ( ге!игл иве !асс!<с(уре<СЬ» (1ос) .Ь (красе, с) ) Версии перечисленных функций с одним аргументом, представленные в $20.4,2, являются теми же функциями для текущего глобального контекста локализации С (но не для 1оса1е() языка С++). За исключением редких случаев, когда глобальные контексты локализации С и С++ различаются (5().2.3), мы можем представлять себе одноаргументные версии как двухаргументные, использующие 1оса1е().
Например; !папе тг Ьвросе (1п11) ( гвгигп Ьврасв (г', 1оса1е () ) г II почти всегда 0.4.6. Преобразование кодов символов Иногда представление хранящихся в файле символов отличается от их желаемого представления в оперативной памяти. Например, часто японские символы хранятся в файлах, в которых используются специальные индикаторы для указания, к которому из четырех распространенных символьных наборов 1Ьап11, ЬатаЬапа, Ьггаяапа, гота!!) они принадлежат. Это немного неудобно, поскольку смысл каждого байта зависит от состояния смещения (вЬ))т зтаге), В то же время, это экономит память, поскольку лишь Ьап)! требует для представления символов более одного байта. В памяти компьютера символы проще обрабатывать, если они представлены мультибайтными символьными наборами (кодировками), в которых каждому символу соответствует одно и то же количество байт.
В таких случаях (например, в случае кодировки ()шсобе) символы хранятся в памяти в виде расширенных символов (звсьаг г, з4.3). Вот почему имеется фасет соыесгг для преобразования символов из одной кодировки в друтую при их чтении и записи. Например: Дисковое представление Преобразования прн вводе/выводе нод управлением содесгт Представление в памяти ()л)соде Этот механизм преобразования кодировок является достаточно общим для реализации произвольных преобразований представлений символов.