青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

 

Unicode

?2.8.1 C 運行期庫對Unicode的支持

? 2.8.1.1 對標準的C頭文件<String.h> 作了修改,定義了一個名字為wchar_t的數據類型,用于處理Unicode 字符。

?????????
typedef unsigned short wchar_t;
????????
? 2.8.1.2 添加了與ANSI C字符串對應的字符串處理函數,以wcs開頭用于處理Unicode字符。

????????? wchar_t * wcscat(wchar_t *,const wchar_t *);
????????? wchar_t * wcschr(const wchar_t *,wchar_t);
????????? int wcscmp(const wchar_t *,const wchar_t *);
????????? wchar_t * wcscpy(wchar_t *,const wchar_t *);
????????? size_t wcslen(const wchar_t *);


? 2.8.1.3 為了建立雙重功能,提供了<TChar.h>幫助創建ANSI/Unicode通用源代碼文件,<TChar.h>提供了一些通用宏根據是否定義了_UNICODE來判斷是使用ANSI數據類型還是Unicode數據類型,是使用ANSI字符串處理函數還是使用Unicode字符串處理函數。
????????
類似于"Error"這樣的字符串提供了 _T 和 _TEXT 2個通用宏。

???????? #ifdef _UNICODE
????????
typedef wchar_t TCHAR;
?????? ? #else
?????? ?
typedef char TCHAR; //!UNICODE

????????
#ifdef _UNICODE
????????
#define __T(x) L##x
?????? ? #else
?????? ?
#define __T(x) x //!UNICODE

????????
#ifdef _UNICODE
????????
#define _TEXT(x) L ## x
?????? ? #else
?????? ?
#define _TEXT(x) x //!UNICODE

????????
#ifdef _UNICODE
????????
#define _tcslen wcslen
?????? ? #else
?????? ?
#define _tcslen strlen //!UNICODE


? 2.8.1.4
printf函數家族是要介紹的最后一組C運行期函數。如果在定義了_UNICODE的情況下編譯你的源代碼模塊,那么printf函數家族便希望所有字符和字符串參數代表Unicode字符和字符串。但是,如果在沒有定義_UNICODE的情況下編譯你的源代碼模塊,printf函數家族便希望傳遞給它的所有字符和字符串都是ANSI字符和字符串。但有個壞消息:在Windows程序中不能使用printf。雖然Windows程序中可以使用大多數C的執行時期鏈接庫-實際上,許多程序寫作者更愿意使用C內存管理和文件I/O函數而不是Windows中等效的函數-Windows對標準輸入和標準輸出沒有概念。在Windows程序中可使用fprintf,而不是printf。還有一個好消息,那就是仍然可以使用sprintf及sprintf系列中的其它函數來顯示文字。這些函數除了將內容格式化輸出到函數第一個參數所提供的字符串緩沖區以外,其功能與printf相同。

?2.8.3 Windows中的Unicode函數和ANSI函數


? 2.8.3.1
Windows NT從底層支援Unicode。這意味著Windows NT內部使用由16位字符組成的字符串。因為世界上其它許多地方還不使用16位字符串,所以Windows NT必須經常將字符串在操作系統內轉換。Windows NT可執行為ASCII、Unicode或者ASCII和Unicode混合編寫的程序。即,Windows NT支持不同的API函數呼叫,這些函數接受8位或16位的字符串.

? 2.8.3.2 一個Windows程序包括表頭文件WINDOWS.H。該文件包括許多其它表頭文件,包括WINDEF.H,該文件中有許多在Windows中使用的基本型態定義,而且它本身也包括WINNT.H。WINNT.H處理基本的Unicode支持。

WINNT.H的前面包含C的表頭文件CTYPE.H,這是C的眾多表頭文件之一,包括wchar_t的定義。WINNT.H定義了新的數據型態,稱作CHAR和WCHAR:

typedef char CHAR ;        
typedef wchar_t WCHAR ;    // wc        

當您需要定義8位字符或者16位字符時,推薦您在Windows程序中使用的數據型態是CHAR和WCHAR。WCHAR定義后面的注釋是匈牙利標記法的建議:一個基于WCHAR數據型態的變量可在前面附加上字母wc以說明一個寬字符。

