Lei's profile踏遍青山人未老BlogNetwork Tools Help

Blog


    September 09

    MS平台中一些字符串相关类型处理的小结【1】

    前一段时间因为基于MFC和ATL做一点东西,被里面的字符串处理弄得几乎要吐血。。。没办法只好baidu+google+msdn。。。这样简单的事情都费了老大的功夫,看来以我的水准离程序员实在还是有很大差距。由此不由的向sphinx、clx、gy,以及MH、QLY和老Cao等致以崇高的敬意:何时才能修炼到你们的水准呐?!!!
    这里就算是对相关字符串处理做一个小结,很多东西来源于Internet,我也尽可能将出处标明。怎么说也可算是半原创了吧,这可是开天辟地头一遭啊Embarrassed

     以下是正文:

    1. char, string和wchar_t, wstring
        C/C++标准最基本的情况大家耳熟能详,没有什么好说的,无非是char* 和 string类的转换问题。string在名为std的命名空间中提供,实际上是basic_string<char>,即basic_string模板类的char实例化。
        从char*到string没的说,可直接利用构造函数;反过来从string到char*则一般依赖string类的成员函数c_str(),不过有个小问题,因为函数返回值是const char*,因此若要对其做改变还是自己copy一份比较稳当。
        以上我们可以称之为ANSI标准,到这里其实问题不是太大,无非是某些字符串处理函数是否线程安全,是否会导致Buffer Overflow等等。这些安全方面的考量不在本文的考察范围之类,因此直接无视之。但众所周知ANSI是8bit的东西,容纳不下像天朝这么博大的文字。于是后来就有了Unicode,就有了wstring,其实这仅仅是模板类basic_string的wchar_t实例化而已。
       
        PS:在VC的项目中,有选择“Use Unicode Character Set”或者“Use Multi-Byte Character Set” (MBCS)。这是两种不同的编码,前者都是两个字节,后者是混合型的(兼容ANSI,因此对英文来说没有区别)。在VC项目中的区别,据[1]说是区别在于前者编译器添加了“_UNICODE” 定义进行编译,而后者则没有这样的定义,一切依赖于“_UNICODE”的值,这样的话有个不错的变通方法,即按照VC中TCHAR的定义,自己定一个新 的类“tstring”,具体办法见[1]。
       
    2. ANSI和Unicode之间的转换
        如果ANSI和Unicode之间井水不犯河水,大家和平相处那就真的是天下太平啦。但人生不如意事十之八九,譬如不少软件系统,尤其是早期的版本很多建立在ANSI之上,为了跟上时代的脚步,需要向Unicode迁移;还有一些就是像我这样自作孽不可活的家伙,因为习惯于char*,于是不管三七二十一乱搞一通,后来发现某些东西(如COM)收礼只收Unicode。。。于是陷入没完没了的ANSI和Unicode之间的互相转换。。。泪流满面。。。
        言归正传。事实上从原理来说ANSI和Unicode之间的转换其实很简单,无非是单字节双字节表示方法的变换而已。问题在于自己做这样的转换既不安全亦不可靠(NB人士除外)。为此,ANSI和Win32各自提供了一套转换方法[2]:
    •   ANSI: setlocale,mbstowcs,wcstombs
    •   Win32: MultiByteToWideChar WideCharToMultiByte
       [2]也给出了一些使用的例子,请自行参考。
       但上述函数,尤其是Win32的函数保持了一贯的参数冗长的特色,实在是麻烦的紧。于是在MFC和ATL中提供了一系列东西供大家使用。。。不过数目是多了一点,让人有目不暇接之感。MFC曾经比较基本和常用的就是:
                1) A2CW      (LPCSTR) -> (LPCWSTR)
                2) A2W      (LPCSTR) -> (LPWSTR)
                3) W2CA      (LPCWSTR) -> (LPCSTR)
                4) W2A      (LPCWSTR) -> (LPSTR)
       这里LPCSTR即const char*, LPCWSTR指的是const wchar_t*,中间的C指的是const。。。依次类推。这四个都是宏,是基于
    MultiByteToWideChar WideCharToMultiByte两个函数或衍生函数之上的。
        不过列为看官,以上四个那都是老黄历了,(如果没有搞错的话。。。)自ATL 7.0之后定义了新的模板类以及基于这些模板类的宏,供MFC和ATL使用,MSDN给出的格式形如:CSourceType2[C]DestinationType[EX]。譬如CA2W,CW2CA等等。第一个C并非是指const,而是代表Class(个人感觉Convert更贴切^_^):
    •    SourceType and DestinationType are described in the table below.
    •    [C] is present when the destination type must be constant.
    •    [EX] is present when the initial size of the buffer must be specified as a template argument.

    SourceType/DestinationType

    Description

    A

    ANSI character string.

    W

    Unicode character string.

    T

    Generic character string (equivalent to W when _UNICODE is defined, equivalent to A otherwise).

    OLE

    OLE character string (equivalent to W).

        一般来说,我们大都使用通过typedef CA2WEX<> CA2W来定义的CA2W以及对应的CW2A。没有EX表示使用默认的缓冲区大小。这里的陷阱在于:由于返回的字符串的空间是在栈中分配的,因而它不能直接作为函数的返回值。
       

        PS: [2]提到Linux没有实现ANSI的这一套函数其实并不确切,[3]对此有一些解释。
       

    References:
    1. http://msdn.microsoft.com/en-us/magazine/cc188714.aspx
    2. http://dev.csdn.net/article/45/45124.shtm
    3. http://aaronike.spaces.live.com/blog/cns!437ebac13d3cefcd!120.entry


    Comments (12)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Shen GEwrote:
    潜心向学,汗,你不是在写代码么。。。
    在美国也有美少女战士么。。。
    Sept. 22
    Albert Zhengwrote:
    ……你还代表天顶星人呢~
    Sept. 16
    Lei Wuwrote:
    邱师傅简直灭绝人性啊,枉我还在开篇致敬!!!
    为了世间的爱和正义,代表月亮宣布将这厮踢出开篇名单了。。。
    O(∩_∩)O~
    Sept. 16
    Lei Wuwrote:
    晕倒,待我潜心向学后再来干倒胳膊。。。
    看来这里的小结的待续是要无限期推延了
    Sept. 16
    Linfeng Qiuwrote:
    围观,哈哈
    Sept. 15
    Hao Wangwrote:
    围观小胖被鄙视。^_^
    不过还是期待后文啊,这些东西我没搞明白过。学习学习……
    我正好想把趋势的东西做完,毕竟答应了人家的。汉字的敏感词检测,实现层面似乎也涉及charset、encoding之类的东西。
    嗯……当然了,如果做起来有难度,我也不介意食言的。
    Sept. 15
    Shen GEwrote:
    大哥,概念搞清楚好不好,要分清楚Unicode和Unicode表示的差别,Unicode逻辑上差不多20位从0000-10FFFF,但是可以有UTF-8,UTF-16等表示形式,国家标准GB18030也是一种Unicode的表示。。。。。
    Sept. 15
    Lei Wuwrote:
    靠,连胳膊这种不混工业界的都开始鄙视我了。。。痛哭流涕啊!!!不过我倒不是开始研究string,仅仅是总结一下winsows平台下的东西(主要是MFC、ATL以及COM中的字符串相关类型的转换和处理),省得以后用到了还得去查。还没有写完,大家敬请期待吧

    诸位听过文武双修麽?小说界和学术界不矛盾吧^_^

    PS:。。。unicode我只听说过16, 21(BMP)以及32三种,20位的是哪一个标准?
    Sept. 12
    Shen GEwrote:
    同认为你是小说界的。。。。。。
    到现在才开始看不同的string,唉,基本功啊。。。。
    忘了告诉你,Unicode是20位的,汉字EXT-A,EXT-B,需要一些特殊的转义符,不要轻易用wchar,有时候貌似Windows API都搞不定的,注意啊。。。
    Sept. 11
    Albert Zhengwrote:
    我还以为你是小说界的……
    Sept. 10
    Lei Wuwrote:
    靠,俺也是混学术界的好不好!
    Sept. 10
    Hao Wangwrote:
    Hi, Coder Wu! ^_^
    Sept. 10

    Trackbacks

    The trackback URL for this entry is:
    http://cid-e161eb52ad524ac0.spaces.live.com/blog/cns!E161EB52AD524AC0!257.trak
    Weblogs that reference this entry
    • None