九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
VC知識庫文章 - VC++的Unicode編程

VC++的Unicode編程

作者:韓耀旭

下載源代碼

一、什么是Unicode

  先從ASCII說起,ASCII是用來表示英文字符的一種編碼規(guī)范。每個(gè)ASCII字符占用1個(gè)字節(jié),因此,ASCII編碼可以表示的最大字符數(shù)是255(00H—FFH)。其實(shí),英文字符并沒有那么多,一般只用前128個(gè)(00H—7FH,最高位為0),其中包括了控制字符、數(shù)字、大小寫字母和其它一些符號。而最高位為1的另128個(gè)字符(80H—FFH)被稱為“擴(kuò)展ASCII”,一般用來存放英文的制表符、部分音標(biāo)字符等等的一些其它符號。
  這種字符編碼規(guī)則顯然用來處理英文沒有什么問題。但是面對中文、阿拉伯文等復(fù)雜的文字,255個(gè)字符顯然不夠用。
于是,各個(gè)國家紛紛制定了自己的文字編碼規(guī)范,其中中文的文字編碼規(guī)范叫做“GB2312—80”,它是和ASCII兼容的一種編碼規(guī)范,其實(shí)就是利用擴(kuò)展ASCII沒有真正標(biāo)準(zhǔn)化這一點(diǎn),把一個(gè)中文字符用兩個(gè)擴(kuò)展ASCII字符來表示,以區(qū)分ASCII碼部分。
  但是這個(gè)方法有問題,最大的問題就是中文的文字編碼和擴(kuò)展ASCII碼有重疊。而很多軟件利用擴(kuò)展ASCII碼的英文制表符來畫表格,這樣的軟件用到中文系統(tǒng)中,這些表格就會被誤認(rèn)作中文字符,出現(xiàn)亂碼。
  另外,由于各國和各地區(qū)都有自己的文字編碼規(guī)則,它們互相沖突,這給各國和各地區(qū)交換信息帶來了很大的麻煩。
要真正解決這個(gè)問題,不能從擴(kuò)展ASCII的角度入手,而必須有一個(gè)全新的編碼系統(tǒng),這個(gè)系統(tǒng)要可以將中文、法文、德文……等等所有的文字統(tǒng)一起來考慮,為每一個(gè)文字都分配一個(gè)單獨(dú)的編碼。

于是,Unicode誕生了。

  Unicode也是一種字符編碼方法,它占用兩個(gè)字節(jié)(0000H—FFFFH),容納65536個(gè)字符,這完全可以容納全世界所有語言文字的編碼。
在Unicode里,所有的字符被一視同仁,漢字不再使用“兩個(gè)擴(kuò)展ASCII”,而是使用“1個(gè)Unicode”,也就是說,所有的文字都按一個(gè)字符來處理,它們都有一個(gè)唯一的Unicode碼。

二、使用Unicode編碼的好處

  使用Unicode編碼可以使您的工程同時(shí)支持多種語言,使您的工程國際化。
  另外,Windows NT是使用Unicode進(jìn)行開發(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)就會首先將Unicode字符串轉(zhuǎn)換成ANSI字符串,然后將結(jié)果返回給您的應(yīng)用程序。進(jìn)行這些字符串的轉(zhuǎn)換需要占用系統(tǒng)的時(shí)間和內(nèi)存。如果用Unicode來開發(fā)應(yīng)用程序,就能夠使您的應(yīng)用程序更加有效地運(yùn)行。

下面例舉幾個(gè)字符的編碼以簡單演示ANSI和Unicode的區(qū)別:

字符  A  N  和
ANSI碼  41H  4eH  cdbaH
Unicode碼  0041H  004eH  548cH

三、使用C++進(jìn)行Unicode編程

  對寬字符的支持其實(shí)是ANSI C標(biāo)準(zhǔn)的一部分,用以支持多字節(jié)表示一個(gè)字符。寬字符和Unicode并不完全等同,Unicode只是寬字符的一種編碼方式。

