ANSI和Unicode:
前者是單字節字符編碼,用來表示英語以及一些西歐語言的所有字符;後者是雙字節字符編碼,可以表示現代計算機涉及的所有字符(包括中文、日文等)。
顯然,使用Unicode更有利於國際化和本地化。除此之外,Windows所有核心函數也都需要Unicode字符串。在調用這些函數時,如果傳入ANSI字符串,那麼這些函數會將其轉換成Unicode再執行;反之,如果函數返回ANSI字符串,那麼操作系統也是先將其從Unicode字符串轉換爲ANSI字符串再返回。這樣的話,會增加開銷,而且埋下一些目前已知的轉換函數中存在的bug。
使用Unicode:
ANSI字符是由char類型來表示的,而在win編程中,Unicode字符由wchar_t(wide chartype)來表示的。在使用wchar_t類型時,需要在字符/字符串前加上大寫字母L來告訴編譯器這是Unicode字符/字符串,如下:
wchar_tc = L'a';
wchar_tstr[10] = L"hello";
爲了更有Windows特色,微軟做了如下類型定義(WinNT.h):
typedefchar CHAR;
typedefshort SHORT;
typedeflong LONG;
……
typedefwchar_t WCHAR;
在前面加P、LP或者C分別表示指針類型和Const限定,如:
typedef__nullterminated WCHAR*NWPSTR, *LPWSTR,*PWSTR;
……
typedef__nullterminated CONSTWCHAR *LPCWSTR,*PCWSTR;
……
typedef__nullterminated CHAR*NPSTR, *LPSTR,*PSTR;
……
typedef__nullterminated CONSTCHAR *LPCSTR,*PCSTR;
此外,爲了更通用一點,微軟還做了如下定義:
#ifdef UNICODE //r_winnt
#ifndef_TCHAR_DEFINED
typedefWCHAR TCHAR, *PTCHAR;
……
#define__TEXT(quote)L##quote // r_winnt
#else /* UNICODE */ //r_winnt
#ifndef _TCHAR_DEFINED
typedef char TCHAR, *PTCHAR;
……
#define __TEXT(quote) quote // r_winnt
#endif/* UNICODE */ //r_winnt
#defineTEXT(quote)__TEXT(quote) // r_winnt
即,使用TCHAR(以及PTSTR),無論字符集是ANSI還是Unicode都可以通過編譯,與之相應的通用字符串函數也出現了,比如_tcslen(tchar.h):
#ifdef_UNICODE
#define_tcslen wcslen
#else
#define_tcslen strlen
#endif
除了_tcslen,還有一堆其他的字符串處理函數,並且與_tcslen(計算字符串長度)不同,其它很多函數需要考慮安全性,比如_tcscpy或者_tcscat:
#ifdef_UNICODE
#define_tcscat wcscat
#define_tcscat_s wcscat_s
#define_tcscpy wcscpy
#define_tcscpy_s wcscpy_s
#else
#define_tcscat strcat
#define_tcscat_s strcat_s
#define_tcscpy strcpy
#define_tcscpy_s strcpy_s
#endif
緊接着處理函數的都是一個安全版本,這些安全性函數都是添加一個_s後綴,它們檢驗參數的有效性以及緩衝區是否足以容納結果。
最後,WinNT.h中還定義了宏TEXT、__TEXT,tchar.h中定義了宏_T、__T、_TEXT,這些宏的功能都是將字符/字符串轉換爲相應的通用類型,比如:
LPTSTRstr1 = _T("hello,world");
LPTSTRstr2 = TEXT("hello");
ATL字符串
COM字符類型
OLECHAR:不同操作系統上,OLECHAR對應不同字符類型,比如win32上對應wchar_t。
BSTR:一種帶長度前綴、含許多特殊語義的OLECHAR字符數組。
ATL字符串轉換類
所有類名稱都採用“C<源格式縮寫>2<目標格式縮寫>”的形式,第一個C表示類。縮寫中A代表指向char的字符指針(LPSTR)、W代表指向wchar_t的字符指針(LPWSTR)、T代表指向TCHAR的字符指針(LPTSTR)、OLE代表指向OLECHAR的字符指針(LPOLESTR)、C表示const限定符。
以下是字符串轉換類:
CA2W CA2WEX CA2T CA2TEX CA2CT CA2CTEX
COLE2T COLE2TEX COLE2CT COLE2CTEX CT2A
CT2AEX CT2CA CT2CAEX CT2OLE CT2OLEEX CT2COLE
CT2COLEEX CT2W CT2WEX CT2CW CT2CWEX CW2A
CW2AEX CW2T CW2TEX CW2CT CW2CTEX
BSTR與CComBSTR
BSTR是指向複合數據類型的指針,該複合數據類型由長度前綴、數據字符串和結束符組成,並且要使用COM內存管理函數來管理BSTR,其專用語義繁多,用法繁瑣。
CComBSTR是BSTR的一個封裝類。
CComBSTR
CComBSTR類維護一個BSTR類型的public成員m_str。
使用小結如下:
//CComBSTR使用小結
//1.構造
//CComBSTR() {m_str = NULL; }
CComBSTRstr1;
//CComBSTR(LPCOLESTRpSrc);
CComBSTRstr2(LPCOLESTR("hello,world"));
//CComBSTR(intnSize, LPCOLESTR sz);
CComBSTRstr3(5, (LPCOLESTR)NULL);
//CComBSTR(intnSize);
CComBSTRstr4(5);
//CComBSTR(LPCSTRpSrc);
CComBSTRstr5("hello,world");
//CComBSTR(intnSize, LPCSTR sz);
CComBSTRstr6(5,"hello,world");
//CComBSTR(REFGUIDsrc);
static constGUID id_sample =
{ 0x3d8b3644, 0xf90e, 0x4058, { 0x95,0xaf, 0xda, 0x5a, 0xe8, 0x81, 0x8, 0x98 } };
CComBSTRstr7(id_sample);
//2.複製構造函數
//CComBSTR(constCComBSTR& src);
CComBSTRstr8(str2);
//3.析構
//~CComBSTR(){::SysFreeString(m_str); }
//4.賦值
//CComBSTR&operator=(const CComBSTR& src){ ... m_str = src.Copy(); ...}
str3 = str2;
//CComBSTR&operator=(LPCOLESTR pSrc){ ... m_str = ::SysAllocString(pSrc); ... }
str8 = LPCOLESTR("hello,world");
//CComBSTR&operator=(LPCSTR pSrc){ ... m_str = A2WBSTR(pSrc); ... }
str1 = "hello,world";
//HRESULTAssignBSTR(const BSTR bstrSrc){ ... }
BSTR bstrTemp = ::SysAllocString(LPCOLESTR("hello,world"));
CComBSTRstr9;
str9.AssignBSTR(bstrTemp);
//boolLoadString(HINSTANCE hInst, UINT nID);
//從指定模塊hInst加載指定的字符串資源nID
//boolLoadString(UINT nID);
//使用全局變量_AtlBaseModule從當前模塊加載指定的字符串資源nID
//5.字符串連接
//HRESULTAppend(LPCOLESTR lpsz, int nLen);
//HRESULTAppend(LPCOLESTR lpsz);
//HRESULTAppend(LPCSTR);
//HRESULTAppend(char ch);
//HRESULTAppend(wchar_t ch);
//HRESULTAppend(const CComBSTR& bstrSrc);
//HRESULTAppendBSTR(BSTR p);
//HRESULTAppendBytes(const char * lpsz, int nLen);
//CComBSTR&operator+=(const CComBSTR& bstrSrc);
//6.字符串比較
//bool operator!() const { return (m_str == NULL); }
//operator<()一共有四個重載版本,後面個都是調用第一個,第一個使用VarBstrCmp進行比較
//booloperator<(const CComBSTR& bstrSrc) const{ ... }
//booloperator<(LPCSTR pszSrc) const{ ... }
//booloperator<(LPCOLESTR pszSrc) const{ ... }
//booloperator<(LPOLESTR pszSrc) const{ ... }
//operator>()與operator<()類似
//operator!=()和operator==()則多重載了一個與NULL比較的版本
//7.其它操作
//返回長度
//unsigned intLength() const { return ::SysStringLen(m_str); }
unsigned intlen = str2.Length();
//複製操作
//BSTR Copy() {... }
//HRESULTCopyTo(BSTR* pbstr);
//轉換操作
str2.ToLower();
str2.ToUpper();
//HRESULTBSTRToArray(LPSAFEARRAY * ppArray){ ... }
//HRESULTArrayToBSTR(const SAFEARRAY * pSrc){ ... }
//清空操作
str1.Empty();
//附加和分離BSTR
//BSTR Detach() {BSTR s = m_str; m_str = NULL; return s; }
//voidAttach(BSTR src){
// if(m_str != src){
// ::SysFreeString(m_str);
// m_str = src;
// }
//}
CString
從簡,使用CString,本質是使用CStringT模板類。
typedefCStringT< wchar_t,StrTraitATL<wchar_t,ChTraitsCRT<wchar_t> > > CAtlStringW;
typedefCStringT< char,StrTraitATL<char,ChTraitsCRT<char> > > CAtlStringA;
typedefCStringT< TCHAR,StrTraitATL<TCHAR,ChTraitsCRT<TCHAR> > > CAtlString;
……
typedefCAtlStringW CStringW;
typedefCAtlStringA CStringA;
typedefCAtlString CString;
……
template<typenameBaseType,classStringTraits>
class CStringT :
public CSimpleStringT……
CStringT繼承CSimpleStringT,該基類提供了很多基本字符串功能;BaseType模板參數用來確定字符類型,數據保存在基類私有成員m_pszData中;StringTraits參數確定資源字符串加載的模塊、字符串管理器以及提供低級的字符操作。ATL提供了默認的字符串管理器,該管理器是一個實現了IAtlStringMgr的具體類CAtlStringMgr。
CStringT採用了類型定義來處理一些語法分支,XCHAR、PXSTR、PCXSTR代表與模板參數一致的字符類型,而YCHAR、PYSTR、PCYSTR相反。比如如果BaseType爲char,則XCHAR代表char,YCHAR代表wchar_t,相應的PXSTR爲LPSTR,PYSTR爲LPWSTR。
基本使用小結如下:
//CStringT基本使用小結
//1.構造函數
//CStringT();
//explicitCStringT( IAtlStringMgr* pStringMgr );
//CStringT( constCStringT& strSrc );
//CStringT( constCThisSimpleString& strSrc );
//CStringT( constXCHAR* pszSrc );
//CStringT( constXCHAR* pch, int nLength );
//CStringT( constXCHAR* pch, int nLength, IAtlStringMgr* pStringMgr );
//CStringT( PXSTRpszSrc, IAtlStringMgr* pStringMgr );
//以上例,與之相反的YCHAR和PYSTR也可
CStringAcaStr1(L"hello,world");
CStringWcwStr1("hello,world");
CString cStr1;
CString cStr2(cStr1);
CString cStr3("hello,world");
CString cStr4('a', 5);
//2.賦值
//CStringT&operator=( const CStringT& strSrc );
//CStringT&operator=( const CThisSimpleString& strSrc );
//CStringT&operator=( PCXSTR pszSrc );
//CStringT&operator=( XCHAR ch );
//以上兩例,YCHAR和PCYSTR也可
caStr1 =L'b';
cwStr1 ='a';
cStr1 = "hello,world";
cStr1 = L"hello,world";
//3.字符串連接
//CStringT&operator+=( const CThisSimpleString& str );
//CStringT&operator+=( const PCXSTR pszSrc );
//CStringT&operator+=( const XCHAR ch );
//以上兩例,PCYSTR和YCHAR也可
caStr1+= L'a';
cwStr1+= L"new";
cStr1 +=cStr2;
//+運算
cStr1 + cStr2;
cStr1 + L'a';
cwStr1 +'a';
//Append
//void Append(PCXSTR pszSrc );
//void Append(PCXSTR pszSrc, int nLength );
//void Append(const CSimpleStringT& strSrc );
//voidAppendChar( XCHAR ch );
//4.轉換
cStr1.MakeLower();
cStr1.MakeUpper();
cStr1.MakeReverse();
//5.比較
//== != < >
caStr1== L"hello,world";
cwStr1!= "hello,world";
cStr1< cStr2;
//6.其它操作
//增
//int Insert( intiIndex, PCXSTR psz )
//int Insert( intiIndex, XCHAR ch )
cStr1.Insert(0,'a');
//刪
//從iIndex開始刪除nCount個字符
//int Delete( intiIndex, int nCount = 1 )
//刪除所有chRemove字符
//int Remove(XCHAR chRemove )
//改
//int Replace(XCHAR chOld, XCHAR chNew )
//int Replace(PCXSTR pszOld, PCXSTR pszNew )
//查
//int Find( XCHARch, int iStart = 0 ) const
//int Find( PCXSTRpszSub, int iStart = 0 ) const
//int FindOneOf(PCXSTR pszCharSet ) const
//intReverseFind( XCHAR ch ) const
//CStringT Left(int nCount ) const
//CStringT Mid(int iFirst ) const
//CStringT Mid(int iFirst, int nCount ) const
//CStringT Right(int nCount ) const
//XCHARoperator[]( int iChar ) const
str1[3];
//Trim方法
//CStringT&Trim()
//CStringT&Trim( XCHAR chTarget )
//CStringT&Trim( PCXSTR pszTargets )
//CStringT&TrimLeft()
//CStringT&TrimLeft( XCHAR chTarget )
//CStringT&TrimLeft( PCXSTR pszTargets )
//CStringT&TrimRight()
//CStringT&TrimRight( XCHAR chTarget )
//CStringT&TrimRight( PCXSTR pszTargets )
//按指定字符分割
//CStringTTokenize( PCXSTR pszTokens, int & iStart ) const
//CStringT格式化
//void __cdeclFormat( PCXSTR pszFormat, ... );
//void __cdeclFormat( UINT nFormatID, .. );
參考資料:
《Windows核心編程》
《深入解析ATL》
轉自:http://blog.csdn.net/jasonblog/article/details/6139669