所謂字符編碼方案就是將所需編碼的符號順序編號,統(tǒng)一用一個序列號來表示。編碼時當然會適當考慮分類的原則,即盡量將同類的字符放在一起,以相同的二進制開頭,如ASCII的a-b就分別對應(yīng)十進制的序號:97-122,97的二進制是0110 0001。
1 ASCII因為計算機是美國人最先搞出來的,而美國人使用的符號少,一個字節(jié)(8個位,0-11111111)就足夠了,這就是ASCII,包括大、小定英文字母、數(shù)字、一些可打印或不可打印的其它符號,共128個: 2 GB2312中國使用的漢字需要以萬計,常用的漢字也是以千計,一個字節(jié)遠遠不夠。(兩個字節(jié)16個位(0x0-0xffff)理論上可以表示2^16=65536個字符。)編碼需要考慮與ASCII兼容,且方便使用。 2.1 兼容ASCII。 2.2 由兩個大于127的字節(jié)來映射我們增加的字節(jié)(確保兩個字節(jié)的最高位都是1); 2.3 發(fā)現(xiàn)最高位是0,那么就可以確定這個字節(jié)映射的是ASCII的字符,那么就只讀取一個字節(jié),然后去查ASCII表,將其解析為ASCII表對應(yīng)的字符。發(fā)現(xiàn)最高位是1,那么就可以確定這個字節(jié)映射的就是GB2312的字符,那么就連續(xù)讀兩個字節(jié),然后去查GB2312,然后將其解析為對應(yīng)的字符。 2.4 ASCII重新映射了兩個字節(jié)的ASCII,這些稱為全角字符,而本身的ASCII的一個字節(jié)映射的字符,稱為半角字符。 2.5 后面又增加了一些字符,形成了GBK,然后再增加了一些,形成了GB18030,都向前兼容。 2.6 ANSI在不同操作系統(tǒng)中,對應(yīng)不同的字符編碼,如簡體中文的操作系統(tǒng),對應(yīng)GB2312,繁體的對應(yīng)Big5,日語的操作系統(tǒng)對應(yīng)JIS。 GB 2312標準共收錄6763個漢字,其中一級漢字3755個,二級漢字3008個;同時,GB 2312收錄了包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語西里爾字母在內(nèi)的682個全角字符。 GB 2312的出現(xiàn),基本滿足了漢字的計算機處理需要,它所收錄的漢字已經(jīng)覆蓋中國大陸99.75%的使用頻率。 對于人名、古漢語等方面出現(xiàn)的罕用字,GB 2312不能處理,這導(dǎo)致了后來GBK及GB 18030漢字字符集的出現(xiàn)。 GB 2312以編碼0xA1A0(10100001 10100000)開始: 3 unicode如果每個國家都搞自己的一套字符編碼方案,對于信息通信自然不便,為此,國際標準化組織便搞了一個統(tǒng)一的unicode字符編碼方案,盡可能包含各國使用的字符。 UCS-2用2個字節(jié)編碼,UCS-4用4個字節(jié)(0x0-0xffffffff)編碼(理論上2^32=4294967296)。 unicode本身只規(guī)定了對應(yīng)的二進制數(shù)是多少(也是一個序列號)。因為需要更多的位數(shù),但發(fā)現(xiàn)一些編碼在前的序列號使用一個字節(jié)或兩個字節(jié)就行了,如果同樣使用4個字節(jié)的話,會造成空間浪費,可以考慮另外經(jīng)濟的存儲方案。所以在unicode統(tǒng)一數(shù)字編碼的基礎(chǔ)上,再搞一套存儲的編碼方案,這就是utf,以用時間來換空間,或用空間換時間,或折衷,對應(yīng)utf-8、utf-32、utf-16,因為存儲的是另外一套編碼體系,需要再做轉(zhuǎn)換。轉(zhuǎn)換格式分別是: utf-8 不同的編碼段使用不同的字節(jié)數(shù)(1-6)存儲,一位的以0開關(guān),兩位的段以110和10開頭,三位的以1110和10、10開頭,四位的以11110和10、10、10開頭。這樣,編碼在前的字符存儲時就節(jié)省了空間,是一個以時間換空間的折衷方案。 utf-16 使用兩個字節(jié)或者4個字節(jié)來存儲,分兩個段,第一個段則直接存儲,不轉(zhuǎn)換,使用兩個字節(jié),如果屬于第二個段(高段),第1、2個字節(jié)以110110開頭,第3、4個字節(jié)的以110111開頭,其它的以unicode編碼依次填入。 utf-32:固定長度,使用4個字節(jié)存儲,以空間換時間(因為不需要轉(zhuǎn)換了)。 4 C++使用的字符串在 C++ 中,以前通常使用 char 表示單字節(jié)的字符,使用 wchar_t 表示寬字符,對國際碼提供一定程度的支持。 char * 字符串有專門的封裝類 std::string 來處理,標準輸入輸出流是 std::cin 和 std::cout 。對于 wchar_t * 字符串,其封裝類是 std::wstring,標準輸入輸出流是 wcin 和 wcout。雖然規(guī)定了寬字符,但是沒有明確一個寬字符是占用幾個字節(jié),Windows 系統(tǒng)里的寬字符是兩個字節(jié),就是 UTF-16;而 Unix/Linux 系統(tǒng)里為了更全面的國際碼支持,其寬字符是四個字節(jié),即 UTF-32 編碼。這為程序的跨平臺帶來一定的混亂,除了 Windows 程序開發(fā)常用 wchar_t* 字符串表示 UTF-16 ,其他情況下 wchar_t* 都用得比較少。MFC 一般用自家的 TCHAR 和 CString 類支持國際化,當沒有定義 _UNICODE 宏時,TCHAR = char,當定義了 _UNICODE宏 時,TCHAR = wchar_t,CString 內(nèi)部也是類似的。Qt 則用 QChar 和 QString 類(內(nèi)部恒定為 UTF-16),一般的圖形開發(fā)庫都用自家的字符串類庫。在新標準 C++11 中,對國際碼的支持做了明確的規(guī)定: char * 對應(yīng) UTF-8 編碼字符串(代碼表示如 u8'多種文字'),封裝類為 std::string; 新增 char16_t * 對應(yīng) UTF-16 編碼字符串(代碼表示如 u'多種文字'),封裝類為 std::u16string ; 新增 char32_t * 對應(yīng) UTF-32 編碼字符串(代碼表示如 U'多種文字'),封裝類為 std::u32string 。 因為 Qt 有封裝好的 QString,所以不太需要這些新增的字符串格式。 -End- |
|