WINNT.H表頭文件進而定義了可用做8位字符串指針的六種數據型態和四個可用做const 8位字符串指針的數據型態。這里精選了表頭文件中一些實用的說明數據型態語句:

typedef CHAR * PCHAR, * LPCH, * PCH, * NPSTR, * LPSTR, * PSTR ;        
typedef CONST CHAR * LPCCH, * PCCH, * LPCSTR, * PCSTR ;        

前綴N和L表示「near」和「long」,指的是16位Windows中兩種大小不同的指標。在Win32中near和long指標沒有區別。

類似地,WINNT.H定義了六種可作為16位字符串指針的數據型態和四種可作為const 16位字符串指針的數據型態:

typedef WCHAR * PWCHAR, * LPWCH, * PWCH, * NWPSTR, * LPWSTR, * PWSTR ;        
typedef CONST WCHAR * LPCWCH, * PCWCH, * LPCWSTR, * PCWSTR ;        

至此,我們有了數據型態CHAR(一個8位的char)和WCHAR(一個16位的wchar_t),以及指向CHAR和WCHAR的指標。與TCHAR.H一樣,WINNT.H將TCHAR定義為一般的字符類型。如果定義了標識符UNICODE(沒有底線),則TCHAR和指向TCHAR的指標就分別定義為WCHAR和指向WCHAR的指標;如果沒有定義標識符UNICODE,則TCHAR和指向TCHAR的指標就分別定義為char和指向char的指標:

#ifdef  UNICODE 
typedef WCHAR TCHAR, * PTCHAR ;
typedef LPWSTR LPTCH, PTCH, PTSTR, LPTSTR ; 
typedef LPCWSTR LPCTSTR ;      
#else
typedef char TCHAR, * PTCHAR ;  
typedef LPSTR LPTCH, PTCH, PTSTR, LPTSTR ; 
typedef LPCSTR LPCTSTR ;   
#endif
        

如果已經在某個表頭文件或者其它表頭文件中定義了TCHAR數據型態,那么WINNT.H和WCHAR.H表頭文件都能防止其重復定義。不過,無論何時在程序中使用其它表頭文件時,都應在所有其它表頭文件之前包含WINDOWS.H。

WINNT.H表頭文件還定義了一個宏,該宏將L添加到字符串的第一個引號前。如果定義了UNICODE標識符,則一個稱作 __TEXT的宏定義如下:

#define __TEXT(quote) L##quote        

如果沒有定義標識符UNICODE,則像這樣定義__TEXT宏:

#define __TEXT(quote) quote        

此外, TEXT宏可這樣定義:

#define TEXT(quote) __TEXT(quote)        

這與TCHAR.H中定義_TEXT宏的方法一樣,只是不必操心底線。我將在本書中使用這個宏的TEXT版本。


???????
? 2.8.3.3 Windows頭文件也定義了ANSI/Unicode通用數據類型PTSTR和PCTSTR.這些數據類型既可以指ANSI字符串,也可以指Unicode字符串,這取決于當編譯程序模塊時是否定義了UNICODE宏。這里的UNICODE宏沒有前置的下劃線。_UNICODE宏用于C運行期頭文件。


?2.8.4 Windows字符串函數??

?
2.8.4.1 Windows提供了一組對字符串進行操作的通用函數,這些函數是通過宏來實現的,這些宏既可以調用函數的Unicode版本,也可以調用函數的ANSI版本,這要根據編譯源代碼模塊時是否已經定義了UNICODE而定。例如,如果沒有定義UNICODE,lstrcat函數將擴展為lstrcatA。如果定義了UNICODE,lstrcat將擴展為lstrcatW

???????? lstrcat??? 將一個字符串置于另一個字符串的結尾處
???????? lstrcmp??? 對兩個字符串進行區分大小寫的比較??????? 對Windows函數CompareString的調用來實現的。

