前幾日在看一個關于多線程下locale問題:在多線程下locale not independent問題。無意中在網(wǎng)上搜到一篇講解C locale 和C++ locale的文章,覺得很好,鏈接如下:
http://stdcxx.apache.org/doc/stdlibug/24-3.html
今天嘗試翻譯一下,加深理解。翻譯如下:
Apache C++ 標準庫用戶向導
24.3 C Locale和C++ Locales區(qū)別
正如我們目前所看到的,C Locale和C++ Locales提供了類似服務。然而,C++ Locale所想表達的語義信息卻不同于C Locale。
為了進一步細節(jié)地探索他們的不同,我們來看看locales是如何被使用的。
24.3.1 C locale的一般使用
c locale 通常會被用作默認locale (defaule locale),本地locale (native locale),或者是多l(xiāng)ocale應用(multiple locale applications)中。
Default locale:作為開發(fā),如果你從不涉及到互聯(lián)網(wǎng)功能的開發(fā)需求,那么你也不會調用std::setlocale()。如果你認為你用戶總是在標準的US English ASCII下使用你的應用,那么你也沒有l(wèi)ocalization的需求。如果你連locale都不知道的話,那么你一定總是在默認的locale下,也就是在US English ASCII locale下開發(fā)你的應用。
Native locale:如果你確實有計劃在你的程序里支持本地化,最合適的策略就是在程序一開始就獲取本地local信息,然后不要再更改設置。這樣你的應用會適配的選擇某個特定locale,并貫穿到應用的整個運行過程中。如此用戶在啟動應用之前就可以顯示的設置他們喜歡的locale。在UNIX系統(tǒng)中,他們通過設置環(huán)境變量,例如LANG來設置locale;其它操作系統(tǒng)有其它的方法去設置locale。
你在程序里可以通過調用set::setlocale("")以及傳一個空字符串作為locale的名字來指定一個用戶有偏好的locale設置。空的字符串是告訴setlocale去使用用戶在環(huán)境中指定的locale作為應用的默認locale。
Multiple locales:有時候你不得不工作在多l(xiāng)ocales的情形下。例如,一個應用是給瑞士人使用的,那么你期望輸出的消息能支持意大利語,法語和德語。因為C locale是一個全局的(global)的數(shù)據(jù)結構,所以你必須在不同locales之間多次切換去支持不同語言。
我們來看一個在多l(xiāng)ocales情形下工作的例子。想象一下你的應用需要打印費用清單給全世界的顧客。那個費用清單一定是符合顧客本地語言的,所以你的應用就必須根據(jù)不同的語言打印不同語言費用清單。其中費用清單里的價格是一個獨立的價格列表。假設我們的應用被一個美國公司使用,價格列表是US English。
應用在US English下讀價格列表(輸入),但是寫費用清單(輸出)是支持客戶本地語言的,比如說德語。因為C有僅有一個全局的(global) locale,全局的locale會同時影響輸入和輸出,所以全局的locale需要在輸入和輸出之間進行切換。在價格從英文價格列表中讀出來之前,locale必須先從德文locale切換成US English locale。在價格加入到費用清單之前,全局的locale必須再切換成德文locale。為了從價格列表里讀下一個價格,locale又要切換為English,如此反復。 圖6解釋了這個過程。
Figure 6 : Multiple locales in C
這是剛才例子的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對象可以極具地簡化這個過程。The iostreams in the C++ Standard Library are internationalized so that streams can be imbued with separate locale objects. C++標準庫下的iostreams是國際通用的(internationalized),所以streams能夠貫穿獨立的locale對象。例如,輸入流是English locale對象,輸出流是German locale對象。如此,locales切換就沒有必要了,正如圖7所顯示的:
Figure 7: Multiple locales in C++
這是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;
}
假設這個例子已經(jīng)有
貨幣值的例子相對簡單,在locales之間切換不是很麻煩。然而,一旦涉及到代碼層面切換,這個問題就變的主要起來了。
為了更好的理解這一點,讓我們再看一下圖2中的JIS encoding scheme使用shift語法如何在圖8中變大方便起來的。正如你說記得那樣,當你解析字符句子的時候,你必須要維護一個shift狀態(tài)。
Figure 8: Figure 2中日文文本在JIS中的編碼
假設你在解析一個含有在JIS下編碼的文本的多字節(jié)文件,正如你在圖9中所看到的。當你解析這個文件,你不得不跟蹤shift狀態(tài)以至于你可以知道如何翻譯你所讀到的字符節(jié),如何以合適的寬字節(jié)來表達這些字符節(jié)。
Figure 9:使用全局C locale解析多字節(jié)文本輸入
在解析文本過程中,全局C locale可以來回切換;例如,文本輸入的locale狀態(tài)從JIS 編碼切換到EUC編碼。每當locale切換到新的狀態(tài),當前的locale狀態(tài)就無效了,在你的應用里你不得不小心維護由locale切換帶來的狀態(tài)切換。
當local切換變得通用的時候,這個問題就迎刃而解了。然而,在多線程環(huán)境下,全局C locale會帶來嚴重的問題,因為一個線程下的locale狀態(tài)不經(jīng)意間會被另外一個線程下的locale給更改了。因為這個原因,在多線程環(huán)境下通用化C程序就很困難。
如果你使用C++ locales,另一方面這個問題也很容易解決了。你可以每個數(shù)據(jù)流綁定到一個獨立的locale對象,這樣問題就不會出現(xiàn)locale被不期望修改的問題。讓我們來看一個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的默認的locale;和全局locale。
Classic locale. 如果你涉及的程序并不需要支持本地化工作,那么使用C++ locales和使用C locales沒什么區(qū)別。 如果你總是認為你的應用程序的用戶總是在US English ASCII環(huán)境下,那么你也不需要請求本地化。對于你,C++標準庫提供了一個預定義的locale對象std::locale::classic(),它正是US English ASCII locale。
Native locale. Native locale是受用戶和系統(tǒng)管理員喜歡的一個locale。在UNIX系統(tǒng)里,通常通過設置環(huán)境變量例如LANG來完成。你也可以通過調用構造函數(shù)std::locale("")為native locale創(chuàng)建一個C++ locale對象,也就是通過請求一個以空字符串作為輸入創(chuàng)建的locale。這個空字符串告訴系統(tǒng)從環(huán)境中得到locale的名字,這等同于C庫函數(shù)的std::setlocale("")。
Named locales. 正如上面所說,一個local可以有一個名字。標準的locale的名字是“c”。不幸的是,其他locales的名字平臺依賴。查詢你的系統(tǒng)文檔來獲知你的系統(tǒng)是什么locales被安裝以及l(fā)ocale是如何命名的。如果你嘗試用一個無效的名字去創(chuàng)建一個locale對象,構造函數(shù)會拋出一個runtime_error異常。
Multiple locales. 當你使用C++ locales,工作在不同的locales就變得很容易了。你在C下面所做的locales切換,在C++里就不再有必要了。你可以綁定每個流到不同的locale 對象。你也可以傳遞locales對象到不同地方使用,這完全沒有問題。
Global locale. 正如C,C++也有全局的locale。 一開始,全局locale是如前所說的標準locale。你也可以通過調用std::locale::global()去改變全局locale。
你也可以通過調用默認的構造函數(shù)std::locale::locale(),為當前的全局locale創(chuàng)建一個快照。這些快照也是locales object獨立的,不受接下來的全局locale改變的影響。
通用化組件像iostreams,使用的全局locale作為默認的locale。如果你不顯式的把一個流和一個特定的locale綁定在一起,那么這個流對象就默認和一個在它被創(chuàng)建時的那個全局的locale綁定。
C下全局locale所能做的,C++全局locale也能做到。在程序啟動一旦開始,程序就激活了本地locale。換言之,本地locale被激活作為global locale,并作為locale快照,之后所有的工作都依賴這個locale。以下的代碼描述了這個過程:
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 設置本地locale作為全局locale
//2 總是使用全局locale快照作為你當前使用的locale對象。假設函數(shù)print_date()是格式化日期的。為了格式化日期,你將要提供一個全局locale的快照給函數(shù)print_date()。
//3 切換全局locale到French全局locale
//4 注意在這個例子中,標準流cout仍然是跟classic locale(標準的locale)綁定的,因為在程序啟動的時候,std::cout就被創(chuàng)建出來了。改變全局locale不會影響先前已經(jīng)存在的流的locales。如果你想讓一個新的全局locale綁定到cout上,你應該在調用完std::locale::global()之后調用stf::cout.imbue(locale())。
24.3.3 C locale和C++ locales之間的聯(lián)系
C locale和C++ locale是完全獨立的。然而,C++ locale對象是有個名字的,通過std::locale::global()使locale對象變成全局locale會引起C locale改變,這個改變會通過調用std::setlocale()。當它發(fā)生時,在C++程序里,locale敏感的C函數(shù)會使用變化了的C locale。
在一個C程序里,是沒有辦法改變C++ locale的。
另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
分享題目:CLocale和C++Locales之間的不同-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://www.rwnh.cn/article18/hdhdp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、移動網(wǎng)站建設、網(wǎng)站設計、外貿建站、微信公眾號、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內容