所謂字符編碼方案就是將所需編碼的符號順序編號,統(tǒng)一用一個序列號來表示。編碼時當然會適當考慮分類的原則,即盡量將同類的字符放在一起,以相同的二進制開頭,如ASCII的a-b就分別對應(yīng)十進制的序號:97-122,97的二進制是0110 0001。
對于字符的數(shù)據(jù)表示使用編碼方案(字符用順序號編碼),而對于字符的輸出則一般是用點陣圖形來輸出的。而對于輸入來說,英文就簡單了,直接按鍵盤輸入即可,中文則不可能直接使用編碼方案的順序號來輸入,因為那樣不夠直觀,不方便記憶和操作,為此,搞出來不同的輸入方案,如五筆、拼音輸入法。對于存儲呢?簡單的方法當然是以最大的編碼(順序號)所需的字節(jié)數(shù)來存儲,但對于需要多個字節(jié)的編碼方案來說,存儲編碼(順序號)在最前面的部分顯然并不需要最大的字節(jié)數(shù),所以對于多字節(jié)編碼的方案往往會按一定規(guī)則另外搞出一套存儲方案,然后按規(guī)則做適當?shù)霓D(zhuǎn)換即可,這是一種以時間換空間的做法。
因為計算機是美國人最先搞出來的,而美國人使用的符號少,一個字節(jié)(8個位,0-11111111)就足夠了,這就是ASCII,包括大、小定英文字母、數(shù)字、一些可打印或不可打印的其它符號,共128個:
中國使用的漢字需要以萬計,常用的漢字也是以千計,一個字節(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)開始:
如果每個國家都搞自己的一套字符編碼方案,對于信息通信自然不便,為此,國際標準化組織便搞了一個統(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)換了)。
在 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-
聯(lián)系客服