計算機編碼原理——不同數據類型存儲中文編碼

  作者以前在Windows平臺編程時,對於字符串顯示中文以及不同的字符集編碼格式不太理解。最近編寫資料用到這部分知識,便通過自己的分析和參考資料做了簡單運用,下面我們一起分析常用的編碼集與中文編碼!


章節預覽:


1.字符數組存儲GB2312中文編碼
2.GB2312標準
3.輸出亂碼原理
4.整數存儲GB2312中文編碼
5.Uncode
6.UTF-8
7.整數存儲UTF-8中文編碼


章節內容:


字符數組存儲GB2312中文編碼:


  首先,我們通過字符數組輸出“你好”,參考代碼:
    unsigned char testch[4] = {0};
    memcpy(testch, “你好”, strlen(“你好”));
    printf("%s|", testch);

    得出的結果爲:你好燙燙燙燙
                              |


首先,我們分析testch輸出的信息:

  我們定義一個256字節的字符數組保存testch值:
    unsigned char testch2[256] = {0};
    memcpy(testch2, testch, 255);
      展開testch2:
        - testch2 0x00aff9f0 "你好燙燙燙燙
        " unsigned char [256]
        [0] 196 ‘?’ unsigned char
        [1] 227 ‘?’ unsigned char
        [2] 186 ‘?’ unsigned char
        [3] 195 ‘?’ unsigned char
        [4] 204 ‘?’ unsigned char
        [5] 204 ‘?’ unsigned char
        [6] 204 ‘?’ unsigned char
        [7] 204 ‘?’ unsigned char
        [8] 204 ‘?’ unsigned char
        [9] 204 ‘?’ unsigned char
        [10] 204 ‘?’ unsigned char
        [11] 204 ‘?’ unsigned char
        [12] 10 ’
        ’ unsigned char
        [13] 0 unsigned char

        Byte13值爲0,程序輸出的testch信息到這裏終止。


然後,我們分析testch輸出的信息內容:

  GB2312規定對匹配的每個字符采用兩個字節表示,在VS2010編譯器中可以這麼認爲(與GB2312標準定義有出入):
    當前字節值爲0-128時,採用國際Ascll碼錶方式計算,當前字節信息會以Ascll碼錶對應符顯示;
    當前字節值大於或等於129時,後面的一個字節與當前字節被認爲是一個GB2312編碼匹配(採用兩個字節位數合併成一個16位數字(低字節在低8位,高字節在高8位)),數字值如果在GB2312編碼內,將顯示GB2312中的對應信息,否則(數字值如果不在GB2312編碼內)按照單個字節顯示。


GB2312標準:


  GB2312是中國主要官方字符集的註冊名稱,用於簡體中文字符。GB縮寫爲國家標準,由中國國家標準總局1980年發佈,1981年5月1日開始使用。GB2312編碼共收錄漢字6763個,其中一級漢字3755個,二級漢字3008個。

  GB2312規定對收錄的每個字符采用兩個字節表示,第一個字節爲“高字節”,對應94個區;第二個字節爲“低字節”,對應94個位,所以它的區位碼範圍是:0101-9494。區號和位號分別加上0xA0就是GB2312編碼。例如最後一個碼位是9494,區號和位號分別轉換成十六進制是5E5E,0x5E+0xA0=0xFE,所以該碼位的GB2312編碼是FEFE。

  GB2312編碼範圍爲0xA1A1—0xFEFE,其中漢字的編碼範圍爲0xB0A1-0xF7FE,第一字節0xB0-0xF7(對應區號:16——87),第二個字節0xA1-0xFE(對應位號:01—94)。


輸出亂碼原因:


  當我們使用字符數組存儲信息並且沒有做字符串結尾(最後一個字節置爲空字符)時,將會發生“內存訪問越位”的情況,因爲,VS2010編譯器會自動把未使用的棧內存空間按字節全部初始化爲0xCC(無符號204),當兩個字節都爲0xCC時,顯示爲GB2312編碼中的“燙”漢字。


整數存儲GB2312中文編碼:


unsigned short:

  在32位編譯器中,一個unsigned short類型佔用2個字節,我們可以通過unsigned short數組保存數據,並輸出“你好”:
    unsigned short sho[3] = {58308,50106,0};
    printf("%s", sho);
    第一個值:58308 轉成二進制數字爲 1110 0011,1100 0100,中文“你”;
    第二個值:50106 轉成二進制數字爲 1110 0011,1011 1010,中文“好”;
    第三個值:作爲空字符使用。

    位數順序:左高右低。


unsigned int:

  在32位編譯器中,一個unsigned int類型佔用4個字節,輸出“你好”:
    unsigned int sho[2] = {3283805124,0};
    printf("%s", sho);
    第一個值:3283805124 轉成二進制數字爲 1100 0011 1011 1010,1110 0011 1100 0100‬,中文“你好”;
    第二個值:作爲空字符使用。

    使用unsigned int類型存儲GB2312數據時,採用2個字節爲一組,3、4字節(中文“好”)在左,1、2字節(中文“你”)在右, 組內順序也是左高右低。


long long:

  在大部分編譯器中,一個long long類型佔用8個字節,輸出“你好呀”:
    long long sho = 208708629619652;
    printf("%s", &sho);
    參數值:208708629619652 或 十六進制 0xBDD1C3BAE3C4 轉成二進制數字爲:
    1011 1101 1101 0001,1100 0011 1011 1010,1110 0011 1100 0100,中文“你好呀”;

    使用long long類型類型存儲GB2312數據時,存儲形式與int相同。示例中我們只輸出3個GB2312字符,6、7字節爲空字符使用。

  在這裏我們可以看出使用無符號類型和有符號類型輸出的結果相同,大部分示例中採用無符號類型只是爲了方便參考數據。


Uncode:


  在非 Unicode 環境下,由於不同國家和地區採用的字符集不一致,很可能出現無法正常顯示所有字符的情況。微軟公司使用了代碼頁(Codepage)轉換表的技術來過渡性的部分解決這一問題,即通過指定的轉換表將非 Unicode 的字符編碼轉換爲同一字符對應的系統內部使用的 Unicode 編碼。
MultiByteToWideChar是一種windows API 函數,該函數映射一個字符串到一個寬字符(Unicode)的字符串。


UTF-8:


  UTF-8是針對Unicode的一種可變長度字符編碼,它可以用來表示Unicode標準中的任何字符,UTF-8將每個Unicode字符編碼爲1到4個八位字節的可變數字,其中八位字節的數目取決於分配給Unicode字符的整數值。這是對Unicode文檔的有效編碼,主要使用US-ASCII字符,因爲它將範圍在U + 0000到U + 007F之間的每個字符表示爲一個八位字節。


整數存儲UTF-8中文編碼:


long long:

  由於UTF-8字符集存在字節不確定因素,直接使用long long類型輸出“你好”:
    system(“chcp 65001”); //在VS2010編譯器中,我們選擇向控制檯輸出UTF-8信息
    long long sho = 208520219770340;
    printf("%s", &sho);
    參數值:208520219770340 或十六進制 0xBDA5E5A0BDE4 轉成二進制數字爲:
‬    1011 1101 1010 0101 1110 0101, 1010 0000 1011 1101 1110 0100‬,中文“你好”;

    示例中“你”、“好”分別佔用三個字節,6、5、4字節(中文“好”)在左,3、2、1字節(中文“你”)在右, 組內順序也是左高右低。

發佈了97 篇原創文章 · 獲贊 218 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章