日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++汉字字符处理

發布時間:2023/12/20 c/c++ 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++汉字字符处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題:實現Apriori算法時的數據集為中文,所以需要用到漢字字符處理。現搜集整合如下。

#include <stdio.h> void main(void){char str[100];printf("輸入漢字:\n");scanf("%s",str);printf("%c%c %c%c\n", str[0],str[1],str[2],str[3]); printf("%s\n",str); }

測試結果:


  • 轉載1 關于C中文字符的處理
    • 一 引入問題
    • 二 解決引入問題所需的知識
    • 三 漢字的編碼方式及在vcc中的處理
      • 漢字編碼方式的介紹
      • vc中漢字的編碼方式
      • 新的內碼標準Unicode
      • 內碼的相互轉換
    • 四 vc中的MutiByte Charater Set 和 Wide Character Set
      • MultiByte Charater Set方式
      • Wide Character Set
    • 五 引入問題的錯誤分析
  • 轉載2 C讀寫漢字C處理中文字符
  • 擴展1 unicode-ansi-utf-8-unicode-big-endian編碼的區別
  • 擴展2 各種字符集編碼
  • 擴展3 Unicode 和 UTF-8 有何區別知乎


轉載1 關于C++中文字符的處理

一 引入問題

代碼 wchar_t a3=L”中國”,編譯時出錯,出錯信息為:數組越界。但wchar_t 是一個寬字節類型,數組a的大小應為6個字節,而兩個漢字的的unicode碼占4個字節,再加上一個結束符,最多6個字節,所以應該不會越界。難道是編譯器出問題了?

二 解決引入問題所需的知識

? ? ? ?主要需兩方面的知識
1. 字符尤其是漢字的編碼,以及語言和工具的支持情況
2. vc/c++中MutiByte Charater Set 和 Wide Character Set有關內存分配的情況.

三 漢字的編碼方式及在vc/c++中的處理

1.漢字編碼方式的介紹

? ? ? ?對英文字符的處理,7位ASCII碼字符集中的字符即可滿足使用需求,且英文字符在計算機上的輸入及輸出也非常簡單,因此,英文字符的輸入、存儲、內部處理和輸出都可以只用同一個編碼(如ASCII碼)。
? ? ? ?而漢字是一種象形文字,字數極多(現代漢字中僅常用字就有六、七千個,總字數高達5萬個以上),且字形復雜,每一個漢字都有”音、形、義”三要素,同音字、異體字也很多,這些都給漢字的的計算機處理帶來了很大的困難。要在計算機中處理漢字,必須解決以下幾個問題:首先是漢字的輸入,即如何把結構復雜的方塊漢字輸入到計算機中去,這是漢字處理的關鍵;其次,漢字在計算機內如何表示和存儲?如何與西文兼容?最后,如何將漢字的處理結果從計算機內輸出?
? ? ? ?為此,必須將漢字代碼化,即對漢字進行編碼。對應于上述漢字處理過程中的輸入、內部處理及輸出這三個主要環節,流程如下:

Created with Rapha?l 2.1.0輸入輸入碼交換碼內部碼字形碼輸出

(1) 輸入碼
? ? ? ?作用是,利用它和現有的標準西文鍵盤結合來輸入漢字。輸入碼也稱為外碼。主要歸為四類:

  • 數字編碼
    數字編碼是用等長的數字串為漢字逐一編號,以這個編號作為漢字的輸入碼。例如,區位碼、電報碼等都屬于數字編碼。

  • 拼音碼
    拼音碼是以漢字的讀音為基礎的輸入辦法。

  • 字形碼
    字形碼是以漢字的字形結構為基礎的輸入編碼。例如,五筆字型碼(王碼)。

  • 音形碼
    音形碼是兼顧漢字的讀音和字形的輸入編碼。

(2) 交換碼
? ? ? ?用于漢字外碼和內部碼的交換。交換碼的國家標準代號為GB2312-8090。

(3) 內部碼
? ? ? ?內部碼是漢字在計算機內的基本表示形式,是計算機對漢字進行識別、存儲、處理和傳輸所用的編碼。內部碼也是雙字節編碼,將國標碼兩個字節的最高位都置為”1”,即轉換成漢字的內部碼。