???????? lstrcmpi?? 對兩個字符串進行不區分大小寫的比較????? Windows函數CompareString的調用來實現的。
???????? lstrcpy??? 將一個字符串拷貝到內存中的另一個位置
???????? lstrlen??? 返回字符串的長度(按字符數來計量)

???????

?
2.8.4.2 Windows還提供了<ShlWApi.h>頭文件包含一組范圍很廣的通用字符串操作函數,類似于StrCat、StrChr、StrCmp和StrCpy等.這些字符串函數既有ANSI版本,也有Unicode版本,例如StrCatA和StrCatW,這取決于當編譯程序模塊時是否定義了UNICODE宏,這些函數與C運行期字符串函數(如strcpy和wcscpy很相似),但是該操作系統函數是操作系統的一個組成部分,操作系統的許多組件都使用這些函數,而不使用C運行期庫。建議最好使用操作系統函數,而不要使用C運行期字符串函數。這將有助于稍稍提高你的應用程序的運行性能,因為操作系統字符串函數常常被大型應用程序比如操作系統的外殼進程Explorer.exe所使用。由于這些函數使用得很多,因此,在你的應用程序運行時,它們可能已經被裝入RAM。



?2.9.4 在Unicode與ANSI之間轉換字符串

? 2.9.4.1
<待續>



?2.9.5 成為符合ANSI和Unicode的應用程序

即使你不打算立即使用Unicode,最好也應該著手將你的應用程序轉換成符合Unicode 的應用程序。下面是應該遵循的一些基本原則:

? 將文本串視為字符數組,而不是chars 數組或字節數組。
? 將通用數據類型(如TCHAR和PTSTR)用于文本字符和字符串。
? 將顯式數據類型(如BYTE和PBYTE)用于字節、字節指針和數據緩存。
? 將TEXT宏用于原義字符和字符串。
? 執行全局性替換(例如用PTSTR替換PSTR)。
? 修改字符串運算問題。例如函數通常希望你在字符中傳遞一個緩存的大小,而不是字節。

