CLocale和C++Locales之間的不同

前幾日在看一個(gè)關(guān)于多線程下locale問(wèn)題:在多線程下locale not independent問(wèn)題。無(wú)意中在網(wǎng)上搜到一篇講解C locale 和C++ locale的文章,覺(jué)得很好,鏈接如下:
http://stdcxx.apache.org/doc/stdlibug/24-3.html

成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)制作、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的虎林網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

今天嘗試翻譯一下,加深理解。翻譯如下:

Apache C++ 標(biāo)準(zhǔn)庫(kù)用戶向?qū)?br/>24.3 C Locale和C++ Locales區(qū)別
正如我們目前所看到的,C Locale和C++ Locales提供了類似服務(wù)。然而,C++ Locale所想表達(dá)的語(yǔ)義信息卻不同于C Locale。

  • 標(biāo)準(zhǔn)C locale是個(gè)全局設(shè)置,整個(gè)應(yīng)用只有一個(gè)locale。因此一個(gè)應(yīng)用很難一次處理多個(gè)locales。
  • 標(biāo)準(zhǔn)C++ locale是一個(gè)類。你可以創(chuàng)建出任意多的標(biāo)準(zhǔn)庫(kù)的實(shí)例。因此你想要多少locale 對(duì)象,你就能創(chuàng)建出來(lái)。

為了進(jìn)一步細(xì)節(jié)地探索他們的不同,我們來(lái)看看locales是如何被使用的。

24.3.1 C locale的一般使用
c locale 通常會(huì)被用作默認(rèn)locale (defaule locale),本地locale (native locale),或者是多l(xiāng)ocale應(yīng)用(multiple locale applications)中。

Default locale:作為開(kāi)發(fā),如果你從不涉及到互聯(lián)網(wǎng)功能的開(kāi)發(fā)需求,那么你也不會(huì)調(diào)用std::setlocale()。如果你認(rèn)為你用戶總是在標(biāo)準(zhǔn)的US English ASCII下使用你的應(yīng)用,那么你也沒(méi)有l(wèi)ocalization的需求。如果你連locale都不知道的話,那么你一定總是在默認(rèn)的locale下,也就是在US English ASCII locale下開(kāi)發(fā)你的應(yīng)用。

Native locale:如果你確實(shí)有計(jì)劃在你的程序里支持本地化,最合適的策略就是在程序一開(kāi)始就獲取本地local信息,然后不要再更改設(shè)置。這樣你的應(yīng)用會(huì)適配的選擇某個(gè)特定locale,并貫穿到應(yīng)用的整個(gè)運(yùn)行過(guò)程中。如此用戶在啟動(dòng)應(yīng)用之前就可以顯示的設(shè)置他們喜歡的locale。在UNIX系統(tǒng)中,他們通過(guò)設(shè)置環(huán)境變量,例如LANG來(lái)設(shè)置locale;其它操作系統(tǒng)有其它的方法去設(shè)置locale。

你在程序里可以通過(guò)調(diào)用set::setlocale("")以及傳一個(gè)空字符串作為locale的名字來(lái)指定一個(gè)用戶有偏好的locale設(shè)置??盏淖址歉嬖Vsetlocale去使用用戶在環(huán)境中指定的locale作為應(yīng)用的默認(rèn)locale。

Multiple locales:有時(shí)候你不得不工作在多l(xiāng)ocales的情形下。例如,一個(gè)應(yīng)用是給瑞士人使用的,那么你期望輸出的消息能支持意大利語(yǔ),法語(yǔ)和德語(yǔ)。因?yàn)镃 locale是一個(gè)全局的(global)的數(shù)據(jù)結(jié)構(gòu),所以你必須在不同locales之間多次切換去支持不同語(yǔ)言。

我們來(lái)看一個(gè)在多l(xiāng)ocales情形下工作的例子。想象一下你的應(yīng)用需要打印費(fèi)用清單給全世界的顧客。那個(gè)費(fèi)用清單一定是符合顧客本地語(yǔ)言的,所以你的應(yīng)用就必須根據(jù)不同的語(yǔ)言打印不同語(yǔ)言費(fèi)用清單。其中費(fèi)用清單里的價(jià)格是一個(gè)獨(dú)立的價(jià)格列表。假設(shè)我們的應(yīng)用被一個(gè)美國(guó)公司使用,價(jià)格列表是US English。

應(yīng)用在US English下讀價(jià)格列表(輸入),但是寫(xiě)費(fèi)用清單(輸出)是支持客戶本地語(yǔ)言的,比如說(shuō)德語(yǔ)。因?yàn)镃有僅有一個(gè)全局的(global) locale,全局的locale會(huì)同時(shí)影響輸入和輸出,所以全局的locale需要在輸入和輸出之間進(jìn)行切換。在價(jià)格從英文價(jià)格列表中讀出來(lái)之前,locale必須先從德文locale切換成US English locale。在價(jià)格加入到費(fèi)用清單之前,全局的locale必須再切換成德文locale。為了從價(jià)格列表里讀下一個(gè)價(jià)格,locale又要切換為English,如此反復(fù)。 圖6解釋了這個(gè)過(guò)程。

