Internacionalizace a lokalizace v C++

╙dy ₧lutΘho kon∞

Opravß°i pr² zkouÜeli dßlnopisy na v∞t∞ quick brown fox jumps over the lazy dog. Tato v∞ta obsahuje vÜechna pφsmena anglickΘ abecedy a zkontrolovat, zda se napsala sprßvn∞, je snazÜφ, ne₧ kontrolovat jednotlivß pφsmena. V ΦeÜtin∞ se k podobnΘmu ·Φelu pou₧φvß v∞ta ₧lu¥ouΦk² k∙≥ p°φÜern∞ ·p∞l ∩ßbelskΘ ≤dy, ta obsahuje vÜechna Φeskß pφsmena s diakritick²mi znamΘnky.

V tomto Φlßnku se nebudeme zab²vat dßlnopisy, ale programy v C++ a jejich zachßzenφm s neanglick²mi jazyky a s neanglick²m nßrodnφm prost°edφm. P°itom si pochopiteln∞ vÜimneme zvlßÜt∞ ΦeÜtiny a ΦeskΘho nßrodnφho prost°edφ a jako p°φklad p°itom budeme pou₧φvat zmφn∞nou v∞tu o ₧lutΘm koni.

Budeme tedy hovo°it o nßstrojφch, kterΘ usnad≥ujφ internacionalizaci, resp. lokalizaci program∙. (Zßle₧φ na ·hlu pohledu: Chce-li autor sv∙j program prodat do zahraniΦφ, musφ ho internacionalizovat, kupujφcφ, kter² chce program p°izp∙sobit mφstnφm zvyklostem, ho lokalizuje.)

O co jde

Na prvnφ pohled by se mohlo zdßt, ₧e problΘmy s pou₧φvßnφm nßrodnφho jazyka (tedy libovolnΘho jazyka jinΘho ne₧ angliΦtiny) v programech konΦφ zvlßdnutφm pat°iΦnΘ k≤dovΘ strßnky, v∞c je ale slo₧it∞jÜφ: Mß-li se program chovat podle mφstnφch zvyklostφ, musφ vedle Φtenφ a zßpisu znak∙ odpovφdajφcφ abecedy um∞t takΘ

Nejmodern∞jÜφ programovacφ jazyky, jako je Java nebo C#, tyto problΘmy um∞jφ °eÜit. V jazycφch C a C++ to v poΦßtcφch tak samoz°ejmΘ nebylo. OvÜem jazyk C++ podle standardu ISO 14882 z r. 1998 u₧ obsahuje °adu nßstroj∙, kterΘ umo₧≥ujφ tyto problΘmy zvlßdnout. Jde p°edevÜφm o

P°i jejich pou₧φvßnφ ale m∙₧eme narazit na °adu problΘm∙. NejobvyklejÜφ z nich je, ₧e tyto nßstroje jsou v p°ekladaΦφch implementovßny s chybami nebo nejsou implementovßny v∙bec. NicmΘn∞ to se m∙₧e v dohlednΘ dob∞ zm∞nit, proto je nezbytnΘ je znßt.

Lokßlnφ nastavenφ a jeho jmΘno

T°φda locale je definovßna ve standardnφ hlaviΦce locale. Mß °adu konstruktor∙, z nich₧ asi nejd∙le₧it∞jÜφ mß jako parametr znakov² °et∞zec obsahujφcφ jmΘno lokßlnφho nastavenφ:

explicit locale( const char* _Locname );

Zadßme-li nesprßvn² °et∞zec nebo ukazatel s nulovou hodnotou, vyvolß tento konstruktor v²jimku typu runtime_error.

JmΘno lokßlnφho nastavenφ
Zde ovÜem narazφme na prvnφ problΘm: JmΘna lokßlnφch nastavenφ nejsou standardizovßna. Obvykle majφ tvar

Jazyk[_stßt[.k≤dovßnφ]]

LomenΘ zßvorky zde oznaΦujφ Φßsti, kterΘ lze vynechat û pak se doplnφ implicitnφ hodnota danß p°ekladaΦem a operaΦnφm systΘmem. ╚asto se ovÜem pou₧φvajφ i r∙znΘ jinΘ zkratky. Nap°φklad pro ΦeÜtinu se m∙₧eme setkat s °et∞zci "czech", "csy", "cs_CZ" a jin²mi, pro slovenÜtinu lze vid∞t °et∞zce "slovak" nebo "sky". Pro angliΦtinu najdeme "en_UK" (Velkß Britßnie), "en_US" (SpojenΘ stßty) nebo "en_AU" (Austrßlie). Ne vÜechny °et∞zce jsou ale k dispozici ve vÜech prost°edφch.

