Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 228
Текст из файла (страница 228)
Полагаясь на <!оз1геагп> и <з1гупу>, пользователь, как правило, может избежать непосредственного использования фасета с1уре. Имеется и Ьупате версия Я ГА, 5 ГА.1) стуре: гетр!иге<с!аяз СЬ» с1аяк яМ сгуре Ьулате: риЬВс ссуре<СЬ' ( /' ... */ ); Г.4.5А . Некоторые удобные интерфейсы Наиболее типичным использованием фасета с1уре является проверка принадлежно- сти символа к некоторой классификации.
Для решения этой задачи имеется следую- щий набор функций: <с1азк СЬ> Ьоо! !зярасе(СЬ с, сопз1 1оса1ей 1ос) <с!азз СЬ> Ьоо! арпа!(СЬ с, сопз1 !оса!ей !ос); <с!азк СЬ> 6оо! йсп1гйСЬ с, сопк1!оса!ей!ос); <с1азя СЬ> Ьоо! Ьзиррег(СЬ с, сопя1 1оса!ей 1ос); <с!аяз СЬ> 6оо! гк!отег(СЬ с, солз1!оса!ей 1ос); <с!ияя СЬ> 6оо1!за1рьа(СЬ с, сопз1 !оса!ей 1ос), <с!аяя СЬ> Ьоо! !зЩ!УСЬ с, сопя! !оса!ей 1ос); <с!азз СЬ> Ьоо! !ярилсг(СЬ с, сопя! 1оса1ей!ос); <с1азз СЬ> Ьоо! !яхс1!у!1(СЬ с, сопя! 1оса!ей !ос); <с!аяз СЬ> 6оо! аи!пит(СЬ с, соля! 1оса!ей !ос); <с!азз СЬ> 6оо! аугарЬ(СЬ с, сопя! !оса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 0 ( ге1игп !зярисе(1, !оса1еЦ; // это почти правда Г.4.6. Преобразование кода символа Иногда представление символов, хранящихся в файле, отличается от желательного представления этих же символов в памяти.
Например, японские символы часто хра- Версии перечисленных функций с одним аргументом, представленные в Я 20А.2), просто являются теми же самыми функциями лля текущей глобальной локализации С (не для глобальной локализации С++ 1оса1е()). За исключением редких случаев, когда глобальные локализации С и Са+ различаются Я Г.23), мы можем рассматривать функции с одним аргументом как двухаргументные функции, использующие 1оса1е(). Например: Приложение Г Локализация 1006 нят в файлах, в которых особые индикаторы (ез)г)Ъ» — <смещения») указывают, к какому из четырех распространенных наборов символов ()сап)), )сага)сапа, )з)гадапа или гошар) принадлежит данная последовательность символов.
Такой способ несколько неуклюж, так как значение каждого байта зависит от чсостояния смещения» (з)ч)(с зсасе). Зато экономится память, потому что только )сап)З требует более одного байта па символ. В памяти компьютера символы проще обрабатывать, когда они представлены в виде многобайтного набора символов, в котором размеры представления всех символов одинаковы. Такие символы (например, коды ()п)сос)е) обычно хранятся в виде расширенных символов (шс/саг г $4.3). Вот почему фасет сос(есо! предоставляет механизм преобразования символов из одного представления в другое в процессе пх чтения и записи.
Например; Представление на диске ~ ~13 Преобразования ввода-вывода под управлением соаСесп! Представление в памяти ~~Пп)сос)е ~ Этот механизм преобразования кода является достаточно общим для реализации произвольных преобразований представлений символов. Он позволяет писать программы, использующие удобное внутреннее представление символов (хранимых в виде с/саг, шс/саг 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) соле!, 1007 Г4.
Стандартные Фасеты геяи11 ои1(51а1ей, сопя1х. Ггот, сопя1 3'/гот епд, сопя13'й~тот пех1, // запись Е' 1о, Е" 1о епгц Е Ыо пех1) сопяг; гезий ипяй(/1(51агес< Е" 1о, Е" 1о епд, Е'й 1о пех1) сопя1; // конец последова// тельности сил~волов т1 епсог/гпц» сопя1 гй оиз(1 Ьоо! а1тауя посоли() сопя1 1йгов»; //хорактеризует основные свойство // кодирования // можно выполнять ввод/вывод // без преобразования кодов? т1 ?епугй(сопя1 51агей, сопя1 Е" /гот, сопя1 Е* 1гот епс1, ягее 1 игах) сопя1; ии ток 1епутй() сопя1 гйгои(1 //х~аксихтльно возможная 1епугй() я1аис 1оса1е:Ыгсй //идентификаторфасета (у 1.2, у ГЗ, З /лй1) рго1ес1ес1 -сос(есог»; //виртуальные 'до функции" (ель З Г4.1) ); с1 а як Л5я 1а 1е ( /* ..
*/ ); р = пегосодесо1<тсйаг 1, сйаг, тйя1а1е 1>; //стандартный слоге тсйаг 1 у= петсодесо1<ихйаг 1, сйаг, Л5я1а1е>; //Л5 в тс6аг 1 Без аргумента 51а1е не супгествовало бы способа сообщить фасету, в какой кодировке воспринимать поток символов сйаг. Тип тйьта1е 1 из <сзвсйаг> или <госйаг.й> идентифицирует стандартное системное преобразование между сйаг и юсйаг 1. Можно также создать новый ссп1есь1 в качестве производного класса, идентифипнруелюго по имени. Например: с1аяя Л5сот: риЬИс содесст<тсйаг 1, сйаг, тбяга1е 1> ( /' ...
*/ ); Вызов 1п(я,/гот,/гот епгЦгот лех1, 1о, 1о епг(, 1о лех1) читает каждый символ диапазона ф.от,/гот епс() и пытается преобразовать его. Если символ можно преобразовать, сл() записывает преобразованное значение в соответствующую позицию диапазона [1о, 1о епс(); если нет — т() завершает выполнение в этом месте. По завершении, 1л() сохраняет указатель на символ, следующий за последним прочитанным, в/гот пех1, а указатель на символ, следующий за последним записанным, — в 1о пех1. Значение геяи11, возвращаемое 1п(), указывает, какая часть работы проделана: ой: преобразованы все символы диапазона [Г, от,/гот епс() раг/1а1; преобразованы не все символы диапазона [ггот,/гот епг/) еггог.
функция т() встретила символ, который не смогла преобразовать посоли: преобразования не потребовалось Фасст сос(есо1 используется Ьая(с ЯеЬи/' (» 21.5) для чтения н записи символов. Этот фасет Ьая(с Щейи/'получает из локализации потока Я 21.7.1). Аргумент шаблона 51а/е является типом, используемым для хранения состояния смешения преобразуемого потока. Тип 51а1е также может использоваться для идентификации различных преобразований путем задания специализации (зрес)а1(хат(оп).
Последний механизм полезен, поскольку символы из разнообразных кодировок (наборов символов) могут храниться в об ьектах одного и того же типа. Например: зоов Приложение П Локализация Вызов а(гоауя посоли() возвращает! ие, если не требуется никакого преобразования между внутренним и внешним наборами символов, и /а!ее — в противном случае.
Очевидно, что а!шауя лосолп(]= 1гие открывает возможность для обеспечения максимально эффективной реализации, которая просто не задействует функции преобразования. Вызов тах 1елу1Ь() возвращает максимальное значение, которое может вернуть 1елу/Ь() при корректном наборе аргументов. Простейшие преобразование кодировки, которое я смог придумать — это преобразование входных символов из нижнего регистра в верхний, Так что ниже представлен, вероятно, простейший из возможных классов содесо1, который, однако, делает нечто полезное: с1авя СШ го иррег риЫ/ссойесо1<сбог,сбаг, тбя1а1е 1» ( ехр1ЩНСИ 1о иррег(яеее 1г- д).
сос(есв1(г) () // преобразование // в верхний регистр Обратите внимание, что результат раг11а! не обязательно свидетельствует об ошибке. Возможно, придется прочитать больше символов, чем планировалось, чтобы завершился ми о го байтный символ, и чтобы его можно было записать; или следует очистить буфер вывода, чтобы освободить место для других символов.
Аргумент я типа Яа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елу1Ь(я,/гот, (гот епс(, тах) возвращает количество символов из ) /гот, 1гот елс1), которое га() может преобразовать. Функция елсос//лу() возвращает -! если кодировка внешнего набора символов использует состояние (згасе) (например, использует последовательности символов, означающие установку и сброс смещения) 0 если кодировка использует различное количество байт для представления отдельных символов (например, представление символов может использовать бит в байте для указания, один или два байта используются в представлении данного символа) и если каждый символ во внешнем представлении занимает и байт Г.4.
Стандартные фасеты 1009 рго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 тих) сопя1; 1п1йо тах 1епуеЬ~ сопк11Ьгов(); )' сойесс1«сйаг, сйаг, тбя1а1е режекий СЫ 1о ирреггйо 1л(31а1е& я, сопя1 сйаг" (гот, сопя! сйаг'(тот епй, сопя1 сйаг & ,(гот лех1, сйаг' 1о, сйаг' 1о елй, сйаг"& 1о пех1) солИ // ...
ф Гб(1б(,, !отта(п() // тривиальний тесгп 1оса!е и(оса1е(1оса1е(), лев СЫ 1о иррег); с(п.!тйие(и1оса1е). сйаг сй; вй1(е(с1п> сй) сои!«сй; Имеется и версия сойесо1 вида булате (9 Г 4, () Г.4.1): 1етр! а1е «с! аяк 1, с(акя Е, с(акя Ыа1е> с!акя яйй сойесо1 Ьупате: риЫ!с сойеси1«ЕЕ,Б1ате> (/" ...