日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c实现多语言编程,C/C++编程中多国语言处理

發布時間:2024/10/8 c/c++ 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c实现多语言编程,C/C++编程中多国语言处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多國語言的存在、不同語言操作系統的存在,使得針對多語言的設計頗費周章,在編碼上所付出的工作量也是可觀的。所謂編碼的問題,歸結起來,就是二進制的編碼以何種編碼格式進行解析的問題。特別是在硬盤文件和內存數據的相互轉化、即讀寫過程中,如果采用了錯誤的編碼格式,就會造成亂碼。JAVA 語言在字符串、編碼等處理方面給了程序員更為直接、方便的接口,習慣使用 JAVA 做編碼的程序員,在使用 C/C++ 進行文本編碼相關的操作時,常會感到困惑。本文的目的在于以常用的 Unicode(UCS-2)、GB2312、UTF8 三種編碼為例,分析不同編碼在實用中的關系,特別是 C/C++ 中,怎樣處理各種編碼的問題。

1. 將內存中編碼 A 的字符串以編碼 B 格式處理成字節流寫入文件

2. 將原本以 A 編碼組成的文件以字節流形式讀入內存、并以編碼 B 解析為字符串。

第一種情況,可能造成數據的變化、失真。

如果使用 JAVA 語言,發生這種錯誤的情況稍少一些,因為在 JAVA 中沒有 wstring 這種概念,在內存中的 String,使用的編碼都是 Unicode,其中的轉換對于程序員來講是透明的。只要使用輸入 / 輸出方法時注意字節流的字符集選擇即可。

例如,編碼為中文 GB2312 的“標準”字符串被讀入內存后轉存為 UTF8 的過程:

圖 1. 文件轉換編碼的 JAVA 處理方式

但 C/C++ 編程,由于通常使用 char、string 類型的時候比較多,特別是進行文件讀寫,基本都是操作 char* 類型的數據。并且也沒有像 JAVA 中 getByte(String charsetname) 這種函數,不能直接根據字符集重新編碼得到字符串的 byte 數組。這時候,我們使用的 string 其實就一般不是 Unicode,而是符合某種編碼表的。這使得我們往往困惑于 string 的編碼問題。假設有 utf8 的字符串“一”(E4 B8 80),而我們錯誤的認為它是符合 gb2312(編碼 A)的,并將其轉換為 utf8(編碼 B),這種轉換結果是破壞性的,錯誤的輸出將永遠無法正確識別。

依然以“標準”為例,這是一個正確的轉換:

圖 2. 文件轉換編碼的 C/C++ 處理方式

第二種情況,則是更常見到的。例如:瀏覽器瀏覽網頁時的發生的亂碼問題;在寫 XML 文件時,指定了 < ?xml version="1.0" encoding="utf-8" ?> 然而文件中卻包含 GB2312 的字符串——這樣經常會導致 XML 文件 bad formatted,而使得解析器出錯。

這種情況下,其實數據都是正確的,只要瀏覽器選擇正確的編碼,將 XML 文件中的 GB2312 轉換為 UTF8 或者修改 encoding,就可以解決問題。

需要注意的是,ASCII 碼的字符,即單字節字符,一般不受編碼變動影響,在所有編碼表中的值是一樣的;需要小心處理的是多字節字符,例如中文語言。

一般的編碼轉換,直接做映射的不太可能,需要比較多的工作量,大多情況下還是選擇 Unicode 作為轉換的中介。

如前文所說,JAVA 的 String 對象是以 Unicode 編碼存在的,所以 JAVA 程序員主要關心的是讀入時判斷字節流的編碼,從而確保可以正確的轉化為 Unicode 編碼;相比之下,C/C++ 將外部文件讀出的數據存為字符數組、或者是 string 類型;而 wstring 才是符合 Unicode 編碼的雙字節數組。一般常用的方法是 C 標準庫的 wcstombs、mbstowcs 函數,和 windows API 的 MultiByteToWideChar 與 WideCharToMultiByte 函數來完成向 Unicode 的轉入和轉出。