Proto₧e jmΘna lokßlnφho nastavenφ nejsou, jak u₧ vφme, standardizovßna, musφme odpovφdajφcφ informace zpravidla hledat v dokumentaci k p°ekladaΦ∙m. (Ta nßs ovÜem nemΘn∞ Φasto odkß₧e na dokumentaci k operaΦnφmu systΘmu.)

Vedle °et∞zc∙, p°edstavujφcφch r∙znΘ jazyky a stßty, m∙₧eme konstruktoru t°φdy locale p°edat °et∞zec "C", kter² oznaΦuje tradiΦnφ nastavenφ v jazycφch C a C++, nebo prßzdn² °et∞zec "", reprezentujφcφ äu₧ivatelem preferovanΘ nastavenφô, tedy zpravidla implicitnφ nastavenφ na danΘm poΦφtaΦi. Nejb∞₧n∞jÜφ komerΦnφ p°ekladaΦe na PC pod Φesk²mi Windows p°i tΘto volb∞ nastavφ ΦeskΘ prost°edφ s k≤dovou strßnkou 852 nebo 1250.

DalÜφ mo₧nostφ m∙₧e b²t °et∞zec "POSIX", jeho₧ v²znam zßvisφ na implementaci.

ZjiÜ¥ujeme jmΘno lokßlnφho nastavenφ
┌plnΘ jmΘno lokßlnφho nastavenφ lze zjistit pomocφ metody name(). Jestli₧e nap°. napφÜeme ve Visual C++ .NET nßsledujφcφ program,

#include <iostream>
#include <locale>
#include <stdexcept>
using namespace std;
int main()
{
        try{
                locale L1("czech");
                cout << L1.name() << endl;
        }
        catch(runtime_error &e)
        {
                cout << e.what() << endl;
        }
        return 0;
}

dozvφme se, ₧e ·plnΘ jmΘno lokßlnφho nastavenφ pro ΦeÜtinu ve Windows NT nebo Windows 2000 je

Czech_Czech Republic.1250

Toto jmΘno samoz°ejm∞ m∙₧eme takΘ pou₧φt pro zadßnφ mφstnφho nastavenφ. Vedle k≤dovΘ strßnky 1250 v n∞m m∙₧eme specifikovat i k≤dovou strßnku 852, kterß se pou₧φvß p°i v²stupu na konzolu. ┌plnΘ jmΘno odpovφdajφcφho nastavenφ je Czech_Czech Republic.852.
Jestli₧e zadßme nap°. °et∞zec Czech_Czech Republic.88592, vznikne v²jimka a program vypφÜe nap°.

bad locale name

nebo

System does not recognize this locale name

nebo¥ takovΘto lokßlnφ nastavenφ nenφ k dispozici. (K≤dovßnφ ISO 8859-2 se skr²vß pod oznaΦenφm "Czech_Czech Republic.28592", ΦeÜtina pro poΦφtaΦe MacIntosh je k dispozici pod jmΘnem "Czech_Czech Republic.10029").
Pou₧ijeme-li v konstruktoru t°φdy locale °et∞zec "slovak", zjistφme, ₧e ·plnΘ jmΘno nastavenφ pro slovenÜtinu je

Slovak_Slovakia.1250

╪et∞zec "german" zp∙sobφ, ₧e program vypφÜe

German_Germany.1252

zadßnφ "english" dß v²sledek

English_United States.1252

Poznamenejme, ₧e v °et∞zci, kter² je parametrem konstruktoru t°φdy locale, m∙₧e zßle₧et na velikosti pφsmen. ╪et∞zce "czech" a "Czech" sice v p°ekladaΦi pro Windows znamenajφ totΘ₧, ale "C" znamenß nastavenφ obvyklΘ v jazycφch C++ a C, zatφmco "c" znamenß katalßnÜtinu ("Catalan_Spain.1252").