1、寬字符的定義

  在ANSI中,一個(gè)字符(char)的長度為一個(gè)字節(jié)(Byte)。使用Unicode時(shí),一個(gè)字符占據(jù)一個(gè)字,C++在wchar.h頭文件中定義了最基本的寬字符類型wchar_t:

typedef unsigned short wchar_t;

從這里我們可以清楚地看到,所謂的寬字符就是無符號短整數(shù)。

2、常量寬字符串

  對C++程序員而言,構(gòu)造字符串常量是一項(xiàng)經(jīng)常性的工作。那么,如何構(gòu)造寬字符字符串常量呢?很簡單,只要在字符串常量前加上一個(gè)大寫的L就可以了,比如:

wchar_t *str1=L" Hello";

這個(gè)L非常重要,只有帶上它,編譯器才知道你要將字符串存成一個(gè)字符一個(gè)字。還要注意,在L和字符串之間不能有空格。

3、寬字符串庫函數(shù)

為了操作寬字符串,C++專門定義了一套函數(shù),比如求寬字符串長度的函數(shù)是

size_t __cdel wchlen(const wchar_t*);

  為什么要專門定義這些函數(shù)呢?最根本的原因是,ANSI下的字符串都是以’\0’來標(biāo)識字符串尾的(Unicode字符串以“\0\0”結(jié)束),許多字符串函數(shù)的正確操作均是以此為基礎(chǔ)進(jìn)行。而我們知道,在寬字符的情況下,一個(gè)字符在內(nèi)存中要占據(jù)一個(gè)字的空間,這就會使操作ANSI字符的字符串函數(shù)無法正確操作。以”Hello”字符串為例,在寬字符下,它的五個(gè)字符是:
0x0048 0x0065 0x006c 0x006c 0x006f
在內(nèi)存中,實(shí)際的排列是:

48 00 65 00 6c 00 6c 00 6f 00

  于是,ANSI字符串函數(shù),如strlen,在碰到第一個(gè)48后的00時(shí),就會認(rèn)為字符串到尾了,用strlen對寬字符串求長度的結(jié)果就永遠(yuǎn)會是1!

4、用宏實(shí)現(xiàn)對ANSI和Unicode通用的編程

  可見,C++有一整套的數(shù)據(jù)類型和函數(shù)實(shí)現(xiàn)Unicode編程,也就是說,您完全可以使用C++實(shí)現(xiàn)Unicode編程。
如果我們想要我們的程序有兩個(gè)版本:ANSI版本和Unicode版本。當(dāng)然,編寫兩套代碼分別實(shí)現(xiàn)ANSI版本和Unicode版本完全是行得通的。但是,針對ANSI字符和Unicode字符維護(hù)兩套代碼是非常麻煩的事情。為了減輕編程的負(fù)擔(dān),C++定義了一系列的宏,幫助您實(shí)現(xiàn)對ANSI和Unicode的通用編程。
  C++宏實(shí)現(xiàn)ANSI和Unicode的通用編程的本質(zhì)是根據(jù)”_UNICODE”(注意,有下劃線)定義與否,這些宏展開為ANSI或Unicode字符(字符串)。

如下是tchar.h頭文件中部分代碼摘抄:

#ifdef  _UNICODEtypedef wchar_t     TCHAR;#define __T(x)      L##x#define _T(x)       __T(x)#else#define __T(x)      xtypedef char            TCHAR;#endif
  可見,這些宏根據(jù)”_UNICODE” 定義與否,分別展開為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ù)處理語法,它叫做“粘貼符號”,表示將前面的L添加到宏參數(shù)上。也就是說,如果我們寫_T(“Hello”),展開后即為L“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 charactertypedef CONST CHAR *LPCSTR, *PCSTR;