這里以 MBs2WCs 函數的實現說明 GB2312 向 Unicode 的轉換的主要過程:

清單 1. 多字節字符串向寬字節字符串轉換

wchar_t * MBs2WCs(const char* pszSrc){

wchar_t* pwcs = NULL;

intsize = 0;

#ifdefined(_linux_)

setlocale(LC_ALL, "zh_CN.GB2312");

size = mbstowcs(NULL,pszSrc,0);

pwcs = new wchar_t[size+1];

size = mbstowcs(pwcs, pszSrc, size+1);

pwcs[size] = 0;

#else

size = MultiByteToWideChar(20936, 0, pszSrc, -1, 0, 0);

if(size <= 0)

returnNULL;

pwcs = new wchar_t[size];

MultiByteToWideChar(20936, 0, pszSrc, -1, pwcs, size);

#endif

returnpwcs;

}

相應的,WCs2MBs 可以將寬字符串轉化為字節流。

清單 2. 寬字節字符串向多字節字符串轉換

char* WCs2MBs(const wchar_t * wcharStr){

char* str = NULL;

intsize = 0;

#ifdefined(_linux_)

setlocale(LC_ALL, "zh_CN.UTF8");

size = wcstombs( NULL, wcharStr, 0);

str = new char[size + 1];

wcstombs( str, wcharStr, size);

str[size] = '\0';

#else

size = WideCharToMultiByte( CP_UTF8, 0, wcharStr, -1, NULL, NULL, NULL, NULL );

str = new char[size];

WideCharToMultiByte( CP_UTF8, 0, wcharStr, -1, str, size, NULL, NULL );

#endif

returnstr;

}

Linux 的 setlocale 的具體使用可以參閱有 C/C++ 文檔,它關系到文字、貨幣單位、時間等很多格式問題。Windows 相關的代碼中 20936 和宏定義 CP_UTF8 是 GB2312 編碼對應的的 Code Page[ 類似的 Code Page 參數可以從 MSDN的 Encoding Class 有關信息中獲得 ]。

這里需要特別指出的是 setlocale 的第二個參數,Linux 和 Windows 是不同的:

1. 筆者在 Eclipse CDT + MinGW 下使用 [country].[charset](如 zh_CN.gb2312 或 zh_CN.UTF8)的格式并不能通過編碼轉換測試,但可以使用 Code Page,即可以寫成 setlocale(LC_ALL, ".20936") 這樣的代碼。這說明,這個參數與編譯器無關,而與系統定義有關,而不同操作系統對于已安裝字符集的定義是不同的。

2. Linux 系統下可以參見 /usr/lib/locale/ 路徑,系統所支持的 locale 都在這里。轉換成 UTF8 時,并不需要 [country] 部分一定是 zh_CN,en_US.UTF8 也可以正常轉換。

另外,標準 C 和 Win32 API 函數返回值是不同的,標準 C 返回的 wchar_t 數組或者是 char 數組都沒有字符串結束符,需要手動賦值,所以 Linux 部分的代碼要有區別對待。

最后,還要注意應當在調用這兩個函數后釋放分配的空間。如果將 MBs2WCs 和 WCs2MBs 的返回值分別轉化為 wstring 和 string,就可以在它們函數體內做 delete,這里為了代碼簡明,故而省略,但請讀者別忘記。

目前的第三方工具已經比較完善,這里介紹兩個,本文側重點不在此,不對其做太多探討。

Linux 上存在第三方的 iconv 項目,使用也較為簡單,其實質也是以 Unicode 作為轉換的中介。可以參閱 iconv 相關網站。

ICU 是一個很完善的國際化工具。其中的 Code Page Conversion 功能也可以支持文本數據從任何字符集向 Unicode 的雙向轉換。可以訪問其 網站

在代碼中調用“編碼轉換方法”一節里提到的函數,將 gb2312 編碼的字符串轉換為 UTF8 編碼,分析其編碼轉換的行為:

在英文 Linux 環境下,執行下列命令:

export LC_ALL=zh_CN.gb2312