(4) 字形碼
? ? ? ?字形碼是表示漢字字形信息(漢字的結構、形狀、筆劃等)的編碼,用來實現計算機對漢字的輸出(顯示、打印)。

2.vc中漢字的編碼方式

? ? ? ?vc/c++正是采用了GB2312內部碼作為漢字的編碼方式,因此vc/c++中的各種輸入輸出方法,如cin/wcin,cout/wcout,scanf/wsanf,printf/wprintf…都是基于GB2312的,如果漢字的內碼不是這種編碼方式,那么利用上述各種方法就不會正確的解析漢字。

ASCII值控制字符ASCII值控制字符ASCII值控制字符ASCII值控制字符
0NUT32(space)64@96
1SOH33!65A97a
2STX3466B98b
3ETX35#67C99c
4EOT36$68D100d
5ENQ37%69E101e
6ACK38&70F102f
7BEL39,71G103g
8BS40(72H104
9HT41)73I105
10LF42*74J106j
11VT43+75K107k
12FF44,76L108l
13CR45-77M109m
14SO46.78N110n
15SI47/79O111o
16DLE48080P112p
17DCI49181Q113q
18DC250282R114r
19DC351383S115s
20DC452484T116t
21NAK53585U117u
22SYN54686V118v
23TB55787W119w
24CAN56888X120x
25EM57989Y121y
26SUB58:90Z122z
27ESC59;91[123{
28FS60<92/124
29GS61=93]125}
30RS62>94^126`
31US63?95_127DEL
? ? ? ?? ? ?NUL空? ? ? ?? ? ?VT 垂直制表? ? ? ?? SYN 空轉同步
STX 正文開始CR 回車CAN 作廢
ETX 正文結束SO 移位輸出EM 紙盡
EOY 傳輸結束SI 移位輸入SUB 換置
ENQ 詢問字符DLE 空格ESC 換碼
ACK 承認DC1 設備控制1FS 文字分隔符
BEL 報警DC2 設備控制2GS 組分隔符
BS 退一格DC3 設備控制3RS 記錄分隔符
HT 橫向列表DC4 設備控制4US 單元分隔符
LF 換行NAK 否定DEL 刪除

? ? ? ?仔細觀察ASCII字符表,從第161個字符開始,后面的字符并不經常為用戶所使用,負值也未使用。GB2312編碼方式充分利用這一特性,將161-255(-95~-1)之間的數值空間作為漢字的標識碼。既然255-161 = 94不能滿足漢字容量的要求,就將每兩個字符并在一塊(即一個漢字占兩個字節),顯然,94* 94 =8836基本上已經滿足了常用漢字個數的要求。計算機處理字符時,當連續處理到兩個大與160(或-95~-1)的字節時,就認為這兩個字節存放了一個漢字字符。可以用下面的Demo程序來模擬vc/c++中輸出漢字字符的過程。

unsigned char input[50]; cin>>input;int flag=0;for(int i =0 ;i < 50 ;i++){if(input[i] > 0xa0 && input[i] != 0){if(flag == 1){cout<<"chinese character"<flag = 0;}else{flag++;//一字節,前四位識別,后四位確定并輸出,見上一段if程序}}else if(input[i] == 0){break;}else{cout<<"english character"<flag=0;} }

輸入:Hello中國 (“中國”對應的GB2312內碼為:214 208,185 250)
輸出:english character
english character
english character
english character
english character
chinese character
chinese character

? ? ? ?vc/c++中的英文字符仍然采用ASCII編碼方式。可以設想,其他國家程序員利用vc/c++編寫程序輸入本國字符時,vc/c++則會采用該國的字符編碼方式來處理這些字符。
? ? ? ? 問題又產生了,韓國的vc/c++程序在中國的vc/c++上運行時,如果沒有相應的內碼庫,則對韓語字符的顯示有可能出現亂碼。我個人猜測,vc安裝程序中應該帶有不同國家的內碼庫,這樣一來肯定會占用很大的空間。如果所有的國家使用統一的編碼方式,且所有的程序設計語言和開發工具都支持這種編碼方式該多好!而現實中,確實已經有這種編碼方式了,且許多新的語言也都支持這種編碼方式,如Java、C#等,它就是下面的Unicode編碼

3.新的內碼標準—Unicode

? ? ? ?Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。它為每種語言中的每個字符設定了統一并且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。
? ? ? ?在Unicode 5.0.0版本中,已定義的碼位只有238605個,分布在平面0、平面1、平面2、平面14、平面15、平面16。其中平面15和平面16上只是定義了兩個各占65534個碼位的專用區(Private Use Area),分別是0xF0000-0xFFFFD和0x100000-0x10FFFD。所謂專用區,就是保留給大家放自定義字符的區域,可以簡寫為PUA。
? ? ? ?平面0也有一個專用區:0xE000-0xF8FF,有6400個碼位。平面0的0xD800-0xDFFF,共2048個碼位,是一個被稱作代理區(Surrogate)的特殊區域。代理區的目的用兩個UTF-16字符表示BMP以外的字符。在介紹UTF-16編碼時會介紹。
? ? ? ?如前所述在Unicode 5.0.0版本中,238605-65534*2-6400-2048=99089。余下的99089個已定義碼位分布在平面0、平面1、平面2和平面14上,它們對應著Unicode定義的99089個字符,其中包括71226個漢字。平面0、平面1、平面2和平面14上分別定義了52080、3419、43253和337個字符。平面2的43253個字符都是漢字。平面0上定義了27973個漢字。
? ? ? ?在Unicode中:漢字“字”對應的數字是23383(十進制),十六進制表示為5B57。在Unicode中,我們有很多方式將數字23383表示成程序中的數據,包括:UTF-8、UTF-16、UTF-32。UTF是“Unicode Transformation Format”的縮寫,可以翻譯成Unicode字符集轉換格式,即怎樣將Unicode定義的數字轉換成程序數據。
? ? ? ?例如,“漢字”對應的數字是0x6c49和0x5b57,而編碼的程序數據是:

char data_utf8[]={0xE6,0xB1,0x89,0xE5,0xAD,0x97};//UTF-8編碼 char16_t data_utf16[]={0x6C49,0x5B57}; //UTF-16編碼 char32_t data_utf32[]={0x00006C49,0x00005B57};//UTF-32編碼

? ? ? ?這里用char、char16_t、char32_t分別表示無符號8位整數,無符號16位整數和無符號32位整數。UTF-8、UTF-16、UTF-32分別以char、char16_t、char32_t作為編碼單位。(注: char16_t 和 char32_t 是 C++ 11 標準新增的關鍵字。如果你的編譯器不支持 C++ 11 標準,請改用 unsigned short 和 unsigned long。)“漢字”的UTF-8編碼需要6個字節。“漢字”的UTF-16編碼需要兩個char16_t,大小是4個字節。“漢字”的UTF-32編碼需要兩個char32_t,大小是8個字節。

? ? ? ?Unicode 編碼系統可分為編碼方式實現方式兩個層次。

  • 編碼方式(此文作于08年)
    ? ? ? ?Unicode 的編碼方式與 ISO 10646 的通用字符集(Universal Character Set,UCS)概念相對應,目前的用于實用的 Unicode 版本對應于 UCS-2,使用16位的編碼空間。也就是每個字符占用2個字節。這樣理論上一共最多可以表示 216 個字符。基本滿足各種語言的使用。實際上目前版本的 Unicode 尚未填充滿這16位編碼,保留了大量空間作為特殊使用或將來擴展。

  • 實現方式
    ? ? ? ?Unicode 的實現方式不同于編碼方式。
    ? ? ? ?目前的Unicode字符分為17組編排,0x0000 至 0x10FFFF,每組稱為平面(Plane),而每平面擁有65536個碼位,共1114112個。
    ? ? ? ?一個字符的 Unicode 編碼是確定的。但是在實際傳輸過程中,由于不同系統平臺的設計不一定一致,以及出于節省空間的目的,對 Unicode 編碼的實現方式有所不同。
    ? ? ? ?Unicode 的實現方式稱為Unicode轉換格式(Unicode Translation Format,簡稱為 UTF)。如,UTF-8 編碼,這是一種變長編碼,它將基本7位ASCII字符仍用7位編碼表示,占用一個字節(首位補0)。而遇到與其他 Unicode 字符混合的情況,將按一定算法轉換,每個字符使用1-3個字節編碼,并利用首位為0或1進行識別。
    ? ? ? ?Java與C#語言都是采用Unicode編碼方式,在這兩種語言中定義一個字符,在內存中存放的就是這個字符的兩字節Unicode碼。如下所示:
    ? ? ? ?char a=’我’; => 內存中存放的Unicode碼為:25105

4.內碼的相互轉換

(1) vc中的實現方法
? ? ? ?利用Windows系統提供的API:::MultiByteToWideChar和::WideCharToMultiByte
::MultiByteToWideChar:實現當前碼到Unicode碼的轉換;
::WideCharToMultiByte:實現Unicode碼到當前碼的轉換;

(2) Java中的實現方法
? ? ? ?String vcString=new String(javaString.getBytes(“UTF-8”),”gb2312”);
? ? ? ?java的編碼應該是UTF-8

(3) C#中的實現方法
? ? ? ???

四 vc中的MutiByte Charater Set 和 Wide Character Set

1.MultiByte Charater Set方式

? ? ? ?這種方式以按字節為單位存放字符,即如果一個字符碼為兩字節,則在內存中占兩字節,字符碼為一字節,就占一字節。例如,字符串“中國abc”的編碼為:中(0xd6、0xd0)、國(0xb9、0xfa)、a(0x61)、b(0x62)、c(0x63)、\0(0x00),就存為如下方式:

? ? ? ?對應的類型,方法有:char、scanf、printf、cin、cout …

2.Wide Character Set

? ? ? ?這種方式是以兩字節為單位存放字符,即如果一個字符碼為兩字節,則在內存中占四字節,字符碼為一字節,就占兩字節。例如,字符串“中國abc”就存為如下方式:

? ? ? ?對應的類型,方法有:wchar_t、wscanf、wprintf、wcin、wcout …
? ? ? ?造成上面存儲方式的根本原因在于,wchar_t類型其實是一個unsigned short 類型。如,存儲上面字符串的數組的定義為:wchar_t buffer[8] 等價于unsigned short buffer[8].而所有以字母w開頭的方法也都是以unsigned short類型,即兩字節為單位來處理字符,因此,存儲在wchar_t類型數組中的字符串無法用cout顯示,只能用wcout方法來顯示。
? ? ? ?由于Unicode碼也是采用兩個字節,因此Wide Character Set方式能夠很好的支持Unicode碼的存儲,但是在vc的環境下要將一個Unicode碼存入兩字節而不是四字節內存中,必須通過上面的API函數::MultiByteToWideChar。首先,將當前的編碼轉換為Unicode碼,然后,將每個字符的Unicode碼放入每一個wchar_t類型的變量中。以下是一個實例代碼:

char input[50]; cin>>input; int size; size=::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,NULL,0); if(size==0)return -1; wchar_t *widebuff=new wchar_t[size]; ::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,widebuff,size);

輸入:中國abc
Debug斷點調試:
size==6

? ? ? ?數組widebuff[0-size]占12字節,存放了6個字符的Unicode碼,碼值為:
? ? ? ?中(0x4e2d) 國(0x56fd) a(0x0061) b(0x0062) c(0x0063) d(0x0000)
? ? ? ?這時,數組的大小size等于輸入的字符個數加上一個結束符,符合我們的想象。

五 引入問題的錯誤分析

  • 沒有理解編譯器中的編碼方式
    ? ? ? ?雖然vc/c++中漢字的編碼占兩個字節,但并不是Unicode碼,是GB2312碼。

  • 沒有理解MutiByte Charater Set 和 Wide Character Set的存儲原則;
    ? ? ? ?在vc/c++中,“中國”按char5來對待,而wchar_t a3實際上是三個unsigned short類型的變量,因此賦值時會越界。

  • 轉載2 C++讀寫漢字,C++處理中文字符

    擴展1 unicode-ansi-utf-8-unicode-big-endian編碼的區別

    ????2010年上傳的文章,但是真的深入淺出,推薦。

    擴展2 各種字符集編碼

    擴展3 Unicode 和 UTF-8 有何區別?(知乎)

    總結

    以上是生活随笔為你收集整理的c++汉字字符处理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。