1. 程式人生 > >c++ 中文字元

c++ 中文字元

UTF-8

網際網路的普及,強烈要求出現一種統一的編碼方式。UTF-8就是在網際網路上使用最廣的一種Unicode的實現方式。其他實現方式還包括UTF-16(字元用兩個位元組或四個位元組表示)和UTF-32(字元用四個位元組表示),不過在網際網路上基本不用。重複一遍,這裡的關係是,UTF-8是Unicode的實現方式之一。

UTF-8最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個位元組表示一個符號,根據不同的符號而變化位元組長度。

UTF-8的編碼規則很簡單,只有二條:

1)對於單位元組的符號,位元組的第一位設為0,後面7位為這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。

2)對於n位元組的符號(n>1),第一個位元組的前n位都設為1,第n+1位設為0,後面位元組的前兩位一律設為10。剩下的沒有提及的二進位制位,全部為這個符號的unicode碼。

下表總結了編碼規則,字母x表示可用編碼的位。

Unicode符號範圍 | UTF-8編碼方式
(十六進位制) | (二進位制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

跟據上表,解讀UTF-8編碼非常簡單。如果一個位元組的第一位是0,則這個位元組單獨就是一個字元;如果第一位是1,則連續有多少個1,就表示當前字元佔用多少個位元組。

下面,還是以漢字"嚴"為例,演示如何實現UTF-8編碼。

已知"嚴"的unicode是4E25(100111000100101),根據上表,可以發現4E25處在第三行的範圍內(0000 0800-0000 FFFF),因此"嚴"的UTF-8編碼需要三個位元組,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然後,從"嚴"的最後一個二進位制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就得到了,"嚴"的UTF-8編碼是"11100100 10111000 10100101",轉換成十六進位制就是E4B8A5。

然後,用文字編輯軟體UltraEdit中的"十六進位制功能",觀察該檔案的內部編碼方式。

1)ANSI:檔案的編碼就是兩個位元組"D1 CF",這正是"嚴"的GB2312編碼,這也暗示GB2312是採用大頭方式儲存的。

2)Unicode:編碼是四個位元組"FF FE 25 4E",其中"FF FE"表明是小頭方式儲存,真正的編碼是4E25。

3)Unicode big endian:編碼是四個位元組"FE FF 4E 25",其中"FE FF"表明是大頭方式儲存。

4)UTF-8:編碼是六個位元組"EF BB BF E4 B8 A5",前三個位元組"EF BB BF"表示這是UTF-8編碼,後三個"E4B8A5"就是"嚴"的具體編碼,它的儲存順序與編碼順序是一致的。



本地化策略集(locale)

“將 ‘a’翻譯成0x61的整數值”,“將ASCII範圍內的編碼與char的整數值對應起來”,類似這樣的規定,是特定系統和特定編譯器制定的,C/C++ 中有個特定的名詞來描述這種規定的集合:本地化策略集(locale。也有翻譯成“現場”)。而翻譯——也就是程式碼轉換(codecvt)只是這個集合中的一個,C++中定義為策略(facet。也有翻譯為“刻面”)

C/C++ 的編譯策略

“本地化策略集”是個很好的概念,可惜在字元和字串這個層面上,C/C++並不使用(C++的locale通常只是影響流(stream)),C/C++使用更直接簡單的策略:硬編碼。

簡單的說,字元(串)在程式檔案(可執行檔案,非原始檔)中的表示,與在程式執行中在記憶體中的表示一致。

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

http://blog.jobbole.com/108860/

然後,用文字編輯軟體UltraEdit中的"十六進位制功能",觀察該檔案的內部編碼方式。

1)ANSI:檔案的編碼就是兩個位元組"D1 CF",這正是"嚴"的GB2312編碼,這也暗示GB2312是採用大頭方式儲存的。

2)Unicode:編碼是四個位元組"FF FE 25 4E",其中"FF FE"表明是小頭方式儲存,真正的編碼是4E25。

3)Unicode big endian:編碼是四個位元組"FE FF 4E 25",其中"FE FF"表明是大頭方式儲存。

4)UTF-8:編碼是六個位元組"EF BB BF E4 B8 A5",前三個位元組"EF BB BF"表示這是UTF-8編碼,後三個"E4B8A5"就是"嚴"的具體編碼,它的儲存順序與編碼順序是一致的。