然后編譯并執行以下程序(其中漢字都是在 gb2312 環境中寫入源文件)

L1: wstring ws = L"一";

L2: string s_gb2312 = "一";

L3: wchar_t * wcs = MBs2WChar(s_gb2312.c_str());

L4: char* cs = WChar2MBs(wcs);

查看輸出:

L1 - 1 wide char: 0x04bb

L2 - 2 bytes:0xd2,0xbb,即 gb2312 編碼 0xD2BB

L3 - 返回的 wchar_t 數組內容為 0x4E00,也就是 Unicode 編碼

L4 - 將 Unicode 再度轉換為 UTF8 編碼,輸出的字符長度為 3,即 0xE4,oxB8,0x80

在 L1 行,執行結果顯示編碼為一個 0x04bb,其實這是一個轉換錯誤,如果使用其他漢字,如“哈”,編譯都將無法通過。也就是說 Linux 環境下,直接聲明中文寬字符串是不正確的,編譯器不能夠正確轉換。

而在中文 windows 下使用相同測試代碼,則會在 L1 處出現區別,ws 中的 wchar_t 元素十六進制值是 0x4e00,這是漢字“一”的 Unicode 編碼。

首先,這里先簡單說明一下 Unicode 和 UTF8 的關系:Unicode 的實現方式和它的編碼方式并不相同,UTF8 就是其實現之一。比方使用 UltraEdit 打開 UTF8 編碼的中文文件,使用 16 進制查看,可以發現看到的中文對應部分應當是 Unicode 編碼,每個中文字長度 2 字節—— UltraEdit 在這里已經做了轉化;如果直接查看其二進制文件,可以發現是 3 字節。但兩者的差別僅在于 Unicode 向 UTF8 做了數學上的轉化。(更多關于 Unicode 和 UTF8 的概念,可以參見 有關文獻)

其次,關于第三方庫的選擇,應當綜合考慮項目的需求。一般的文本字符轉換,系統的庫函數已經可以滿足需求,實現也很簡單;如果需要針對不同地區的語言、文字、習慣進行編程,需要更為豐富的功能,當然選擇成熟的第三方工具可以事半功倍。

最后,從邏輯上保持字符串的編碼正確,需要注意幾條一般規律:

編碼選擇:多國語言環境的編程,以使用 UTF 編碼為原則,減少字符集轉換。

string 并不包含編碼信息,但是編碼確定了 string 的二進制內容。

讀寫一致:讀入時使用的字符集要與寫出時使用的一致。如果不需要改變字符串內容,僅僅是將字符串讀入、再寫出,建議不要調整任何字符集——即使程序使用的系統默認字符集 A 與文件的實際編碼 B 不符合,寫出的字符串依然會是正確的 B 編碼。

讀入已知:對于必須處理、解析或顯示的字符串,從文件讀入時必須知道它的編碼,避免處理字符串的代碼簡單使用系統默認字符集;即便對于程序從系統中收集到的內存字符串,也應知道其符合的編碼格式——一般為系統默認字符集。

避免直接使用 Unicode:這里是說將非 ASCII 編碼的 16 進制或者 10 進制數值用 與 ; 包含起來的使用方式,例如將中文“一”寫成“e00;”。這種方法的實質是 Unicode 編碼直接寫入文件。這不僅會降低代碼的通用性、輸出文件的可讀性,處理起來也很困難。比如法文字符在其他字符集中是大于 80H 的單字節字符,程序同時要支持中文的時候,很有可能會將多字節的中文字符錯誤割裂。

避免陷入直接的字符集編程:國際化、本地化的工具已經比較成熟,非純粹做編碼轉換的程序員沒有必要自己去處理不同編碼表的映射轉換問題。

Unicode/UTF8 并不能解決一切亂碼問題:Unicode 可以說是將世界語言統一起來的一套編碼。但是這并不意味著在一個系統中可以正常顯示的按照 UTF8 編碼的文件,在另一個系統中也可以正常顯示。例如,在中文的 UTF8 編碼或者 Unicode 編碼在沒有東亞語言包支持的法文系統中,依然是不可識別的亂碼——盡管 UTF8、Unicode 它們都支持。