Figure 6 : Multiple locales in C
C Locale和C++ Locales之間的不同

這是剛才例子的C代碼:

double price;
char buf[SZ];
while ( ... )     // processing the German invoice 
{
   std::setlocale(LC_ALL, "En_US");
   std::fscanf(priceFile, "%lf", &price);

   // convert $ to DM according to the current exchange rate
   std::setlocale(LC_ALL, "De_DE");
   std::strfmon(buf,SZ, "%n", price);
   std::fprintf(invoiceFile, "%s", buf);
}

使用C++ locale對(duì)象可以極具地簡(jiǎn)化這個(gè)過(guò)程。The iostreams in the C++ Standard Library are internationalized so that streams can be imbued with separate locale objects. C++標(biāo)準(zhǔn)庫(kù)下的iostreams是國(guó)際通用的(internationalized),所以streams能夠貫穿獨(dú)立的locale對(duì)象。例如,輸入流是English locale對(duì)象,輸出流是German locale對(duì)象。如此,locales切換就沒(méi)有必要了,正如圖7所顯示的:
Figure 7: Multiple locales in C++
C Locale和C++ Locales之間的不同
這是C++代碼的例子:

priceFile.imbue(std::locale("En_US"));
invoiceFile.imbue(std::locale("De_DE"));
moneytype price;
while ( ... )  // processing the German invoice
{
   priceFile >> price;
   // convert $ to DM according to the current exchange rate
   invoiceFile << price;
}

假設(shè)這個(gè)例子已經(jīng)有

  • 一個(gè)類 moneytype, 來(lái)表示貨幣的價(jià)值,
  • 類moneytype提供了流insertion ( << ) 和 extraction ( >> )操作符
  • 使用std::money_put和std::money_get來(lái)格式化和解析貨幣值,流<<用std::money_put格式貨幣值;流>>用std::money_get解析貨幣值
    第26章列舉了一個(gè)較復(fù)雜的電話號(hào)碼的例子來(lái)闡釋這個(gè)技術(shù)。類moneytype不是C++標(biāo)準(zhǔn)庫(kù)的一部分。

貨幣值的例子相對(duì)簡(jiǎn)單,在locales之間切換不是很麻煩。然而,一旦涉及到代碼層面切換,這個(gè)問(wèn)題就變的主要起來(lái)了。

為了更好的理解這一點(diǎn),讓我們?cè)倏匆幌聢D2中的JIS encoding scheme使用shift語(yǔ)法如何在圖8中變大方便起來(lái)的。正如你說(shuō)記得那樣,當(dāng)你解析字符句子的時(shí)候,你必須要維護(hù)一個(gè)shift狀態(tài)。
Figure 8: Figure 2中日文文本在JIS中的編碼
C Locale和C++ Locales之間的不同

假設(shè)你在解析一個(gè)含有在JIS下編碼的文本的多字節(jié)文件,正如你在圖9中所看到的。當(dāng)你解析這個(gè)文件,你不得不跟蹤shift狀態(tài)以至于你可以知道如何翻譯你所讀到的字符節(jié),如何以合適的寬字節(jié)來(lái)表達(dá)這些字符節(jié)。

Figure 9:使用全局C locale解析多字節(jié)文本輸入
C Locale和C++ Locales之間的不同

在解析文本過(guò)程中,全局C locale可以來(lái)回切換;例如,文本輸入的locale狀態(tài)從JIS 編碼切換到EUC編碼。每當(dāng)locale切換到新的狀態(tài),當(dāng)前的locale狀態(tài)就無(wú)效了,在你的應(yīng)用里你不得不小心維護(hù)由locale切換帶來(lái)的狀態(tài)切換。

當(dāng)local切換變得通用的時(shí)候,這個(gè)問(wèn)題就迎刃而解了。然而,在多線程環(huán)境下,全局C locale會(huì)帶來(lái)嚴(yán)重的問(wèn)題,因?yàn)橐粋€(gè)線程下的locale狀態(tài)不經(jīng)意間會(huì)被另外一個(gè)線程下的locale給更改了。因?yàn)檫@個(gè)原因,在多線程環(huán)境下通用化C程序就很困難。

如果你使用C++ locales,另一方面這個(gè)問(wèn)題也很容易解決了。你可以每個(gè)數(shù)據(jù)流綁定到一個(gè)獨(dú)立的locale對(duì)象,這樣問(wèn)題就不會(huì)出現(xiàn)locale被不期望修改的問(wèn)題。讓我們來(lái)看一個(gè)C++ locales的例子。

priceFile.imbue(std::locale("En_US"));
invoiceFile.imbue(std::locale("De_DE"));
moneytype price;
while ( ... )  // processing the German invoice
{
   priceFile >> price;
   // convert $ to DM according to the current exchange rate
   invoiceFile << price;
}

24.3.2 C++ locales的一般使用
C++ locale通常被用作支持多l(xiāng)ocales的默認(rèn)的locale;和全局locale。