Win32 API在winnt.h頭文件中定義了一些實(shí)現(xiàn)字符和常量字符串的宏進(jìn)行ANSI/Unicode通用編程。同樣,只例舉幾個(gè)最常用的:
#ifdef  UNICODEtypedef WCHAR TCHAR, *PTCHAR;typedef LPWSTR LPTCH, PTCH;typedef LPWSTR PTSTR, LPTSTR;typedef LPCWSTR LPCTSTR;#define __TEXT(quote) L##quote      // r_winnt#else   /* UNICODE */               // r_winnttypedef 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(沒有下劃線),進(jìn)行條件編譯。
   Win32 API也定義了一套字符串函數(shù),它們根據(jù)是否定義了“UNICODE”分別展開為ANSI和Unicode字符串函數(shù)。如:lstrlen。API的字符串操作函數(shù)和C++的操作函數(shù)可以實(shí)現(xiàn)相同的功能,所以,如果需要的話,建議您盡可能使用C++的字符串函數(shù),沒必要去花太多精力再去學(xué)習(xí)API的這些東西。
  也許您從來沒有注意到,Win32 API實(shí)際上有兩個(gè)版本。一個(gè)版本接受MBCS字符串,另一個(gè)接受Unicode字符串。例如:其實(shí)根本沒有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
  可見,API函數(shù)根據(jù)定義UNICODE與否決定指向Unicode版本還是MBCS版本。
  細(xì)心的讀者可能已經(jīng)注意到了UNICODE和_UNICODE的區(qū)別,前者沒有下劃線,專門用于Windows頭文件;后者有一個(gè)前綴下劃線,專門用于C運(yùn)行時(shí)頭文件。換句話說,也就是在ANSI C++語言里面根據(jù)_UNICODE(有下劃線)定義與否,各宏分別展開為Unicode或ANSI字符,在Windows里面根據(jù)UNICODE(無下劃線)定義與否,各宏分別展開為Unicode或ANSI字符。
  在后面我們將會看到,實(shí)際使用中我們不加嚴(yán)格區(qū)分,同時(shí)定義_UNICODE和UNICODE,以實(shí)現(xiàn)UNICODE版本編程。

五、VC++6.0中編寫Unicode編碼的應(yīng)用程序

  VC++ 6.0支持Unicode編程,但默認(rèn)的是ANSI,所以開發(fā)人員只需要稍微改變一下編寫代碼的習(xí)慣便可以輕松編寫支持UNICODE的應(yīng)用程序。
  使用VC++ 6.0進(jìn)行Unicode編程主要做以下幾項(xiàng)工作:

1、為工程添加UNICODE和_UNICODE預(yù)處理選項(xiàng)。

  具體步驟:打開[工程]->[設(shè)置…]對話框,如圖1所示,在C/C++標(biāo)簽對話框的“預(yù)處理程序定義”中去除_MBCS,加上_UNICODE,UNICODE。(注意中間用逗號隔開)改動后如圖2:


圖一


圖二

  在沒有定義UNICODE和_UNICODE時(shí),所有函數(shù)和類型都默認(rèn)使用ANSI的版本;在定義了UNICODE和_UNICODE之后,所有的MFC類和Windows API都變成了寬字節(jié)版本了。

2、設(shè)置程序入口點(diǎn)

  因?yàn)镸FC應(yīng)用程序有針對Unicode專用的程序入口點(diǎn),我們要設(shè)置entry point。否則就會出現(xiàn)連接錯誤。
  設(shè)置entry point的方法是:打開[工程]->[設(shè)置…]對話框,在Link頁的Output類別的Entry Point里填上wWinMainCRTStartup。


圖三

3、使用ANSI/Unicode通用數(shù)據(jù)類型

  微軟提供了一些ANSI和Unicode兼容的通用數(shù)據(jù)類型,我們最常用的數(shù)據(jù)類型有_T ,TCHAR,LPTSTR,LPCTSTR。
  順便說一下,LPCTSTR和const TCHAR*是完全等同的。其中L表示long指針,這是為了兼容Windows 3.1等16位操作系統(tǒng)遺留下來的,在Win32 中以及其它的32位操作系統(tǒng)中,long指針和near指針及far修飾符都是為了兼容的作用,沒有實(shí)際意義。P(pointer)表示這是一個(gè)指針;C(const)表示是一個(gè)常量;T(_T宏)表示兼容ANSI和Unicode,STR(string)表示這個(gè)變量是一個(gè)字符串。綜上可以看出,LPCTSTR表示一個(gè)指向常固定地址的可以根據(jù)一些宏定義改變語義的字符串。比如:

