ascii編碼與unicode編碼

2021-02-19 大人物小城夢

    定義字符數組 szHello ,初值為 "Hello"。編寫程序1:

#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ char szHello[] = "Hello"; printf("%s\r\n", szHello); system("pause"); return 0;}

    按 F10 進行單步調試,發現 Hello 字符串的每個字符在內存中各佔一個字節,這就是 ascii碼 。由美國人發明,所以只出現大小寫英文字母、數字和一些符號。因此,最早只有127個字符被編碼到計算機裡,也就是 7位 2進位數字,最高位(第八位)為 0 。

    這個編碼表被稱為 ascii編碼,比如大寫字母 H 的編碼是 72(16進位48),小寫字母 o 的編碼是 111(16進位6F)。

    定義字符數組 szHello ,初值為 "Hello同學們"。編寫程序2: 

#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ char szHello[] = "Hello同學們"; printf("%s\r\n", szHello); system("pause"); return 0;}

    按 F10 進行單步調試,發現字符串 "Hello" 的每個字符在內存中仍各佔一個字節,但是字符串 "同學們",每一個漢子在內存中卻佔兩個字節。

    這是因為,在中國1990年出版的《辭海》就高達14872個漢字,上面提到的 ascii編碼,每個字只用一個字節表示,最多可表示 256 個字,顯然是遠遠不夠的,至少需要兩個字節,而且還不能和ASCII編碼衝突,所以,中國制定了GB2312編碼,用來把中文編進去。

    可以想得到的是,全世界有上百種語言,日本,韓國等,並且各國有各國的標準,就會不可避免地出現衝突,結果就是,在多語言混合的文本中,顯示出來會有亂碼。

    因此,unicode編碼應運而生。unicode編碼在內存中佔兩個字節,最多可表示 65535 個字,可以把所有語言都統一到一套編碼裡,這樣就解決了亂碼問題。

    通過調試結果也可以看出,字節值為正數,用 ascii 編碼表示英文;字節值負數,用 unicode 編碼表示中文。

    編譯執行,並不會出現亂碼輸出。

    但是如果在英文中文混用的情況下,編譯器判斷一個字節出錯時,會連續判斷錯誤,造成大面積的亂碼。例如將 6F 改為 8F,如下圖所示,導致"同學們"字符串均發生亂碼。

    因為中英文混用時,內存中一會佔一個字節,一會佔兩個字節,編譯器處理的難度會提升很多,容易造成亂碼現象。利用空間換時間的思維,不論英文還是中文,都利用 unicode編碼方式,全部在內存空間中佔兩個字節。

    將內存空間佔一個字節的變量類型 char ,改為內存空間佔兩個字節的變量類型 unsigned short int 。編寫程序3:

#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ unsigned short int szHello[] = "Hello同學們"; printf("%s\r\n", szHello); system("pause"); return 0;}

    

    因為字符串 "Hello同學們" 仍是 ascii編碼方式,所以編譯未通過,提示無法從 char [12] 轉換為 unsigned short [],沒有可以進行這種轉換的環境。

    在字符串前加 L ,如 L"我的字符串" 表示將 ascii編碼字符串轉換成 unicode編碼的字符串。在字符串 "Hello同學們" 前加 L,編寫程序4:

#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ unsigned short int szHello[] = L"Hello同學們"; printf("%s\r\n", szHello); system("pause"); return 0;}

    編譯通過。按 F10 進行單步調試,字符串中的每個字符和漢字都各佔兩個字節的內存空間。

    printf 函數是按 ascii編碼方式列印,默認字符串 \0 結尾,因為字符串 "Hello同學們" 是 unicode編碼,所以在 H 字符後是 00 ,printf 看見 00 結束列印,只輸出 H 。

    查看 MSDN 可知,列印 unicode編碼字符串,必須要用 wprintf 函數。因為 wprintf函數是 printf函數的寬字節版本,但兩函數的行為相同。 

    將 printf 函數改為 wprintf 函數。編寫程序5:

#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ unsigned short int szHello[] = L"Hello同學們"; wprintf(L"%s", szHello); system("pause"); return 0;}

    編譯執行,只輸出了 Hello,而中文部分字符串"同學們"卻沒有輸出。

    只有利用 setlocale 函數,設置當前位置,才能顯示中文部分的字符串。查看 MSDN,輸出簡體中文用 "chs" 。

    根據 MSDN 獲取到的修改方式,編寫程序6:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>
int main(int argc, char* argv[]){ setlocale(LC_ALL, "chs"); unsigned short int szHello[] = L"Hello同學們"; wprintf(L"%s\r\n", szHello); system("pause"); return 0;}

    編譯執行,輸出 "Hello同學們" 成功。

    利用編譯選項宏實現 ascii編碼方式和unicode編碼方式的隨時切換,思路為如果定義宏 MYUNICODE ,代碼全部為 unicode編碼模式,否則代碼全部為 ascii編碼模式。編寫程序7:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>
#define MYUNICODE
#ifdef MYUNICODE#define TCHAR unsigned short int#define _tprintf wprintf#define _tmain wmain#define _tsetlocale _wsetlocale#define _tsystem _wsystem#define _T(x) L ## x
#else #define TCHAR char #define _tprintf printf#define _tmain main#define _tsetlocale setlocale#define _tsystem system#define _T(x) x
#endif
int main(int argc, char* argv[]){ _tsetlocale(LC_ALL, _T("chs")); TCHAR szHello[] = _T("Hello同學們"); _tprintf(_T("%s\r\n"), szHello); _tsystem(_T("pause")); return 0;}

    按 F10 進行單步調試,字符串以 unicode編碼方式在內存中存儲。

    注釋掉宏 MYUNICODE 。編寫程序8:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>

#ifdef MYUNICODE#define TCHAR unsigned short int#define _tprintf wprintf#define _tmain wmain#define _tsetlocale _wsetlocale#define _tsystem _wsystem#define _T(x) L ## x
#else #define TCHAR char #define _tprintf printf#define _tmain main#define _tsetlocale setlocale#define _tsystem system#define _T(x) x
#endif
int main(int argc, char* argv[]){ _tsetlocale(LC_ALL, _T("chs")); TCHAR szHello[] = _T("Hello同學們"); _tprintf(_T("%s\r\n"), szHello); _tsystem(_T("pause")); return 0;}

    按 F10 進行單步調試,字符串以 ascii編碼方式在內存中存儲。