這意味著你不應該傳遞sizeof(szBuffer),而應該傳遞(sizeof(szBuffer)/sizeof(TCHAR)。另外,如果需要為字符串分配一個內存塊,并且擁有該字符串中的字符數目,那么請記住要按字節來分配內存。這就是說,應該調用malloc(nCharacters *sizeof(TCHAR)),而不是調用malloc(nCharacters)。在上面所說的所有原則中,這是最難記住的一條原則,如果操作錯誤,編譯器將不發出任何警告。



???? <Windows核心編程>
???? <Windows程序設計>



2.9.5 C++ string

我經常在 C++ 程序中使用標準模板庫(STL)的 std::string 類,但在 使用 Unicode 時碰到了問題。在使用常規 C 風格的字符串時,我可以使用 TCHAR 和 _T 宏,這樣針對 Unicode 或 ASCII 均可以進行編譯,但我 總是發現這種ASCII/Unicode的結合很難與 STL 的 string 類一起使用。你有什么好的建議嗎?
是的,一旦知道 TCHAR 和_T 是如何工作的,那么這個問題很簡單?;舅枷胧?TCHAR 要么是char,要么是 wchar_t,這取決于 _UNICODE 的值:
  // abridged from tchar.h
	#ifdef  _UNICODE
	typedef wchar_t TCHAR;
	#define __T(x) L ## x
	#else
	typedef char TCHAR;
	#define __T(x) x
	#endif
  當你在工程設置中選擇 Unicode 字符集時,編譯器會用 _UNICODE 定義進行編譯。如果你選擇MBCS(多字節字符集),則編譯器將不會帶 _UNICODE 定義 。一切取決于_UNICODE 的值。同樣,每一個使用字符指針的 Windows API 函數會有一個 A(ASCII) 和一個 W(Wide/Unicode) 版本,這些版本的 實際定義也是根據 _UNICODE 的值來決定:
#ifdef UNICODE
	#define CreateFile CreateFileW
	#else
	#define CreateFile CreateFileA
	#endif
  同樣,_tprintf 和 _tscanf 對應于 printf 和 scanf。所有帶"t"的版本使用 TCHARs 取代了chars。那么怎樣把以上的這些應用到 std::string 上呢?很簡單。STL已經有一個使用寬字符定義的wstring類 (在 xstring 頭文件中定義)。string 和 wstring 均是使用 typedef 定義的模板類,基于 basic_string, 用它可以創建任何字符類型的字符串類。以下就是 STL 定義的 string 和 wstring:
// (from include/xstring)
	  typedef basic_string< char, 
	  char_traits< char >, allocator< char > >
	  string;
	  typedef basic_string< wchar_t, 
	  char_traits< wchar_t >, allocator< wchar_t > > 
	  wstring;
  模板被潛在的字符類型(char 或 wchar_t)參數化,因此,對于 TCHAR 版本,所要做的就是使用 TCHAR 來模仿定義。
   typedef basic_string< TCHAR, 
	  char_traits< TCHAR >, 
	  allocator< TCHAR > > 
	  tstring;
  現在便有了一個 tstring,它基于 TCHAR——也就是說,它要么是 char,要么是 wchar_t,這取決于 _UNICODE 的值。 以上示范并指出了 STL 是怎樣使用 basic_string 來實現基于任何類型的字符串的。定義一個新的 typedef 并不是解決此問題最有效的方法。一個更好的方法是基于 string 和wstring 來簡單 地定義 tstring,如下:
#ifdef _UNICODE
	#define tstring wstring
	#else
	#define tstring string
	#endif
  這個方法之所以更好,是因為 STL 中已經定義了 string 和 wstring,那為什么還要使用模板來定義一個新的和其中之一一樣的字符串類呢? 暫且叫它 tstring。可以用 #define 將 tstring 定義為 string 和 wstring,這樣可以避免創建另外一個模板類( 雖然當今的編譯器非常智能,如果它把該副本類丟棄,我一點也不奇怪)。[編輯更新-2004/07/30:typedef 不創建新類,只是為某個類型引入限定范圍的名稱,typedef 決不會定義一個新的類型]。不管怎樣,一旦定義了 tstring,便可以像下面這樣編碼:
tstring s = _T("Hello, world");
      _tprintf(_T("s =%s\n"), s.c_str());
  basic_string::c_str 方法返回一個指向潛在字符類型的常量指針;在這里,該字符類型要么是const char*,要么是 const wchar_t*。
  Figure 2 是一個簡單的示范程序,舉例說明了 tstring 的用法。它將“Hello,world”寫入一個文件,并報告寫了多少個字節。我對 工程進行了設置,以便用 Unicode 生成 debug 版本,用 MBCS 生成 Release 版本。你可以分別進行編譯/生成并運行程序,然后比較結果。Figure 3 顯示了例子的運行情況。


Figure 3 運行中的 tstring

  順便說一下,MFC 和 ATL 現在已經聯姻,以便都使用相同的字符串實現。結合后的實現使用一個叫做 CStringT 的模板類,這在某種意義上 ,其機制類似 STL 的 basic_string,用它可以根據任何潛在的字符類型來創建 CString 類。在 MFC 包含文件 afxstr.h 中定義了三種字符 串類型,如下:
typedef ATL::CStringT< wchar_t, 
	  StrTraitMFC< wchar_t > > CStringW;
	  typedef ATL::CStringT< char, 
	  StrTraitMFC< char > > CStringA;
	  typedef ATL::CStringT< TCHAR, 
	  StrTraitMFC< TCHAR > > CString;
CStringW,CStringA 和 CString 正是你所期望的:CString 的寬字符,ASCII 和 TCHAR 版本。
  那么,哪一個更好,STL 還是 CStirng?兩者都很好,你可以選擇你最喜歡的一個。但有一個問題要考慮到:就是你想要鏈接哪個庫,以及你是否已經在使用 MFC/ATL。從編碼 的角度來看,我更喜歡 CString 的兩個特性:
  其一是無論使用寬字符還是char,都可以很方便地對 CString 進行初始化。
CString s1 = "foo";
	CString s2 = _T("bar");	
  這兩個初始化都正常工作,因為 CString 自己進行了所有必要的轉換。使用 STL 字符串,你必須使用_T()對 tstring 進行初始化,因為你 無法通過一個char*初始化一個wstring,反之亦然。
  其二是 CString 對 LPCTSTR 的自動轉換操作,你可以像下面這樣編碼:
  CString s;
	LPCTSTR lpsz = s;
  另一方面,使用 STL 必須顯式調用 c_str 來完成這種轉換。這確實有點挑剔,某些人會爭辯說,這樣能更好地了解何時進行轉換。比如, 在C風格可變參數的函數中使用 CString 可能會有麻煩,像 printf:
  printf("s=%s\n", s); // 錯誤
	printf("s=%s\n", (LPCTSTR)s); // 必需的	
  沒有強制類型轉換的話,得到的是一些垃圾結果,因為 printf 希望 s 是 char*。我敢肯定很多讀者都犯過這種錯誤。防止這種災禍是 STL 設計者不提供轉換操作符的一個毋庸置疑的理由。而是堅持要你調用 c_str。一般來講,喜歡使用 STL 家伙趨向于理論和學究氣,而 Redmontonians(譯者:指微軟)的大佬們則更注重實用和散漫。嘿,不管怎樣,std::string 和 CString 之間的實用差別是微不足道的。



作者簡介
  Paul DiLascia 是一名自由作家,顧問和 Web/UI 設計者。他是《Writing Reusable Windows Code in C++》書(Addison-Wesley, 1992)的作者。通過 http://www.dilascia.com 可以獲得更多了解。  
本文出自 MSDN Magazine August 2004 期刊,可通過當地報攤獲得,或者最好是 訂閱

本文由 VCKBASE MTT 翻譯
,http://www.vckbase.com/document/viewdoc/?id=1293







posted on 2011-08-13 01:32 Vcer-JZ 閱讀(921) 評論(0)  編輯 收藏 引用 所屬分類: MFC

導航

統計

隨筆分類

隨筆檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            精品成人一区二区| 欧美日本不卡| 麻豆国产va免费精品高清在线| 亚洲欧美国产精品专区久久| 久久美女艺术照精彩视频福利播放| 国产精品女同互慰在线看| 欧美在线国产| 91久久在线观看| 亚洲一区久久久| 亚洲国产精品999| 久久久国产成人精品| 亚洲一区综合| 国产欧美精品在线播放| 欧美在线视频免费| 亚洲国产mv| 亚洲精品一区二区三区福利| 欧美激情五月| 久久久国产午夜精品| 激情五月综合色婷婷一区二区| 欧美一区二区免费视频| 性刺激综合网| 黄色成人小视频| 欧美sm视频| 欧美成人午夜激情在线| 亚洲日本在线视频观看| 亚洲国内高清视频| 免费看亚洲片| 亚洲免费电影在线| 99re8这里有精品热视频免费 | 红杏aⅴ成人免费视频| 欧美一二三视频| 亚洲一区二区三区激情| 国产精品成人免费精品自在线观看| 亚洲一区二区三区欧美 | 欧美精品一区二区三区很污很色的| 国产一区日韩二区欧美三区| 欧美有码在线视频| 久久综合色88| 欧美国产日韩免费| 久久天天躁狠狠躁夜夜av| 亚洲激情中文1区| 牛牛影视久久网| 欧美理论大片| 久久精品电影| 蜜臀久久久99精品久久久久久 | 精品91在线| 日韩午夜av| 一色屋精品视频免费看| 亚洲国产一区二区三区在线播 | 亚洲精选在线| 欧美成人免费网站| 国产精品久久久久一区| 欧美jjzz| 国产精品日日做人人爱| 欧美黄色影院| 国产一区二区三区高清在线观看| 亚洲电影免费| 国产一区白浆| 中国女人久久久| 亚洲人www| 久久激情网站| 午夜伦欧美伦电影理论片| 免费看黄裸体一级大秀欧美| 亚洲精品社区| 免费在线观看日韩欧美| 亚洲自拍都市欧美小说| 另类激情亚洲| 欧美一区二区日韩| 欧美激情视频一区二区三区免费 | 一级成人国产| 久久久噜噜噜久久| 中文在线不卡视频| 亚洲一区二区三区四区中文| 久久久精品性| 国产精品亚洲成人| 亚洲老板91色精品久久| 国产亚洲欧美日韩美女| 99精品久久久| 一区二区高清视频| 久热精品视频在线观看一区| 久久久久久九九九九| 欧美三级韩国三级日本三斤| 老司机午夜精品| 国产伪娘ts一区| 午夜精品在线视频| 久久av一区二区三区漫画| 国产精品色在线| 亚洲一级免费视频| 午夜精品久久久久久久久久久久久 | 亚洲精品欧美日韩专区| 激情91久久| 午夜国产欧美理论在线播放| 亚洲天堂av图片| 欧美高清视频在线| 亚洲国产精彩中文乱码av在线播放 | 精品电影在线观看| 一区二区三区高清视频在线观看| 一色屋精品视频在线观看网站| 久久国产主播精品| 久久久综合网站| 精品96久久久久久中文字幕无| 久久精品道一区二区三区| 久久爱www久久做| 欧美综合国产| 久久综合久久久久88| 在线国产精品一区| 欧美暴力喷水在线| 日韩视频在线免费观看| 亚洲综合三区| 国产在线观看91精品一区| 免费成人av资源网| 亚洲人成77777在线观看网| 欧美日韩视频在线一区二区 | 日韩视频在线一区| 欧美xart系列在线观看| 亚洲国产精品久久| 欧美了一区在线观看| 亚洲视频你懂的| 久久久国产午夜精品| 亚洲黄色毛片| 欧美私人网站| 午夜精品一区二区三区在线| 欧美大学生性色视频| 在线中文字幕一区| 国产一区二区三区不卡在线观看| 久久亚洲电影| 99精品福利视频| 老司机免费视频一区二区三区| 99国产精品视频免费观看一公开| 国产精品家教| 久久九九免费视频| 亚洲一区在线免费观看| 国产麻豆综合| 欧美高清视频在线观看| 亚洲综合导航| 亚洲国产精品女人久久久| 国内免费精品永久在线视频| 欧美经典一区二区| 欧美影视一区| 欧美肉体xxxx裸体137大胆| 亚洲福利免费| 久久久精品一区二区三区| 一本色道久久综合精品竹菊| 国产亚洲综合精品| 亚洲午夜久久久| 国产精品久久久久久久久久妞妞| 久久精品视频在线看| 一区二区国产在线观看| 牛牛影视久久网| 久久精品免费看| 亚洲综合激情| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 裸体歌舞表演一区二区| 亚洲午夜女主播在线直播| 免费成年人欧美视频| 午夜视频精品| 亚洲在线播放电影| 国产精品99久久久久久久vr| 亚洲国产精品第一区二区三区| 欧美在线综合| 香蕉久久精品日日躁夜夜躁| 久久香蕉精品| 欧美在线网站| 午夜视频一区二区| 亚洲视频精品| 夜夜精品视频| 欧美精品一区二区三区在线看午夜| 久久精品国产精品亚洲综合| 亚洲欧美国产毛片在线| 亚洲一区在线观看视频| 中文欧美字幕免费| 99热在线精品观看| 亚洲精品影院在线观看| 亚洲韩国青草视频| 亚洲国产视频一区| 亚洲福利专区| 亚洲国产成人久久| 亚洲国产乱码最新视频| 亚洲欧洲日本mm| 亚洲精品国产精品国自产观看| 日韩亚洲视频| 一区二区三区久久| 夜夜嗨网站十八久久| 亚洲一区二区精品在线观看| 中日韩美女免费视频网站在线观看| 日韩视频在线观看免费| 99视频一区二区| 亚洲一区综合| 久久国产精品一区二区三区四区| 亚洲日韩中文字幕在线播放| 亚洲精品欧美激情| 亚洲色图综合久久| 亚洲欧美怡红院| 久久久久久久久久久久久女国产乱| 久久精品一区中文字幕| 欧美成人精品一区| 欧美午夜在线观看| 国产伦精品一区| 有坂深雪在线一区| 亚洲美女av网站|