TCHAR* szText=_T(“Hello!”);TCHAR szText[]=_T(“I Love You”);LPCTSTR lpszText=_T(“大家好!”);
使用函數(shù)中的參數(shù)最好也要有變化,比如:
MessageBox(_T(“你好”));

  其實(shí),在上面的語句中,即使您不加_T宏,MessageBox函數(shù)也會自動把“你好”字符串進(jìn)行強(qiáng)制轉(zhuǎn)換。但我還是推薦您使用_T宏,以表示您有Unicode編碼意識。

4、修改字符串運(yùn)算問題

  一些字符串操作函數(shù)需要獲取字符串的字符數(shù)(sizeof(szBuffer)/sizeof(TCHAR)),而另一些函數(shù)可能需要獲取字符串的字節(jié)數(shù)sizeof(szBuffer)。您應(yīng)該注意該問題并仔細(xì)分析字符串操作函數(shù),以確定能夠得到正確的結(jié)果。
ANSI操作函數(shù)以str開頭,如strcpy(),strcat(),strlen();
Unicode操作函數(shù)以wcs開頭,如wcscpy,wcscpy(),wcslen();
ANSI/Unicode操作函數(shù)以_tcs開頭 _tcscpy(C運(yùn)行期庫);
ANSI/Unicode操作函數(shù)以lstr開頭 lstrcpy(Windows函數(shù));
考慮ANSI和Unicode的兼容,我們需要使用以_tcs開頭或lstr開頭的通用字符串操作函數(shù)。

六、舉個(gè)Unicode編程的例子

第一步:
  打開VC++6.0,新建基于對話框的工程Unicode,主對話框IDD_UNICODE_DIALOG中加入一個(gè)按鈕控件,雙擊該控件并添加該控件的響應(yīng)函數(shù):

void CUnicodeDlg::OnButton1(){TCHAR* str1=_T("ANSI和UNICODE編碼試驗(yàn)");m_disp=str1;UpdateData(FALSE);}
  添加靜態(tài)文本框IDC_DISP,使用ClassWizard給該控件添加CString類型變量m_disp。使用默認(rèn)ANSI編碼環(huán)境編譯該工程,生成Unicode.exe。

第二步:
  打開“控制面板”,單擊“日期、時(shí)間、語言和區(qū)域設(shè)置”選項(xiàng),在“日期、時(shí)間、語言和區(qū)域設(shè)置”窗口中繼續(xù)單擊“區(qū)域和語言選項(xiàng)”選項(xiàng),彈出“區(qū)域和語言選項(xiàng)”對話框。在該對話框中,單擊“高級”標(biāo)簽,將“非Unicode的程序的語言”選項(xiàng)改為“日語”,單擊“應(yīng)用”按鈕,如圖四:


圖四

彈出的對話框單擊“是”,重新啟動計(jì)算機(jī)使設(shè)置生效。
運(yùn)行Unicode.exe程序并單擊“Button1”按鈕,看,靜態(tài)文本框出現(xiàn)了亂碼。

第三步:
  改為Unicode編碼環(huán)境編譯該工程,生成Unicode.exe。再次運(yùn)行Unicode.exe程序并單擊“Button1”按鈕。看到Unicode編碼的優(yōu)勢了吧。

就說這些吧,祝您好運(yùn)。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
VC中unicode項(xiàng)目向多字節(jié)字符集項(xiàng)目移植
VC Windows平臺字符透明編程大總結(jié)
在VC6.0下設(shè)置Unicode編譯環(huán)境
windows環(huán)境下unicode編程總結(jié)
LPSTR、LPCSTR、LPTSTR和LPCTSTR的意義及區(qū)別(轉(zhuǎn))
使你的C/C++代碼支持Unicode
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服