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

  • 相关阅读:
    零散
    修改element的内部样式的两种方式
    在vue-cli项目中使用第三方的js,不是es6格式
    Docker知识
    golang使用grpc
    vue中axios导出文件
    nginx、vue和thinkphp配置
    Mysql的一些问题
    数据库索引失效原因
    golang中使用grpc服务
  • 原文地址:https://www.cnblogs.com/htys/p/3420703.html
Copyright © 2020-2023  润新知