Pou₧φvßnφ lokßlnφho nastavenφ
Pokud znßte prßci s lokßlnφm nastavenφm v jazyce C, vφme, ₧e v n∞m lze pomocφ funkce setlocale() ze standardnφ hlaviΦky locale.h p°edepsat lokßlnφ nastavenφ pro cel² program. Tφm urΦφme zp∙sob psanφ desetinnΘ teΦky nebo Φßrky p°i v²stupu pomocφ funkcφ z rodiny printf(), formßt data a Φasu vrßcenΘho pomocφ funkce strftime() a n∞kterΘ dalÜφ v∞ci.
V jazyce C++ m∙₧eme na û rozdφl od jazyka C û pracovat s n∞kolika r∙zn²mi lokßlnφmi nastavenφmi. Dßle uvidφme, jak je lze pou₧φt k porovnßvßnφ °et∞zc∙, k ovlivn∞nφ r∙zn²ch datov²ch proud∙ atd.

Chceme-li pou₧φt n∞kterΘ lokßlnφ nastavenφ jako globßlnφ (aby ho mohly pou₧φvat mj. i funkce z jazyka C), pou₧ijeme statickou metodu global(), kterΘ jako parametr p°edßme instanci t°φdy locale p°edstavujφcφ nastavenφ, kterou chceme pou₧φvat jako globßlnφ. Tato metoda zßrove≥ vrßtφ p°edchozφ nastavenφ. Nap°φklad p°φkazy

locale LocNove("Czech_Czech republic.1250");
locale LocStare = locale::global ( LocNove );

urΦφ jako globßlnφ nastavenφ popsanΘ prom∞nnou LocNove a zßrove≥ ulo₧φ do prom∞nnΘ LocStare dosavadnφ nastavenφ.

Znaky nßrodnφch abeced

Mßlokter² evropsk² nßrod vystaΦφ s pφsmeny latinskΘ abecedy bez diakritick²ch znamΘnek û hßΦk∙, Φßrek, akcent∙ atd. (Krom∞ angliΦtiny nßs napadß snad jedin∞ holandÜtina.) N∞kterΘ jazyky krom∞ diakritick²ch znamΘnek pou₧φvajφ i zvlßÜtnφ pφsmena, neznßmß v jin²ch jazycφch û nap°. v n∞mΦin∞ je to ostrΘ s (znak ▀), v dßnÜtin∞ znak a atd. Je jasnΘ, ₧e rozumn² program bude s u₧ivatelem komunikovat v jeho jazyce, a k tomu pot°ebuje ·plnou znakovou sadu jazyka.

KlasickΘ °eÜenφ tohoto problΘmu p°i pou₧itφ ä·zk²chô znak∙ (typu char) bylo zalo₧eno na k≤dov²ch strßnkßch, tj. na tom, ₧e znaky s k≤dy v rozmezφ 128û255 m∞ly v r∙zn²ch prost°edφch r∙zn² v²znam. Toto °eÜenφ Ülo pou₧φt p°edevÜφm pro evropskΘ jazyky, nebo¥ ty pou₧φvajφ hlßskovß pφsma o malΘm poΦtu znak∙. OvÜem pro jazyky z DßlnΘho v²chodu, kterΘ pou₧φvajφ slabiΦnß pφsma o velkΘm poΦtu znak∙, nem∞lo v²znam. Tyto jazyky pou₧φvaly k≤dovßnφ zalo₧enΘ na tzv. vφcebajtov²ch znacφch (multibyte characters), v nich₧ r∙znΘ znaky mohly b²t k≤dovßny r∙zn²m poΦtem bajt∙. Navφc n∞kterΘ bajty m∞ly v²znam podobn² p°e°a∩ovaΦ∙m na klßvesnici û urΦovaly, kter² z n∞kolika mo₧n²ch v²znam∙ bude nßsledujφcφ bajt mφt.

Od konce 80. let se stßle d∙razn∞ji prosazuje vφcebajtovΘ k≤dovßnφ Unicode, kterΘ pokr²vß snad vÜechny jazyky, je popsßno mezinßrodnφm standardem ISO/IEC 10646 (ve kterΘm se ovÜem oznaΦenφ Unicode neobjevuje).

Pro prßci se znaky v k≤dovßnφ Unicode slou₧φ v C++ datov² typ wchar_t, kter² zabφrß obvykle dva nebo Φty°i bajty a Φasto se o n∞m hovo°φ jako o äÜirok²chô znacφch. Znakovou konstantu tohoto typu zapisujeme podobn∞ jako ä·zkouô znakovou konstantu, pouze p°ed ni p°ipojφme prefix L. Podobn∞ p°ipojφme prefix L p°ed °et∞zcovΘ literßly typu wchar_t.

