Win编程笔记:字符串小结

Basics

 

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, .. )

posted @ 2013-11-13 09:27  阿窟窿  阅读(447)  评论(0编辑  收藏  举报