相關焦點

  • Python 2.x 字符編碼終極指南
    我們知道,ascii 只包含 127 個字符,根本無法表示中文。所以,讓 ascii 來編碼、解碼中文,就超出了其能力範圍。這就像你對一個不懂中文的老外說中文,他根本沒法聽懂。簡單來說,所有的編碼、解碼錯誤都是由於所選的編碼、解碼方式無法表示某些字符造成的。有時候我們就是想用 ascii 去編碼一段夾雜中文的str字節串,並不希望拋出異常。
  • Python 編碼為什麼那麼蛋疼?
    本質上 str 是一串二進位字節序列,下面的示例代碼可以看出 str 類型的 「禪」 列印出來是十六進位的 \xec\xf8 ,對應的二進位字節序列就是 『11101100 11111000』。'>>> type(u)<type 'unicode'>我們要把 unicode 符號保存到文件或者傳輸到網絡就需要經過編碼處理轉換成 str 類型,於是 python 提供了 encode 方法,從 unicode 轉換到 str,反之亦然。
  • Python 編碼錯誤的本質原因
    再來說說 Python 中的編碼問題。Python 的誕生時間比 Unicode 要早很多,Python2 的默認編碼是ASCII,正因為如此,才導致很多的編碼問題。錯誤的原因在字符編碼轉換操作時,遇到最多的問題就是 UnicodeEncodeError 和 UnicodeDecodeError 錯誤了,這些錯誤的根本原因在於 Python2 默認是使用 ascii 編碼進行 decode 和 encode 操作,例如:CASE 1>>> s = '你好'
  • glibc字符編碼研究
    Unicode是國際組織制定的可以容納世界上所有文字和符號的字符編碼系統,有UCS-2和UCS-4兩種編碼規範,其中UCS-2編碼長度為2位元組,UCS-4是前者的擴展採用4位元組編碼,因此UCS-4字符集的容量大於UCS-2,在Linux的glibc中對unicode的處理都是UCS-4編碼規範。unicode編碼系統兼容了ASCII編碼系統,因此unicode的前128個編碼對應了ascii碼。
  • 深入淺出 + 徹底理解 Python 編碼
    下面,我們在python命令行中輸入如下兩行代碼:e = s.decode("utf-8")isinstance(e,unicode)程序的輸出是True,這說明,decode後返回的e確實是一個unicode對象。unicode在這裡是一個類,是python裡面的類。
  • 如何正確解決Python中的中文編碼問題?
    編程派微信號:codingpy作者:xianglong原文連結:http://xianglong.me/article/learn-python-1-chinese-encoding/字符串是Python中最常用的數據類型,而且很多時候你會用到一些不屬於標準ASCII字符集的字符,這時候代碼就很可能拋出UnicodeDecodeError: 'ascii
  • 給妹子講python-S01E08理清python中的字符編碼方法
    接下來我們來比較一下unicode、latin-1、ASCII編碼方式的兼容性問題:首先,非ASCII字符無法使用ASCII編碼轉換成字節字符串s = 'π排球の'b = s.encode('ascii')Traceback (most recent call
  • Python 與 Unicode
    unicode 與 utf8 的關係unicode 定義了統一的字符集, UTF8 則是一種編碼 unicode 字符集的方式.在 python2 中, str 類型, unicode 類型都是 basestring 的子類, 其中 str 類型就好比 C 語言中的字符串, unicode 類型就好比 C 語言中的寬字符串.因為 utf8 的編碼方式不使用 0x0 填充, 一串 utf8 字符流實際上也是一串合法的 c 字符流 (0x0 結尾) — 也就是合法的 str 類型的字符流.
  • 字符編碼那些事:Unicode與UTF-8(見過但沒懂過,說的就是你)
    所以,ASCII編碼和Unicode編碼的區別:ASCII編碼是1個字節,而Unicode編碼通常是2個字節。但是,如果你寫的文本基本上全部是英文的話,用Unicode編碼比ASCII編碼需要多一倍的存儲空間,並不划算。因此,迎來了把Unicode編碼轉化為「可變長編碼」的UTF-8編碼。UTF-8編碼把一個Unicode字符根據不同的數字大小編碼成1-6個字節,常用的英文字母被編碼成1個字節,漢字通常是3個字節,只有很生僻的字符才會被編碼成4-6個字節。
  • 運維開發:字符集編碼 ASCII,Unicode 和 UTF-8 你知多少
    這樣一來,這些歐洲國家使用的編碼體系,可以表示最多256個符號。但是,這裡又出現了新的問題。不同的國家有不同的字母,因此,哪怕它們都使用256個符號的編碼方式,代表的字母卻不一樣。比如,130在法語編碼中代表了é,在希伯來語編碼中卻代表了字母Gimel (ג),在俄語編碼中又會代表另一個符號。
  • 來了解一下文件編碼!
    與數值信息一樣,為了便於在不同的系統之間進行交換,字符必須採用標準的二進位編碼表示。但字符和國家、地區的文化有關,情況非常複雜,本文主要介紹西文字符和漢字字符的常用編碼表示。       目前計算機中使用的最廣泛的西文字符集機器編碼就是ascii字符集和ascii碼,即美國信息交換標準碼。
  • 【Python基礎】(6.1)字符編碼
    # ASCII表的特點: 1、只有英文字符與數字的一一對應關係 2、一個英文字符對應1Bytes,1Bytes=8bit,8bit最多包含256個數字,可以對應256個字符,足夠表示所有英文字符插圖:ascii
  • Python中常用的字符編碼,編碼解碼之間的轉換
    ,它是現今最通用的單字節編碼系統。每個符號的編碼都不一樣,比如,U+0639表示阿拉伯字母Ain,U+0041表示英語的大寫字母A,U+4E25表示漢字嚴。具體的符號對應表,可以查詢unicode.org,或者專門的漢字對應表。Unicode的問題:Unicode只是一個符號集,它只規定了符號的二進位代碼,卻沒有規定這個二進位代碼應該如何存儲。
  • 給妹子講python-S01E07字符編碼歷史觀:從ASCII到Unicode
    2.ASCII編碼到Unicode編碼的發展過程3.容易混淆的字符編碼與字符代碼【妹子說】上兩集基本上讓我們熟悉了字符串的常見用法,不過倒也讓我想起一直以來困惑的一些概念:ASCII碼、Unicode、字符編碼什麼的,一直沒搞明白過,今天不妨就來介紹一下這方面的內容吧。
  • 【Python進階】2.9將Unicode文本標準化
    解決方案在Unicode中,某些字符能夠用多個合法的編碼表示。; t1 == t2True>>> print(ascii(t1))'Spicy Jalape\xf1o'>>> t3 = unicodedata.normalize('NFD', s1)>>> t4 = unicodedata.normalize('NFD', s2)>>> t3
  • 科普:Python編碼的前世今生
    Unicode只是規定如何編碼,並沒有規定如何傳輸、保存這個編碼。例如「漢」字的Unicode編碼是 6C49,我可以用4個 ASCII 數字來傳輸、保存這個編碼;也可以用UTF-8編碼的3個連續的字節 E6 B1 89來表示它。關鍵在於通信雙方都要認可。因此Unicode編碼有不同的實現方式,比如:UTF-8、UTF-16等等。
  • 帶你走進編碼的世界——Unicode編碼
    美國人發明了計算機,設置了最早的編碼,他們只將數字、大小寫英文字母及一些符號一共128個字符編碼到計算機中。這套編碼表就是著名的ASCII編碼表,例如大寫字母A的二進位編碼為01000001,十進位編碼為65,十六進位編碼為41;小寫字母a的二進位編碼為01100001,十進位編碼為97,十六進位編碼為61。
  • 關於Unicode編碼
    對於遵從ISO2022的8比特編碼字符集,也是按照上述7比特編碼原則設計的編碼方案。這種8比特編碼字符集很容易兼容當時的7比特寬的通信協議/通信設備。8比特字符編碼時,0x00-0x1F表示C0或稱CL區(L是left縮寫,因為其在字符表的左側),0x80-0x9F表示C1或稱CR(R是Right縮寫,因為其在字符表的右側)。
  • ASCII、ANSI、GB2312、GBK、UNICODE、UTF-8 五種編碼的簡介
    然後我們就使用 ANSI 來對 GB2312,GBK,Shift_JIS,EUC_KR 進行一個統稱,即指不同國家對 ASCII 編碼的擴展,成為 ANSI 。這樣在中文簡體電腦系統下 ANSI 默認指的是 GB2312,在繁體系統下默認是採用 BIG5 編碼,在日文電腦系統中 ANSI 默認是 Shift_JIS 編碼,韓文就是 EUC_KR。
  • Unicode和UTF-8
    我們都知道Python2默認使用ASCII字符編碼(Python3默認使用UTF-8字符編碼),因為Python2這門語言發布的時候,Unicode編碼還沒有誕生,見這篇文章Python編碼為什麼那麼蛋疼?。