Pro ulo₧enφ znakov²ch °et∞zc∙ m∙₧eme pou₧φvat bu∩ pole t∞chto typ∙ nebo (rad∞ji) instance typu string, resp. wstring.

P°i v²stupu se ovÜem musφ znaky z k≤dovßnφ Unicode p°evΘst do k≤dovßnφ, pou₧φvanΘho v oknech, v souboru nebo na konzole. K tomu je t°eba specifikovat lokßlnφ nastavenφ, tedy zadat objekt t°φdy locale, kter² je popisuje.

┌zkΘ a ÜirokΘ proudy

Ne₧ p°ejdeme k v²stupu ΦeskΘho textu, musφme si °φci n∞kolik slov o datov²ch proudech.
DatovΘ proudy pro ÜirokΘ znaky (äÜirokΘ proudyô) jsou û stejn∞ jako datovΘ proudy pro ·zkΘ znaky, tedy ä·zkΘ proudyô û instance t°φd, vznikl²ch specializacφ Üablon basic_istream<>, basic_ostream<>, basic_fstream<> atd. Prvnφm parametrem t∞chto Üablon je typ znak∙, tedy char v p°φpad∞ ·zk²ch proud∙ a wchar_t v p°φpad∞ Üirok²ch proud∙. Druh²m parametrem je t°φda rys∙ (traits), popisujφcφ vlastnosti znak∙. Implicitnφ hodnotou druhΘho parametru Üablon proud∙ je specializace Üablony rys∙ char_traits<> pro prvnφ parametr.

Pro ·zkΘ proudy jsou pomocφ deklarace typedef zavedena obvyklß jmΘna û istream, ostream, fstream atd. Pro ÜirokΘ proudy jsou zavedena podobnß jmΘna, kterß ovÜem zaΦφnajφ pφsmenem w.
Z toho, ₧e jde o r∙znΘ specializace tΘ₧e Üablony, plyne, ₧e s ob∞ma druhy proud∙ zachßzφme prakticky stejn∞.

Poznamenejme, ₧e i ÜirokΘ proudy v dneÜnφch operaΦnφch systΘmech uklßdajφ do soubor∙ zpravidla ·zkΘ znaky a pochopiteln∞ v nich takΘ ·zkΘ znaky oΦekßvajφ. P°i p°evodu z k≤dovßnφ Unicode do ·zk²ch znak∙ p°i zßpisu a p°i opaΦnΘm p°evodu p°i Φtenφ je ovÜem t°eba znßt lokßlnφ nastavenφ (k≤dovou strßnku, v nφ₧ jsou ·zkΘ znaky zapsßny). Tu urΦφme tak, ₧e k proudu pomocφ metody imbue() p°ipojφme objekt t°φdy locale.

V²stup ΦeskΘho textu

Pou₧φvßme-li ·zkΘ znaky, je v²stup ΦeskΘho textu v podstat∞ jednoduch²: Musφme si p°ipravit pot°ebn² znakov² °et∞zec v odpovφdajφcφm k≤dovßnφ. Jsme-li ve Windows, je to komplikovßno tφm, ₧e v oknech se pou₧φvß k≤dovß strßnka 1250, zatφmco p°i v²stupu na konzolu k≤dovß strßnka 852. Vstupnφ a v²stupnφ proudy si s ob∞ma poradφ bez problΘm∙.

Pou₧φvßme-li ÜirokΘ znaky, je v∞c na prvnφ pohled slo₧it∞jÜφ, nebo¥ musφme pou₧φvat i proudy pro ÜirokΘ znaky, jako je wistream, wostream, wfstream atd. Na druhΘ stran∞ ale zφskßme i vφce mo₧nostφ.

Jako p°φklad si vezmeme za ·kol zapsat do souboru a vypsat na konzolu v∞tu o ₧lu¥ouΦkΘm koni. Jak to ud∞lat?
Nejprve deklarujeme znakovΘ pole nebo °et∞zec obsahujφcφ po₧adovanou v∞tu:

wchar_t cw[] = L"Älu¥ouΦk² k∙≥ p°φÜern∞ ·p∞l ∩ßbelskΘ ≤dy.";
wstring S(L"Älu¥ouΦk² k∙≥ p°φÜern∞ ·p∞l ∩ßbelskΘ ≤dy.");

