现在的位置: 首页 > 综合 > 正文

Win编程笔记:字符串小结

2013年05月02日 ⁄ 综合 ⁄ 共 6982字 ⁄ 字号 评论关闭

 

Win编程笔记:字符串小结

 

JasonLee@http://blog.csdn.net/jasonblog

 

Basics

 

ANSIUnicode

前者是单字节字符编码,用来表示英语以及一些西欧语言的所有字符;后者是双字节字符编码,可以表示现代计算机涉及的所有字符(包括中文、日文等)。

显然,使用Unicode更有利于国际化和本地化。除此之外,Windows所有核心函数也都需要Unicode字符串。在调用这些函数时,如果传入ANSI字符串,那么这些函数会将其转换成Unicode再执行;反之,如果函数返回ANSI字符串,那么操作系统也是先将其从Unicode字符串转换为ANSI字符串再返回。这样的话,会增加开销,而且埋下一些目前已知的转换函数中存在的bug

 

使用Unicode

ANSI字符是由char类型来表示的,而在win编程中,Unicode字符由wchar_twide
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;

在前面加PLP或者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都可以通过编译,与之相应的通用字符串函数也出现了,比如_tcslentchar.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__TEXTtchar.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

 

BSTRCComBSTR

BSTR是指向复合数据类型的指针,该复合数据类型由长度前缀、数据字符串和结束符组成,并且要使用COM内存管理函数来管理BSTR,其专用语义繁多,用法繁琐。

CComBSTRBSTR的一个封装类。

 

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采用了类型定义来处理一些语法分支,XCHARPXSTRPCXSTR代表与模板参数一致的字符类型,而YCHARPYSTRPCYSTR相反。比如如果BaseTypechar,则XCHAR代表charYCHAR代表wchar_t,相应的PXSTRLPSTRPYSTRLPWSTR

基本使用小结如下:

    //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 );

    //以上例,与之相反的YCHARPYSTR也可

    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 );

    //以上两例,YCHARPCYSTR也可

    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 );

    //以上两例,PCYSTRYCHAR也可

抱歉!评论已关闭.