iconv 判斷字元編碼 C 中的中文編碼

2021-10-14 06:30:10 字數 3256 閱讀 5308

中文編碼是乙個複雜而繁瑣的問題,尤其是在使用c++的時候,不像python這種直接就可以迭代出單個中文字元,c++中是以位元組為單位的,那麼我們要讀取乙個中文字元就要讀取三次位元組流,讀取英文本元就只需要讀取一次,是不是超級麻煩。那麼c++怎麼樣在中英文混合的字串中分離中英文或者計算字串長度(不是位元組數)呢,那就需要徹底搞清楚編碼是個怎麼回事。

ascii 碼,全稱 american standard code for information interchange,一共規定了 128 個字元的編碼,包括 10 個阿拉伯數字(從0x30開始,使用16進製表示)、26 個大寫字母(從65開始)、26 個小寫字母(從97開始),33 個英文標點符號,及 32 個控制字元,還有最後乙個0x7f

128 個字元,至少需要 7 個位元(bit)來表示,而乙個位元組(byte)有 8 個位元,故將位元組的最高位的位元規定為 0(這是規定),使用剩下的 7 個位元,剛好可以完整的表示 ascii 碼規定的字元。

阿拉伯數字的編碼從0x300x39,按順序分別表示 0 到 9 這 10 個字元。這樣帶來了乙個優勢:可以直接做字元的減法,得到字元對應的數字大小。大寫字母和小寫字母亦是如此。舉個例子:

char ch_9 = '9';

int value = ch_9 - '0';

assert(value == 9);

大寫字母從0x41開始(二進位制表示1000001),小寫字母從0x61(二進位制表示1100001)開始。注意觀察,二者相差了乙個0x20,即 32。任意乙個小寫字母對比對應的大寫字母,僅第 6 個比特有 1 與 0 的不同。進而可以通過這一點進行大小寫字母的判斷及其轉換。

//判斷字母大小寫

char a = 'b';

if ((a & 0x20) == 0x20)

//小寫轉大寫

char a = 'b';

char c = a ^ 0x20;

cout << c << endl;

//輸出 b

//大寫轉小寫

char a = 'b';

char c = a | 0x20;

cout << c << endl;

//輸出 b

//當然直接加上或者減去 32 也是可以實現大小寫轉換的

ascii 中的控制字元較為少用,有印象的僅僅是bell字元(0x07)。大一學習程式設計的時候發現可以通過printf("a");使用電腦發出蜂鳴聲,如今在 mac 上嘗試依然有效。

ascii 碼僅規定了 128 個字元,只能滿足英文的基本需求。乙個位元組最多能表示 256 個字元,而中文的常用漢字就有數千了,故而需要使用多個位元組來表示漢字。兩個位元組可以表示的字元上限為 65536,絕大部分情況下能夠滿足漢字使用的需求了。經典的漢字編碼包括gbk、gb2312、gb18030、cp939等。

在漢字編碼中,之前 ascii 碼沒有使用的最高位派上了用場。如果乙個位元組最高位是 0,說明這個位元組便是 ascii 碼,查表解析即可;如果最高位非 0,那麼說明這是乙個多位元組編碼,需要聯合下乙個位元組一起進行解析。

unicode 便是便是文字和符號的統一度量衡。unicode,unique code,universe code,全世界每乙個字元對應乙個唯一的編碼。unicode 收錄了大量的漢字,漢字的編碼從0x4e00開始,到0x9fff結束。

然而 unicode 僅僅定義了符號與二進位制編碼的關係,但沒有定義如何儲存和解析這些二進位制編碼。如果直接將二進位制編碼寫入檔案,那麼讀取時會產生歧義。例如4e 00 41,你無法知道這記錄的是 1 個字元,還是 2 個字元(可以解碼為「一a」),或者是 3 個字元(可以解碼為「n[空]a」)。如果統一每個字元的記錄長度,那麼對於常用中文便需要至少 3 個位元組來表示乙個符號,那麼對於全英的檔案則太浪費了。

unicode 解決了編碼統一的問題,但沒有解決編碼儲存和解析的問題。utf-8 則解決了 unicode 沒有解決的問題。

utf-8對於原有的 ascii 碼完全相容,而最高位的 1 的數量表示當前字元占用的位元組數。可以通過上表將 unicode 轉換為utf-8編碼,即將 x 按照高低位順序替換為 unicode 的二進位制位,缺了則使用 0 補齊。以漢字「一」為例,其 unicode 編碼為0x4e00,對應的二進位制為100 1110 0000 0000,二進位制共計 15 位。填充到1110***x 10****** 10******中(從右往左依次替換掉x,因為有16個x,所有最左邊的乙個x用0代替),最高位缺了一位,使用 0 補齊,最終可得11100100 10111000 10000000,即e4 b8 80。使用一行python3**驗證一下:

print(b'xe4xb8x80'.decode())

# 列印結果:一

utf-8編碼還保持著乙個優秀的特性,無論是使用左對齊(字串排序),還是右對齊(數值排序),utf-8編碼始終保持著與 unicode 一致的大小順序。舉個栗子 ,字串u8"a" < u8"一&quot;, 同時寬字元wchar_t(l'a') < wchar_t(l'一')。仔細想想還是蠻有意思的。

//使用c++實現像python一樣的字串遍歷

std::vector spliteachchar(const string chars)

else if ((input[i] & 0xe0) == 0xc0) else if ((input[i] & 0xf0) == 0xe0) else if ((input[i] & 0xf8) == 0xf0)

words.push_back(input.substr(i, next));

i += next;

}return words;

}

linux使用iconv在不同字元編碼中轉換

在linux系統下利用iconv命令進行gbk與utf 8字元編碼間的轉換 gbk編碼和utf 8編碼的區別 1.gbk的文字編碼是雙位元組來表示的,即不論中 英文本元均使用雙位元組來表示,只不過為區分中文,將其兩個位元組的最高位都定成1。utf 8編碼則是用以解決國際上字元的一種多位元組編碼,它對...

C 中判斷字元是否大寫

在c 中,通常判斷乙個字元是否為大寫字母,有些人可能會第一時間想到用正規表示式,那除了正規表示式,是否還有其他方式呢?答案是肯定的,先一睹為快,具體 如下 using system using system.collections.generic using system.linq using sy...

Python 中的字元編碼

1 str型別可以理解為乙個二進位制block,或multibyte 2 multibyte str.decode unicode 3 unicode str.encode multibyte str binary block 4 unicode str 的操作引數也應為unicode,如 unic...