Dßle v programu deklarujeme dv∞ instance t°φdy locale, kterΘ budou popisovat nßrodnφ prost°edφ s k≤dov²mi strßnkami 1250 (pro soubor) a 852 (pro konzolovΘ okno):

locale Kon("Czech_Czech Republic.852"); // Pro konzolu
locale Sou("Czech_Czech Republic.1250"); // Pro okna

Pro v²stup na konzolu musφme pou₧φt äÜirok²ô proud wcout. Jak vφme, lokßlnφ prost°edφ k n∞mu p°ipojφme pomocφ metody imbue():

wcout.imbue(Kon);

Pak u₧ m∙₧eme obsah pole cw bez problΘm∙ vypsat:

wcout << cw << endl;

V²pis do souboru nenφ o nic slo₧it∞jÜφ: Vytvo°φme instanci t°φdy wofstream napojenou na odpovφdajφcφ soubor a p°ipojφme k nφ odpovφdajφcφ lokßlnφ prost°edφ:

wofstream F("data.dta");
F.imbue(Sou);
F << cw << endl;
F.close();

To je vÜe. Cel² program m∙₧e vypadat takto:

#include <iostream>
#include <stdexcept>
#include <fstream>
#include <locale>
using namespace std;
wchar_t cw[] = L"Älu¥ouΦk² k∙≥ p°φÜern∞ ·p∞l ∩ßbelskΘ ≤dy.";
int main()
{
        try{
                locale Kon("Czech_Czech Republic.852");
                locale Sou("Czech_Czech Republic.1250");
                wcout.imbue(Kon);
                wofstream F("data.dta");
                F.imbue(Sou);
                F << cw << endl; // V²pis v Cp1250
                F.imbue(Kon);
                F << cw << endl; // V²pis v Cp852
                F.close();
                wcout << cw << endl;
        }
        catch(runtime_error &e)
        {
                cerr << e.what() << endl;
        }
        return 0;
}

Soubor data.dta bude obsahovat v∞tu o ₧lutΘm koni, ovÜem v ·zk²ch znacφch a v k≤dovßnφ danΘm p°edepsanou k≤dovou strßnkou.
Poznamenejme, ₧e lokßlnφ prost°edφ, p°ipojenΘ k datovΘmu proudu, m∙₧eme zjistit volßnφm metody getloc(). Je-li nap°. L prom∞nnß typu locale, m∙₧eme napsat

L = wcout.getloc();

Prom∞nnß L pak bude obsahovat lokßlnφ nastavenφ pou₧φvanΘ proudem wcout.

Vstup ΦeskΘho textu

P°i vstupu ze souboru obsahujφcφho Φesk² text ve znßmΘ k≤dovΘ strßnce postupujeme podobn∞. Jestli₧e nap°. soubor data.dta obsahuje text

Ahoj

zp∙sobφ p°φkazy

wchar_t cw[100];
wifstream I("data.dta");
I.imbue(locale("czech"));
I >> cw ;

₧e pole cw bude obsahovat °et∞zec "Ahoj" v k≤dovßnφ UNICODE. OvÜem pou₧itφ operßtoru >> nenφ p°φliÜ v²hodnΘ, nebo¥ vstup skonΦφ u prvnφ mezery. Kdyby nßÜ soubor obsahoval v∞tu o ₧lutΘm koni, p°eΦetli bychom takto jen slovo "Älu¥ouΦk²". Daleko rozumn∞jÜφ je pou₧φt funkci getline(), kterou najdeme v hlaviΦkovΘm souboru string:

wstring S;
getline(wcin, S);

getline() je Üablonovß funkce, kterΘ lze jako parametry p°edat bu∩ ·zk² vstupnφ proud a instanci t°φdy string, nebo Üirok² proud a instanci t°φdy wstring. Tato funkce p°eΦte z danΘho proudu (a s jeho lokßlnφm nastavenφm) vÜe do konce °ßdku, ulo₧φ to do danΘ °et∞zcovΘ prom∞nnΘ a vrßtφ odkaz na p°edan² proud.

P°φklad
Nynφ u₧ znßme vÜe, co je pot°eba, abychom mohli napsat filtr, kter² bude slou₧it ke konverzi textov²ch soubor∙ z k≤dovΘ strßnky 1250 do k≤dovΘ strßnky 852. To znamenß, ₧e si m∙₧eme rovnou ukßzat zdrojov² text:

