學(xué)習(xí)Windows編程的時(shí)候,遇到字符串處理會(huì)讓人非常抓狂,當(dāng)然問(wèn)題的根本還是自己學(xué)藝不精,不過(guò)還是得吐槽一下,造成這一局面的原因是規(guī)則變化多端而又有點(diǎn)不可捉摸,這不,最近就掉到坑里面去了。
先看看下面的這段代碼:
int main(int argn,char* argv[]){ char strA[]="ABC 簡(jiǎn)體中文"; wchar_t strW[]=L"ABC 簡(jiǎn)體中文"; PRintf("%s/n",strA); wprintf(L"%s/n",strW); return 0;}猜猜看,輸出是什么?在我的電腦上(程序使用VS2010編譯通過(guò),Windows 7操作系統(tǒng),簡(jiǎn)體中文版)運(yùn)行的結(jié)果是這樣的:
第一個(gè)還好好地,怎么第二個(gè)會(huì)出現(xiàn)三個(gè)問(wèn)號(hào)?
調(diào)試一下試試看,在return 0前面下斷點(diǎn),然后查看內(nèi)存:
這個(gè)是strA在內(nèi)存中的值:41 42 43 20 bc f2 cc e5 d6 d0 ce c4 00
而strW則是:41 00 42 00 43 00 20 00 80 7b 53 4f 2d 4e 87 65 00 00
首先,我們知道char類(lèi)型占一個(gè)字節(jié),而wchar_t則是占兩個(gè)字節(jié),前面的41,42,43,20就是分別’A’,’B’,’C’和’ ‘(空格),這里表明,寬字符采用的是Little-Endian方式存放兩個(gè)字節(jié)的,接下來(lái)我們把重點(diǎn)都放在漢字上面。
在strA中,表示漢字“簡(jiǎn)體中文”數(shù)據(jù)為bc f2 cc e5 d6 d0 ce c4,而在strW則是80 7b 53 4f 2d 4e 87 65,差別很大,為什么是這樣呢?
這其中涉及到了編碼的問(wèn)題。char類(lèi)型中出現(xiàn)的漢字,采用的是GB2312的編碼規(guī)則,查詢(xún)?cè)摼幋a表,可以發(fā)現(xiàn),“簡(jiǎn)”字的編碼為BCF2,“體”為CCE5,“中”為D6D0,而“文”則為CEC4,這就是strA中中文的表示方式,但是在寬字符strW中,采用的編碼則是Unicode編碼,在Windows平臺(tái)下Unicode編碼值就是UTF-16編碼值。查詢(xún)“簡(jiǎn)體中文”四個(gè)漢字的編碼,可以發(fā)現(xiàn)是7B80 4F53 4E2D 6587,由于計(jì)算機(jī)的架構(gòu)為L(zhǎng)ittle-Endian,需要把高低位字節(jié)互換,這也就是寬字符的表示形式。
根據(jù)網(wǎng)頁(yè)上的說(shuō)明(參考這里)C/C++標(biāo)準(zhǔn)只是聲明wchar_t是一個(gè)可以表示字符集中的任意一個(gè)字符的足夠?qū)挼淖兞款?lèi)型。wchar_t可以用任何encoding編碼方式來(lái)存儲(chǔ)這個(gè)字符,如ANSI、UCS-2或者UCS-4, 甚至是SCU-128,只不過(guò)我們通常是用unicode編碼方式。wchar_t是與實(shí)現(xiàn)相關(guān)的。所以為了可移植性,我們不能假定wchar_t的編碼方式,然后根據(jù)編碼方式做一些相關(guān)性操作,我們只能理解它為一個(gè)足夠?qū)挼淖址?lèi)型。
最后,我們還能順便發(fā)現(xiàn),wprintf函數(shù)在處理文本輸出的時(shí)候,并不處理編碼問(wèn)題,而是直接按多字節(jié)字符順序輸出。
好,現(xiàn)在問(wèn)題的原因找到了,那么該如何解決問(wèn)題呢?
Windows當(dāng)然不會(huì)沒(méi)有想到這個(gè)問(wèn)題,在Windows中,提供了如下兩個(gè)函數(shù):WideCharToMultiByte和MultiByteToWideChar,他們都位于頭文件winnls.h中,分別是將寬字符轉(zhuǎn)化為多字節(jié)和將多字節(jié)轉(zhuǎn)化為寬字符。下面的例子直接給出了轉(zhuǎn)化的代碼,函數(shù)的具體使用方法可以翻閱MSDN。
int main(int argn,char* argv[]){ wchar_t strW[]=L"ABC 簡(jiǎn)體中文"; char* pW2A; int t=0; //第一次,確定需要的字節(jié)數(shù) t=WideCharToMultiByte(CP_ACP,0,strW,-1,NULL,0,NULL,FALSE); if(t!=0) { pW2A=(char*)malloc(t);//分配內(nèi)存,然后運(yùn)行第二次,注意參數(shù)區(qū)別 WideCharToMultiByte(CP_ACP,0,strW,-1,pW2A,t,NULL,FALSE); printf("%s/n",pW2A); free(pW2A); } return 0;}這回顯示就沒(méi)有什么問(wèn)題了,長(zhǎng)舒一口氣,暫時(shí)從坑里面爬出來(lái)了。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注