Classic locale.如果你涉及的程序并不需要支持本地化工作,那么使用C++ locales和使用C locales沒(méi)什么區(qū)別。 如果你總是認(rèn)為你的應(yīng)用程序的用戶總是在US English ASCII環(huán)境下,那么你也不需要請(qǐng)求本地化。對(duì)于你,C++標(biāo)準(zhǔn)庫(kù)提供了一個(gè)預(yù)定義的locale對(duì)象std::locale::classic(),它正是US English ASCII locale。

Native locale.Native locale是受用戶和系統(tǒng)管理員喜歡的一個(gè)locale。在UNIX系統(tǒng)里,通常通過(guò)設(shè)置環(huán)境變量例如LANG來(lái)完成。你也可以通過(guò)調(diào)用構(gòu)造函數(shù)std::locale("")為native locale創(chuàng)建一個(gè)C++ locale對(duì)象,也就是通過(guò)請(qǐng)求一個(gè)以空字符串作為輸入創(chuàng)建的locale。這個(gè)空字符串告訴系統(tǒng)從環(huán)境中得到locale的名字,這等同于C庫(kù)函數(shù)的std::setlocale("")。

Named locales.正如上面所說(shuō),一個(gè)local可以有一個(gè)名字。標(biāo)準(zhǔn)的locale的名字是“c”。不幸的是,其他locales的名字平臺(tái)依賴。查詢你的系統(tǒng)文檔來(lái)獲知你的系統(tǒng)是什么locales被安裝以及l(fā)ocale是如何命名的。如果你嘗試用一個(gè)無(wú)效的名字去創(chuàng)建一個(gè)locale對(duì)象,構(gòu)造函數(shù)會(huì)拋出一個(gè)runtime_error異常。

Multiple locales.當(dāng)你使用C++ locales,工作在不同的locales就變得很容易了。你在C下面所做的locales切換,在C++里就不再有必要了。你可以綁定每個(gè)流到不同的locale 對(duì)象。你也可以傳遞locales對(duì)象到不同地方使用,這完全沒(méi)有問(wèn)題。

Global locale.正如C,C++也有全局的locale。 一開(kāi)始,全局locale是如前所說(shuō)的標(biāo)準(zhǔn)locale。你也可以通過(guò)調(diào)用std::locale::global()去改變?nèi)謑ocale。

你也可以通過(guò)調(diào)用默認(rèn)的構(gòu)造函數(shù)std::locale::locale(),為當(dāng)前的全局locale創(chuàng)建一個(gè)快照。這些快照也是locales object獨(dú)立的,不受接下來(lái)的全局locale改變的影響。

通用化組件像iostreams,使用的全局locale作為默認(rèn)的locale。如果你不顯式的把一個(gè)流和一個(gè)特定的locale綁定在一起,那么這個(gè)流對(duì)象就默認(rèn)和一個(gè)在它被創(chuàng)建時(shí)的那個(gè)全局的locale綁定。

C下全局locale所能做的,C++全局locale也能做到。在程序啟動(dòng)一旦開(kāi)始,程序就激活了本地locale。換言之,本地locale被激活作為global locale,并作為locale快照,之后所有的工作都依賴這個(gè)locale。以下的代碼描述了這個(gè)過(guò)程:

std::locale::global(std::locale(""));                         //1
...
std::string t = print_date(today, std::locale());             //2
...
std::locale::global(std::locale("Fr_CH"));                    //3
...
std::cout << something;                                       //4

//1 設(shè)置本地locale作為全局locale
//2 總是使用全局locale快照作為你當(dāng)前使用的locale對(duì)象。假設(shè)函數(shù)print_date()是格式化日期的。為了格式化日期,你將要提供一個(gè)全局locale的快照給函數(shù)print_date()。
//3 切換全局locale到French全局locale
//4 注意在這個(gè)例子中,標(biāo)準(zhǔn)流cout仍然是跟classic locale(標(biāo)準(zhǔn)的locale)綁定的,因?yàn)樵诔绦騿?dòng)的時(shí)候,std::cout就被創(chuàng)建出來(lái)了。改變?nèi)謑ocale不會(huì)影響先前已經(jīng)存在的流的locales。如果你想讓一個(gè)新的全局locale綁定到cout上,你應(yīng)該在調(diào)用完std::locale::global()之后調(diào)用stf::cout.imbue(locale())。
24.3.3 C locale和C++ locales之間的聯(lián)系

C locale和C++ locale是完全獨(dú)立的。然而,C++ locale對(duì)象是有個(gè)名字的,通過(guò)std::locale::global()使locale對(duì)象變成全局locale會(huì)引起C locale改變,這個(gè)改變會(huì)通過(guò)調(diào)用std::setlocale()。當(dāng)它發(fā)生時(shí),在C++程序里,locale敏感的C函數(shù)會(huì)使用變化了的C locale。

在一個(gè)C程序里,是沒(méi)有辦法改變C++ locale的。

分享名稱:CLocale和C++Locales之間的不同
本文網(wǎng)址:http://bm7419.com/article6/pcgeog.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航用戶體驗(yàn)、、標(biāo)簽優(yōu)化、定制開(kāi)發(fā)ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作