// Filtr pro konverzi Cp1250 -> Cp852
// Program konver.cpp
#include <iostream>
#include <locale>
#include <string>
#include <stdexcept>
using namespace std;

int main(int argv, char *argc[])
{
        wstring ws;
        try {
                locale L1("Czech_Czech Republic.1250");
                locale L2("Czech_Czech Republic.852");
                wcin.imbue(L1);
                wcout.imbue(L2);
                while (getline(wcin, ws))
                {
                        wcout << ws << endl;
                        if(!wcout) wcerr << L"sorry" ;
                }
        }
        catch(runtime_error &e)
        {
                cerr << "Nepodporovane kodovani";
        }
        return 0;
}

Jak jist∞ vφte, jako filtry oznaΦujeme programy, kterΘ se spouÜt∞jφ z p°φkazovΘ °ßdky a pou₧φvajφ standardnφ vstup a v²stup. P°i spuÜt∞nφ je zpravidla p°esm∞rujeme, aby Φetly ze souboru a p°φpadn∞ vypisovaly v²stup do souboru.
V tomto programu nejprve deklarujeme pomocnou prom∞nnou ws typu wstring (°et∞zec se Üirok²mi znaky). Pak vytvo°φme objekt L1 s lokßlnφm nastavenφm pro Cp1250, kter² p°ipojφme k proudu wcin, a objekt L2 s lokßlnφm nastavenφm pro Cp852, kter² p°ipojφme k proudu wcout.

Nynφ u₧ zb²vß jen v cyklu p°eΦφst jednotlivΘ °ßdky vstupu a hned je zase vypsat. Ke Φtenφ pou₧ijeme metodu getline(), kterß v₧dy p°eΦte ze zadanΘho proudu cel² °ßdek a ulo₧φ ho do danΘ instance t°φdy wstring. Tato metoda vracφ odkaz na p°edan² proud, proto ji lze pou₧φt v podmφnce cyklu while; Φtenφ skonΦφ, narazφ-li na konec souboru.

P°i Φtenφ se text p°evede z k≤dovΘ strßnky 1250 do k≤dovßnφ Unicode, p°i v²pisu se p°evede z Unicode do k≤dovΘ strßnky 852. (Nenφ to nejefektivn∞jÜφ zp∙sob p°evodu, je to ale programßtorsky nejsnazÜφ zp∙sob, ovÜem za p°edpokladu, ₧e ob∞ tato lokßlnφ nastavenφ jsou na pou₧itΘm poΦφtaΦi k dispozici).
Vezmeme-li soubor hou.txt, obsahujφcφ v k≤dovΘ strßnce 1250 text

Älu¥ouΦk² k∙≥
p°φÜern∞ ·p∞l
∩ßbelskΘ ≤dy

a spustφme-li ho p°φkazem

konver < hou.txt > py.txt

dostaneme soubor py.txt, v n∞m₧ bude stejn² text v k≤dovΘ strßnce 852. To znamenß, ₧e pod Windows uvidφme n∞co jako

─luúou└k° k¿▓
p░▌▄ern²  p²l
┤▀belsk┌ ídy

Konverze °et∞zc∙

I kdy₧ obvykle v jednom programu pou₧φvßme bu∩ jen ÜirokΘ nebo jen ·zkΘ °et∞zce, obΦas p°ece jen pot°ebujeme pou₧φt obojφ zßrove≥, pak se m∙₧eme setkat s ·lohou p°evΘst Üirok² °et∞zec na ·zk² nebo naopak. K tomu slou₧φ metody narrow(), resp. widen() t°φdy ctype, kterß je souΦßstφ lokßlnφho nastavenφ. (M∙₧eme se na ni dφvat jako na objektovΘ zapouzd°enφ funkcφ z hlaviΦky ctype.h z jazyka C). Platφ-li deklarace

wchar_t cw[] = L"Älu¥ouΦk² k∙≥ p°φÜern∞ ·p∞l ∩ßbelskΘ ≤dy.";
char cn[100];

p°evedeme pole cw Üirok²ch znak∙ na pole ·zk²ch znak∙ v lokßlnφm nastavenφ Kon podivn∞ vypadajφcφm p°φkazem