學習從 Nicolar M. Josuttis, C++ Standard Library, The: A Tutorial and Reference 這本書,或者在線鏈接 c++ reference可以獲得 C++ 標準庫有關信息

wikipedia 上有

Unicode 相關的概念解說

在 developerWorks 上查閱所有 Linux 技巧 和 Linux 教程。

獲得產品和技術下載

IBM 軟件試用版,體驗強大的 DB2?,Lotus?,Rational?,Tivoli?和

WebSphere?軟件。

討論

現供職于 IBM 上海 CSTL,Tools Center 項目組,主要進行 C/C++,XML,服務器工具方面的程序開發。有 6 年 JAVA 和 C/C++ 開發經驗,擁有上海交大計算機碩士學位。

總結

以上是生活随笔為你收集整理的c实现多语言编程,C/C++编程中多国语言处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 1000部拍拍拍18勿入免费视频 | 日本国产一级片 | 成人午夜sm精品久久久久久久 | 欧美日韩黄 | 一区二区片 | 韩日av网站 | 免费在线观看日韩 | 成年人网站免费视频 | 一区二区av在线 | 精品一区二区久久久久久久网站 | 日本国产一区二区三区 | 一级淫片免费 | 6080亚洲精品一区二区 | 男生操女生逼逼 | 香港三级韩国三级日本三级 | 中文字幕久久一区 | 禁断介护av | 欧美大片网站 | 奇米97 | 亚洲综合图片网 | 亚洲欧美日韩国产 | 午夜激情网 | 图书馆的女友动漫在线观看 | www.com欧美 | 少妇一级视频 | 久久精品国产亚洲7777 | 青青草综合 | 国产福利合集 | 波多野结衣亚洲视频 | 免费三片在线播放 | 久久精品香蕉视频 | 欧美区国产区 | 麻豆短视频在线观看 | 岛国av一区二区三区 | 欧洲亚洲女同hd | 国产chinesehd天美传媒 | 夜夜爽网站 | 精品少妇一区二区三区密爱 | 久久久久亚洲av成人网人人网站 | 可以在线观看的av网站 | 最新视频 - 88av | 日韩片在线观看 | 国产精品自产拍高潮在线观看 | 五月婷中文字幕 | 成人免费xxxxx在线视频 | 麻豆chinese新婚xxx | 超碰人人人| 亚洲成av人片在线观看无 | 日本免费毛片 | 精品视频一二区 | 日韩高清网站 | 天天色官网 | 日韩精品自拍 | 欧美乱妇日本无乱码特黄大片 | 永久免费在线 | 日韩在线一区视频 | 影音先锋一区 | 色屁屁一区二区三区 | 国产精品国产三级国产在线观看 | 欧美日韩在线播放三区四区 | 亚洲欧美成人一区二区三区 | 日韩看片 | 国产成人无码a区在线观看视频 | 日韩欧美精品久久 | 久久a毛片 | 999视频在线 | 黄在线免费 | 污污视频网站在线 | eeuss国产一区二区三区黑人 | 中文字幕电影一区二区 | 亚洲一区二区三区蜜桃 | 丰满岳妇乱一区二区三区 | 午夜精品福利一区二区三区蜜桃 | 精品999视频 | 啪啪av网| 性色av一区二区三区四区 | 国产一级淫 | av在线免费不卡 | 丝袜制服中文字幕 | 日本黄色激情视频 | 日韩理论在线观看 | 成人综合一区 | 成人ay| 欧美日韩一区三区 | 欧美孕妇性xx | 九草视频在线观看 | 国产视频第一区 | 国产一区伦理 | 久久精品视频2 | 一区二区三区四区在线播放 | 免费小视频在线观看 | 亚州av在线 | 久久不射网站 | 色综合久久久久久 | 伊人在线| 这里只有精品视频在线观看 | 精品久久久久久久免费人妻 | 毛片美女 | 国产裸体网站 |