mfc中socket字符接收不完整unicode问题
? ? ? ? ?最近在socket編程中遇到一個(gè)問(wèn)題:服務(wù)器端接收的字符不完整,設(shè)置斷點(diǎn)后發(fā)現(xiàn)接受的char數(shù)組中每隔一個(gè)字符有一個(gè)空,查閱相關(guān)資料后發(fā)現(xiàn)原因是字符編碼的問(wèn)題。vs2010默認(rèn)使用unicode編碼,即一個(gè)字符倆個(gè)字節(jié),而傳統(tǒng)ANSI編碼為一個(gè)字節(jié)代表一個(gè)字符,所以socket編程中,使用send函數(shù)時(shí)需要注意,str.gelength()是獲得字符總數(shù),而不是字節(jié)數(shù),所以發(fā)送時(shí)需要*2倍或者*sizeof(TCHAR)。unicode詳細(xì)介紹如下:
一:字符編碼
1. ASCII?
我們需要了解的最早編碼是ASCII碼。它用7個(gè)二進(jìn)制位來(lái)表示,由于那個(gè)時(shí)期生產(chǎn)的大多數(shù)計(jì)算機(jī)使用8位大小的字節(jié),因此用戶不僅可以存放所有可能的 ASCII字符,而且有整整一位空余下來(lái)。
由于字節(jié)有多達(dá)8位的空間,因此許多人在想:“呀!我們可以把128~255之間的編碼用做個(gè)人的應(yīng)用目的?!眴?wèn)題在于,同時(shí)產(chǎn)生這種想法的人相當(dāng) 多,而且在128~255之間的各個(gè)位置上應(yīng)該存放什么這一問(wèn)題上,真是仁者見(jiàn)仁智者見(jiàn)智。事實(shí)上,只要人們開(kāi)始在美國(guó)以外的地方購(gòu)買(mǎi)計(jì)算機(jī),那么各種各 樣的不同OEM字符集都會(huì)進(jìn)入規(guī)劃設(shè)計(jì)行列,并且各人都會(huì)根據(jù)自己的需要使用高位的128個(gè)字符。如此一來(lái),甚至在同語(yǔ)種的文檔之間就不容易實(shí)現(xiàn)互換。 ASCII可被擴(kuò)展,最優(yōu)秀的擴(kuò)展方案是ISO 8859-1,通常稱之為L(zhǎng)atin-1。Latin-1包括了足夠的附加字符集來(lái)寫(xiě)基本的西歐語(yǔ)言。
最后,這個(gè)人人參與的OEM終于以ANSI標(biāo)準(zhǔn)的形式形成文件。在ANSI標(biāo)準(zhǔn)中,每個(gè)人都認(rèn)同如何使用低端的128個(gè)編碼,這與ASCII相當(dāng)一致。不過(guò),根據(jù)所在國(guó)籍的不同,處理編碼128以上的字符有許多不同的方式。這些不同的系統(tǒng)稱為代碼頁(yè)。
同時(shí),甚至更為令人頭疼的事情正在逐步上演,亞洲國(guó)家的字符表有成千上萬(wàn)個(gè)字符,這樣的字符表是用8位二進(jìn)制無(wú)法表示的。該問(wèn)題的解決通常有賴于稱為DBCS(double byte character set,雙字節(jié)字符集)的繁雜字符系統(tǒng)。
不過(guò),仍然需要指出一點(diǎn),多數(shù)人還是姑且認(rèn)為一個(gè)字節(jié)就是一個(gè)字符,以及一個(gè)字符就是8個(gè)二進(jìn)制位,并且只要確保不將字符串從一臺(tái)計(jì)算機(jī)移植到另一臺(tái) 計(jì)算機(jī),或者說(shuō)一種以上的語(yǔ)言,那么這幾乎總是可以湊合。當(dāng)然,只要一進(jìn)入Internet,從一臺(tái)計(jì)算機(jī)向另一臺(tái)計(jì)算機(jī)移植字符串就成為家常便飯了,而 各種復(fù)雜狀況也隨之呈現(xiàn)出來(lái)。令人欣慰的是,Unicode隨即問(wèn)世了。
2.iso8859-1
屬于單字節(jié)編碼,最多能表示的字符范圍是0-255,應(yīng)用于英文系列。比如,字母'a'的編碼為0x61=97。
很明顯,iso8859-1編碼表示的字符范圍很窄,無(wú)法表示中文字符。但是,由于是單字節(jié)編碼,和計(jì)算機(jī)最基礎(chǔ)的表示單位一致,所以很多時(shí)候,仍 舊使用iso8859-1編碼來(lái)表示。而且在很多協(xié)議上,默認(rèn)使用該編碼。比如,雖然"中文"兩個(gè)字不存在iso8859-1編碼,以gb2312編碼為 例,應(yīng)該是"d6d0 cec4"兩個(gè)字符,使用iso8859-1編碼的時(shí)候則將它拆開(kāi)為4個(gè)字節(jié)來(lái)表示:"d6 d0 ce c4"(事實(shí)上,在進(jìn)行存儲(chǔ)的時(shí)候,也是以字節(jié)為單位處理的)。而如果是UTF編碼,則是6個(gè)字節(jié)"e4 b8 ad e6 96 87"。很明顯,這種表示方法還需要以另一種編碼為基礎(chǔ)。
3. GB碼
全稱是GB2312-80《信息交換用漢字編碼字符集基本集》,1980年發(fā)布,是中文信息處理的國(guó)家標(biāo)準(zhǔn),在大陸及海外使用簡(jiǎn)體中文的地區(qū)(如新 加坡等)是強(qiáng)制使用的唯一中文編碼。P-Windows3.2和蘋(píng)果OS就是以GB2312為基本漢字編碼, Windows 95/98則以GBK為基本漢字編碼、但兼容支持GB2312。?
雙字節(jié)編碼
范圍:A1A1~FEFE
A1-A9:符號(hào)區(qū),包含682個(gè)符號(hào)
B0-F7:漢字區(qū),包含6763個(gè)漢字
4.GB2312
GB2312(1980年)一共收錄了7445個(gè)字符,包括6763個(gè)漢字和682個(gè)其它符號(hào)。漢字區(qū)的內(nèi)碼范圍高字節(jié)從B0-F7,低字節(jié)從 A1-FE,占用的碼位是72*94=6768。其中有5個(gè)空位是D7FA-D7FE。GB2312-80中共收錄了7545個(gè)字符,用兩個(gè)字節(jié)編碼一個(gè) 字符。每個(gè)字符最高位為0。GB2312-80編碼簡(jiǎn)稱國(guó)標(biāo)碼。
GB2312支持的漢字太少。1995年的漢字?jǐn)U展規(guī)范GBK1.0收錄了21886個(gè)符號(hào),它分為漢字區(qū)和圖形符號(hào)區(qū)。漢字區(qū)包括21003個(gè)字符。
5. GB12345-90
1990年制定了繁體字的編碼標(biāo)準(zhǔn)GB12345-90《信息交換用漢字編碼字符集第一輔助集》,目的在于規(guī)范必須使用繁體字的各種場(chǎng)合,以及古籍 整理等。該標(biāo)準(zhǔn)共收錄6866個(gè)漢字(比GB2312多103個(gè)字,其它廠商的字庫(kù)大多不包括這些字),純繁體的字大概有2200余個(gè)。?
雙字節(jié)編碼
范圍:A1A1~FEFE
A1-A9:符號(hào)區(qū),增加豎排符號(hào)
B0-F9:漢字區(qū),包含6866個(gè)漢字
6.GBK
GBK編碼(Chinese Internal Code Specification)是中國(guó)大陸制訂的、等同于UCS的新的中文編碼擴(kuò)展國(guó)家標(biāo)準(zhǔn)。gbk編碼能夠用來(lái)同時(shí)表示繁體字和簡(jiǎn)體字,而gb2312只 能表示簡(jiǎn)體字,gbk是兼容gb2312編碼的。GBK工作小組于1995年10月,同年12月完成GBK規(guī)范。該編碼標(biāo)準(zhǔn)兼容GB2312,共收錄漢字 21003個(gè)、符號(hào)883個(gè),并提供1894個(gè)造字碼位,簡(jiǎn)、繁體字融于一庫(kù)。Windows95/98簡(jiǎn)體中文版的字庫(kù)表層編碼就采用的是GBK,通過(guò) GBK與UCS之間一一對(duì)應(yīng)的碼表與底層字庫(kù)聯(lián)系。
英文名:Chinese Internal Code Specification
中文名:漢字內(nèi)碼擴(kuò)展規(guī)范1.0版
雙字節(jié)編碼,GB2312-80的擴(kuò)充,在碼位上和GB2312-80兼容
范圍:8140~FEFE(剔除xx7F)共23940個(gè)碼位
包含21003個(gè)漢字,包含了ISO/IEC 10646-1中的全部中日韓漢字
7. BIG5編碼
是目前臺(tái)灣、香港地區(qū)普遍使用的一種繁體漢字的編碼標(biāo)準(zhǔn),包括440個(gè)符號(hào),一級(jí)漢字5401個(gè)、二級(jí)漢字7652個(gè),共計(jì)13060個(gè)漢字。 BIG5又稱大五碼或五大碼,1984年由臺(tái)灣財(cái)團(tuán)法人信息工業(yè)策進(jìn)會(huì)和五間軟件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大眾 (FIC)創(chuàng)立,故稱大五碼。Big5碼的產(chǎn)生,是因?yàn)楫?dāng)時(shí)臺(tái)灣不同廠商各自推出不同的編碼,如倚天碼、IBM PS55、王安碼等,彼此不能兼容;另一方面,臺(tái)灣政府當(dāng)時(shí)尚未推出官方的漢字編碼,而中國(guó)大陸的GB2312編碼亦未有收錄繁體中文字。
Big5字符集共收錄13,053個(gè)中文字,該字符集在中國(guó)臺(tái)灣使用。耐人尋味的是該字符集重復(fù)地收錄了兩個(gè)相同的字:“?!?0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。
Big5碼使用了雙字節(jié)儲(chǔ)存方法,以兩個(gè)字節(jié)來(lái)編碼一個(gè)字。第一個(gè)字節(jié)稱為“高位字節(jié)”,第二個(gè)字節(jié)稱為“低位字節(jié)”。高位字節(jié)的編碼范圍0xA1-0xF9,低位字節(jié)的編碼范圍0x40-0x7E及0xA1-0xFE。
盡管Big5碼內(nèi)包含一萬(wàn)多個(gè)字符,但是沒(méi)有考慮社會(huì)上流通的人名、地名用字、方言用字、化學(xué)及生物科等用字,沒(méi)有包含日文平假名及片假字母。
例如臺(tái)灣視“著”為“著”的異體字,故沒(méi)有收錄“著”字??滴踝值渲械囊恍┎渴子米?如“亠”、“疒”、“辵”、“癶”等)、常見(jiàn)的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也沒(méi)有收錄到Big5之中。
8.UTF-8
UTF:UCS Transformation Format.考慮到unicode編碼不兼容iso8859-1編碼,而且容易占用更多的空間:因?yàn)閷?duì)于英文字母,unicode也需要兩個(gè)字節(jié)來(lái)表 示。所以u(píng)nicode不便于傳輸和存儲(chǔ)。因此而產(chǎn)生了utf編碼,utf編碼兼容iso8859-1編碼,同時(shí)也可以用來(lái)表示所有語(yǔ)言的字符,不 過(guò),utf編碼是不定長(zhǎng)編碼,每一個(gè)字符的長(zhǎng)度從1-6個(gè)字節(jié)不等。另外,utf編碼自帶簡(jiǎn)單的校驗(yàn)功能。一般來(lái)講,英文字母都是用一個(gè)字節(jié)表示,而漢字 使用三個(gè)字節(jié)。
注意,雖然說(shuō)utf是為了使用更少的空間而使用的,但那只是相對(duì)于unicode編碼來(lái)說(shuō),如果已經(jīng)知道是漢字,則使用GB2312/GBK無(wú)疑是 最節(jié)省的。不過(guò)另一方面,值得說(shuō)明的是,雖然utf編碼對(duì)漢字使用3個(gè)字節(jié),但即使對(duì)于漢字網(wǎng)頁(yè),utf編碼也會(huì)比unicode編碼節(jié)省,因?yàn)榫W(wǎng)頁(yè)中包 含了很多的英文字符。
UTF8編碼后的大小是不一定,例如一個(gè)英文字母"a" 和 一個(gè)漢字 "好",編碼后占用的空間大小就不樣了,前者是一個(gè)字節(jié),后者是三個(gè)字節(jié)!編碼的方法是從低位到高位。黃色為標(biāo)志位其它著色為了顯示其,編碼后的位置。
9.Unicode
Unicode字符集(簡(jiǎn)稱為UCS),國(guó)際標(biāo)準(zhǔn)組織于1984年4月成立ISO/IEC JTC1/SC2/WG2工作組,針對(duì)各國(guó)文字、符號(hào)進(jìn)行統(tǒng)一性編碼。1991年美國(guó)跨國(guó)公司成立Unicode Consortium,并于1991年10月與WG2達(dá)成協(xié)議,采用同一編碼字集。目前Unicode是采用16位編碼體系,其字符集內(nèi)容與 ISO10646的BMP(Basic Multilingual Plane)相同。Unicode于1992年6月通過(guò)DIS(Draf International Standard),目前版本V2.0于1996公布,內(nèi)容包含符號(hào)6811個(gè),漢字20902個(gè),韓文拼音11172個(gè),造字區(qū)6400個(gè),保留 20249個(gè),共計(jì)65534個(gè)。Unicode編碼后的大小是一樣的.例如一個(gè)英文字母 "a" 和 一個(gè)漢字 "好",編碼后都是占用的空間大小是一樣的,都是兩個(gè)字節(jié)!
Unicode可以用來(lái)表示所有語(yǔ)言的字符,而且是定長(zhǎng)雙字節(jié)(也有四字節(jié)的)編碼,包括英文字母在內(nèi)。所以可以說(shuō)它是不兼容iso8859-1編 碼的,也不兼容任何編碼。不過(guò),相對(duì)于iso8859-1編碼來(lái)說(shuō),uniocode編碼只是在前面增加了一個(gè)0字節(jié),比如字母'a'為"00 61"。
需要說(shuō)明的是,定長(zhǎng)編碼便于計(jì)算機(jī)處理(注意GB2312/GBK不是定長(zhǎng)編碼),而unicode又可以用來(lái)表示所有字符,所以在很多軟件內(nèi)部是使用unicode編碼來(lái)處理的,比如java。
二:選擇Unicode的優(yōu)勢(shì)
VS 2003開(kāi)始VC方面的項(xiàng)目都是默認(rèn)使用unicode字符集,使用Unicode編碼可以使您的工程同時(shí)支持多種語(yǔ)言,使您的工程國(guó)際化。另外,Windows NT是使用Unicode進(jìn)行開(kāi)發(fā)的,整個(gè)系統(tǒng)都是基于Unicode的。如果調(diào)用一個(gè)API函數(shù)并給它傳遞一個(gè)ANSI(ASCII字符集以及由此派生并兼容的字符集,如:GB2312,通常稱為ANSI字符集)字符串,那么系統(tǒng)首先要將字符串轉(zhuǎn)換成Unicode,然后將Unicode字符串傳遞給操作系統(tǒng)。如果希望函數(shù)返回ANSI字符串,系統(tǒng)就會(huì)首先將Unicode字符串轉(zhuǎn)換成ANSI字符串,然后將結(jié)果返回給您的應(yīng)用程序。進(jìn)行這些字符串的轉(zhuǎn)換需要占用系統(tǒng)的時(shí)間和內(nèi)存。如果用Unicode來(lái)開(kāi)發(fā)應(yīng)用程序,就能夠使您的應(yīng)用程序更加有效地運(yùn)行。
另外,Windows NT是使用Unicode進(jìn)行開(kāi)發(fā)的,整個(gè)系統(tǒng)都是基于Unicode的。如果調(diào)用一個(gè)API函數(shù)并給它傳遞一個(gè)ANSI(ASCII字符集以及由此派生并兼容的字符集,如:GB2312,通常稱為ANSI字符集)字符串,那么系統(tǒng)首先要將字符串轉(zhuǎn)換成Unicode,然后將Unicode字符串傳遞給操作系統(tǒng)。如果希望函數(shù)返回ANSI字符串,系統(tǒng)就會(huì)首先將Unicode字符串轉(zhuǎn)換成ANSI字符串,然后將結(jié)果返回給您的應(yīng)用程序。進(jìn)行這些字符串的轉(zhuǎn)換需要占用系統(tǒng)的時(shí)間和內(nèi)存。如果用Unicode來(lái)開(kāi)發(fā)應(yīng)用程序,就能夠使您的應(yīng)用程序更加有效地運(yùn)行。
在ANSI中,一個(gè)字符(char)的長(zhǎng)度為一個(gè)字節(jié)(Byte)。使用Unicode時(shí),一個(gè)字符占據(jù)一個(gè)字,
三、使用C++進(jìn)行Unicode編程
對(duì)寬字符的支持其實(shí)是ANSI C標(biāo)準(zhǔn)的一部分,用以支持多字節(jié)表示一個(gè)字符。寬字符和Unicode并不完全等同,Unicode只是寬字符的一種編碼方式。
1、寬字符的定義
在ANSI中,一個(gè)字符(char)的長(zhǎng)度為一個(gè)字節(jié)(Byte)。使用Unicode時(shí),一個(gè)字符占據(jù)一個(gè)字,C++在wchar.h頭文件中定義了最基本的寬字符類型wchar_t:
typedef unsigned short wchar_t;從這里我們可以清楚地看到,所謂的寬字符就是無(wú)符號(hào)短整數(shù)。
2、常量寬字符串
對(duì)C++程序員而言,構(gòu)造字符串常量是一項(xiàng)經(jīng)常性的工作。那么,如何構(gòu)造寬字符字符串常量呢?很簡(jiǎn)單,只要在字符串常量前加上一個(gè)大寫(xiě)的L就可以了,比如:
wchar_t *str1=L" Hello";這個(gè)L非常重要,只有帶上它,編譯器才知道你要將字符串存成一個(gè)字符一個(gè)字。還要注意,在L和字符串之間不能有空格。
3、寬字符串庫(kù)函數(shù)
為了操作寬字符串,C++專門(mén)定義了一套函數(shù),比如求寬字符串長(zhǎng)度的函數(shù)是
size_t __cdel wchlen(const wchar_t*); 為什么要專門(mén)定義這些函數(shù)呢?最根本的原因是,ANSI下的字符串都是以’\0’來(lái)標(biāo)識(shí)字符串尾的(Unicode字符串以“\0\0”結(jié)束),許多字符串函數(shù)的正確操作均是以此為基礎(chǔ)進(jìn)行。而我們知道,在寬字符的情況下,一個(gè)字符在內(nèi)存中要占據(jù)一個(gè)字的空間,這就會(huì)使操作ANSI字符的字符串函數(shù)無(wú)法正確操作。以”Hello”字符串為例,在寬字符下,它的五個(gè)字符是:
0x0048 0x0065 0x006c 0x006c 0x006f
在內(nèi)存中,實(shí)際的排列是:
于是,ANSI字符串函數(shù),如strlen,在碰到第一個(gè)48后的00時(shí),就會(huì)認(rèn)為字符串到尾了,用strlen對(duì)寬字符串求長(zhǎng)度的結(jié)果就永遠(yuǎn)會(huì)是1!
4. Windows定義的Unicode數(shù)據(jù)類型有哪些?
數(shù)據(jù)類型 說(shuō)明
WCHAR Unicode字符
PWSTR 指向Unicode字符串的指針
PCWSTR 指向一個(gè)恒定的Unicode字符串的指針
對(duì)應(yīng)的ANSI數(shù)據(jù)類型為CHAR,LPSTR和LPCSTR。
ANSI/Unicode通用數(shù)據(jù)類型為T(mén)CHAR,PTSTR,LPCTSTR。
5. 如何對(duì)Unicode進(jìn)行操作?
字符集 特性 實(shí)例
ANSI 操作函數(shù)以str開(kāi)頭 strcpy
Unicode 操作函數(shù)以wcs開(kāi)頭 wcscpy
MBCS 操作函數(shù)以_mbs開(kāi)頭 _mbscpy
ANSI/Unicode 操作函數(shù)以_tcs開(kāi)頭 _tcscpy(C運(yùn)行期庫(kù))
ANSI/Unicode 操作函數(shù)以lstr開(kāi)頭 lstrcpy(Windows函數(shù))
如何表示Unicode字符串常量?
字符集 實(shí)例
ANSI “string”
Unicode L“string”
ANSI/Unicode T(“string”)或_TEXT(“string”)if( szError[0] == _TEXT(‘J’) ){ }
6. 如何編寫(xiě)符合ANSI和Unicode的應(yīng)用程序?
(1)將文本串視為字符數(shù)組,而不是chars數(shù)組或字節(jié)數(shù)組。
(2)將通用數(shù)據(jù)類型(如TCHAR和PTSTR)用于文本字符和字符串。
(3)將顯式數(shù)據(jù)類型(如BYTE和PBYTE)用于字節(jié)、字節(jié)指針和數(shù)據(jù)緩存。
(4) 將TEXT宏用于原義字符和字符串。
(5)執(zhí)行全局性替換(例如用PTSTR替換PSTR)。
(6)修改字符串運(yùn)算問(wèn)題。例如函數(shù)通常希望在字符中傳遞一個(gè)緩存的大小,而不是字節(jié)。這意味著不應(yīng)該傳遞sizeof(szBuffer),而應(yīng)該傳遞(sizeof(szBuffer)/sizeof(TCHAR)。另外,如果需要為字符串分配一個(gè)內(nèi)存塊,并且擁有該字符串中的字符數(shù)目,那幺請(qǐng)記住要按字節(jié)來(lái)分配內(nèi)存。這就是說(shuō),應(yīng)該調(diào)用
malloc(nCharacters *sizeof(TCHAR)),而不是調(diào)用malloc(nCharacters)。
7、用宏實(shí)現(xiàn)對(duì)ANSI和Unicode通用的編程
可見(jiàn),C++有一整套的數(shù)據(jù)類型和函數(shù)實(shí)現(xiàn)Unicode編程,也就是說(shuō),您完全可以使用C++實(shí)現(xiàn)Unicode編程。
如果我們想要我們的程序有兩個(gè)版本:ANSI版本和Unicode版本。當(dāng)然,編寫(xiě)兩套代碼分別實(shí)現(xiàn)ANSI版本和Unicode版本完全是行得通的。但是,針對(duì)ANSI字符和Unicode字符維護(hù)兩套代碼是非常麻煩的事情。為了減輕編程的負(fù)擔(dān),C++定義了一系列的宏,幫助您實(shí)現(xiàn)對(duì)ANSI和Unicode的通用編程。
C++宏實(shí)現(xiàn)ANSI和Unicode的通用編程的本質(zhì)是根據(jù)”_UNICODE”(注意,有下劃線)定義與否,這些宏展開(kāi)為ANSI或Unicode字符(字符串)。
如下是tchar.h頭文件中部分代碼摘抄:
#ifdef _UNICODE typedef wchar_t TCHAR; #define __T(x) L##x #define _T(x) __T(x) #else #define __T(x) x typedef char TCHAR; #endif 可見(jiàn),這些宏根據(jù)”_UNICODE” 定義與否,分別展開(kāi)為ANSI或Unicode字符。 tchar.h頭文件中定義的宏可以分為兩類:A、實(shí)現(xiàn)字符和常量字符串定義的宏我們只列出兩個(gè)最常用的宏:
| 宏 | 未定義_UNICODE(ANSI字符) | 定義了_UNICODE(Unicode字符) |
| TCHAR | char | wchar_t |
| _T(x) | x | L##x |
注意:
“##”是ANSI C標(biāo)準(zhǔn)的預(yù)處理語(yǔ)法,它叫做“粘貼符號(hào)”,表示將前面的L添加到宏參數(shù)上。也就是說(shuō),如果我們寫(xiě)_T(“Hello”),展開(kāi)后即為L(zhǎng)“Hello”
B、實(shí)現(xiàn)字符串函數(shù)調(diào)用的宏
C++為字符串函數(shù)也定義了一系列宏,同樣,我們只例舉幾個(gè)常用的宏:
| 宏 | 未定義_UNICODE(ANSI字符) | 定義了_UNICODE(Unicode字符) |
| _tcschr | strchr | wcschr |
| _tcscmp | strcmp | wcscmp |
| _tcslen | strlen | wcslen |
四、使用Win32 API進(jìn)行Unicode編程
Win32 API中定義了一些自己的字符數(shù)據(jù)類型。這些數(shù)據(jù)類型的定義在winnt.h頭文件中。例如:
typedef char CHAR; typedef unsigned short WCHAR; // wc, 16-bit UNICODE character typedef CONST CHAR *LPCSTR, *PCSTR; Win32 API在winnt.h頭文件中定義了一些實(shí)現(xiàn)字符和常量字符串的宏進(jìn)行ANSI/Unicode通用編程。同樣,只例舉幾個(gè)最常用的: #ifdef UNICODE typedef WCHAR TCHAR, *PTCHAR; typedef LPWSTR LPTCH, PTCH; typedef LPWSTR PTSTR, LPTSTR; typedef LPCWSTR LPCTSTR; #define __TEXT(quote) L##quote // r_winnt #else /* UNICODE */ // r_winnt typedef char TCHAR, *PTCHAR; typedef LPSTR LPTCH, PTCH; typedef LPSTR PTSTR, LPTSTR; typedef LPCSTR LPCTSTR; #define __TEXT(quote) quote // r_winnt #endif /* UNICODE */ // r_winnt 從以上頭文件可以看出,winnt.h根據(jù)是否定義了UNICODE(沒(méi)有下劃線),進(jìn)行條件編譯。Win32 API也定義了一套字符串函數(shù),它們根據(jù)是否定義了“UNICODE”分別展開(kāi)為ANSI和Unicode字符串函數(shù)。如:lstrlen。API的字符串操作函數(shù)和C++的操作函數(shù)可以實(shí)現(xiàn)相同的功能,所以,如果需要的話,建議您盡可能使用C++的字符串函數(shù),沒(méi)必要去花太多精力再去學(xué)習(xí)API的這些東西。
也許您從來(lái)沒(méi)有注意到,Win32 API實(shí)際上有兩個(gè)版本。一個(gè)版本接受MBCS字符串,另一個(gè)接受Unicode字符串。例如:其實(shí)根本沒(méi)有SetWindowText()這個(gè)API函數(shù),相反,有SetWindowTextA()和SetWindowTextW()。后綴A表明這是MBCS函數(shù),后綴W表示這是Unicode版本的函數(shù)。這些API函數(shù)的頭文件在winuser.h中聲明,下面例舉winuser.h中的SetWindowText()函數(shù)的聲明部分: #ifdef UNICODE #define SetWindowText SetWindowTextW #else #define SetWindowText SetWindowTextA #endif // !UNICODE 可見(jiàn),API函數(shù)根據(jù)定義UNICODE與否決定指向Unicode版本還是MBCS版本。
總結(jié)
以上是生活随笔為你收集整理的mfc中socket字符接收不完整unicode问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 权限设计,设计模型分析(DAC,MAC,
- 下一篇: 驯龙高手java版_石器时代2驯龙高手