use_facet<ctype<wchar_t> >(Kon).narrow(
cw, cw+sizeof(cw)/sizeof(wchar_t), '*', cn);

V²znam ÜablonovΘ funkce use_facet<>() si vysv∞tlφme pozd∞ji; zatφm nßm staΦφ v∞d∞t, ₧e tato funkce vrßtφ instanci t°φdy ctype lokßlnφho nastavenφ Kon. Pro vrßcenou instanci t°φdy ctype pak zavolßme funkci narrow. Jako parametry jφ p°edßvßme

Poznamenejme, ₧e vedle funkcφ pro konverzi ·seku pole jsou k dispozici i p°etφ₧enΘ verze t∞chto metod, kterΘ konvertujφ jedin² znak.
Funkci widen() pou₧φvßme podobn∞, nemß vÜak t°etφ parametr (implicitnφ znak). To znamenß, ₧e platφ-li deklarace

wchar_t cw[100];
char cn[] = "Älu¥ouΦk² k∙≥ p°φÜern∞ ·p∞l ∩ßbelskΘ ≤dy.";

a je-li zdrojov² k≤d zapsßn v k≤dovΘ strßnce 1250, zp∙sobφ p°φkazy

locale L("Czech_Czech Republic.1250");
use_facet<ctype<wchar_t> >(L).widen(cn, cn+sizeof(cn)/sizeof(char), cw);

₧e pole cw bude obsahovat uveden² °et∞zec v k≤dovßnφ Unicode.
Poznamenejme, ₧e standardnφ knihovna z°ejm∞ neobsahuje nßstroj pro p°evod mezi typy string a wstring.

Budete-li to zkouÜet

U₧ jsme si °ekli, ₧e jednφm z nejrozÜφ°en∞jÜφch problΘm∙ s nßrodnφm prost°edφm je, ₧e jeho implementace v souΦasn²ch p°ekladaΦφch obsahuje chyby. M∙₧e se vßm nap°. stßt, ₧e program nebude vypisovat znaky s diakritick²mi znamΘnky, m∙₧e se ale takΘ stßt, ₧e nebude znßt ₧ßdn² z v²Üe uveden²ch °et∞zc∙, urΦujφcφch jmΘna nßrodnφch prost°edφ. Podφvejme se na nejrozÜφ°en∞jÜφ komerΦnφ p°ekladaΦe.

Nap°φklad Borland C++Builder 4 znß z°ejm∞ jen °et∞zce "" a "C", p°iΦem₧ prßzdn² °et∞zec znamenß totΘ₧ co "C". Borland C++Builder 5 ji₧ znß °adu jmen lokßlnφch nastavenφ, metoda name() t°φdy locale vypφÜe hodnoty pro jednotlivΘ kategorie lokßlnφho nastavenφ jazyka C. Navφc p°i pokusu vypsat do proudu wcout nebo do proudu pro v²stup do souboru text obsahujφcφ znaky s diakritick²mi znamΘnky se program zhroutφ (vznikne v²jimka bad_alloc). TakΘ p°evod mezi ·zk²mi a Üirok²mi znaky jaksi nezvlßdß. Borland C++Builder 6 sice ji₧ sprßvn∞ vypisuje jmΘno lokßlnφho nastavenφ, ale operace s Φesk²mi Üirok²mi znaky stßle nezvlßdß.

Microsoft Visual C++ 6 sprßvn∞ zachßzφ se jmΘny lokßlnφch nastavenφ a zvlßdß i v²stup Φesk²ch znak∙ proudem wcout na konzolu, nezvlßdß vÜak v²stup pomocφ Üirok²ch proud∙ do soubor∙ (alespo≥ pod Windows 95, nebo¥ jinou instalaci tohoto p°ekladaΦe nemßme k dispozici). Vzhledem k tomu, ₧e tento p°ekladaΦ neimplementuje Üablony v plnΘm rozsahu, je t°eba p°i p°evodu mezi ·zk²mi a Üirok²mi znaky mφsto ÜablonovΘ funkce use_facet<>() pou₧φt makro _USEFAC().
VÜechny p°φklady, kterΘ zde uvßdφme, jsem odladili ve Visual C++ .NET.

P°φÜt∞

P°φÜt∞ se podφvßme na p°evod mal²ch pφsmen na velkß a naopak, na abecednφ °azenφ a na n∞kterΘ dalÜφ operace.

Miroslav Virius