当前位置:C++技术网 > 资讯 > string和CString互换互用详细分析

string和CString互换互用详细分析

更新时间:2015-06-23 16:06:09浏览次数:1+次

    string和CString互用的难点就在于宽窄字符的互换问题。如果解决了这个问题,互换互用就不存在问题了。先来说说这两个的基本区别。CString是MFC中的字符串处理类,string是C++标准库的字符串处理类。两个的最适合的场合不一样,string适合于C字符串的地方,因为string内部实现是C字符数组模型,可以很好的处理C风格字符串。而CString则是出身于MFC,作为MFC的考虑,自然考虑的高远,因此给CString的实现增加了通用性,其内部实现是根据环境编码来调整的。如果环境使用Unicode编码形式,那么调用构造函数时,使用的是Unicode版本,因此每个字符就是用两个字节表示,就是宽字符类型字符串,而C风格字符串则是一个字节表示一个字符串的。如果环境使用多字节字符集形式,那么CString内部实现就是一个字节表示一个字符,这与C风格字符串兼容,因此处理起来就很方便了。
    而平常在使用CString时,使用宏_T()或者TEXT()让IDE自动区分宽窄字符,因此就省去了很多问题。但是有时候,也带来了问题。如果对于环境编码不熟悉的朋友,就不知道怎么处理了。有时候也不知道CString内部到底是宽字符还是窄字符。这里说明一下,在IDE的“项目”菜单中,选择”XXX属性”(XXX为工程名字),在“配置属性”>>“常规”>>“字符集”可以区别。改这里的字符集将会对代码中所有含有_T()或者TEXT()的以及T版的函数和变量名等都产生影响。可能就会使代码编译不通过等问题,视具体情况而定。而显式使用W版(宽字符版)和A版窄字符版的函数和变量类型,都不受影响。
    上面是两种的基本了解。如果要用最简单的做到互用,直接将IDE中的字符集设置成多字符集就可以解决这个问题。因为此时CString就相当于一个C风格字符串的指针,但是是一个智能指针,可以对CString字符串使用C风格字符串(即窄字符串)进行赋值等操作。而此时带来的问题就是,平常使用的一些函数如MessageBox使用上就需要注意了。因为MFC大多函数都是实现同性性特性,所以平时都用T宏来包含字符串,这样不管环境字符集怎么变,始终都可以保持一致。如果设置成多字节字符集,那么MessageBox则使用的是A版函数了,那么传入的参数就可以直接是C风格字符串了。而平常默认的Unicode编码时,传递C风格字符串是不允许的,这点就稍加说明。掌握了这个道理后,就可以运用自如。此时将string直接赋值给CString还是不行的,因为string是一个对象,而不是字符串指针,所以需要调用cstr()成员函数得到C风格字符串常量指针,就可以赋值给CString了,包括使用CString的format函数也是要传入C风格字符串的。但是,因为CString被处理成智能指针,CString对象就相当于字符串指针,就可以直接赋值给string使用了。这个很方便。如果使用内存复制函数memcpy,此时也是很方便的,因为CString调用GetBuffer函数就可以得到内部的字符串指针,而使用string的c_str函数就可以获得string内部的字符串常量指针,只要将这个指针强制转换成一般的指针就可以自由读写字符串了。因此关键的一点,此时CString和string内部都是一个字节表示一个字符,一对一关系,处理起来就很简单。需要注意的一点,CString调用GetBuffer函数时,打开了内部的字符串,内部就处于不稳定状态,因为字符串随时都可能修改删除等,所以打开后不要调用其他的成员函数,比如GetLeng函数,这样是不可靠的,因为获得长度后很可能就在返回长度那一刻字符就删除了。所以要打开CString前,要先获得长度保存下来,打开使用完后调用ReleaseBuffer函数释放,这样内部的字符串还是处于正常状态,之后就可以正常调用其他成员函数了。这里是说打开后不稳定,不是不能调用其他成员函数,而是调用后得不到可靠的结果而已。
    而如果环境使用的是Unicode字符集,那么这时就不能像上面那样处理了。将string赋值给CString,还不是那么容易的事情。这时发现直接赋值等都是行不通的,因为这是将窄字符传递给宽字符,而其内部没有做处理,就没办法赋值了。不过还好,CString的构造函数还是可以处理这种情况。CString n_str(cstr.c_str());//cstr是string对象。 这种情况下将窄字符的string传进去就可以得到宽字符CString了。而对于将CString转成string,从宽字符转到窄字符,还不是简单的将宽字符传入构造函数即可。这个还需要进一步研究,如果你知道,请告诉我哦。
    不过最后有一个很好的解决方案,那就是字符集的转换。使用WideCharToMultiByte函数可以将宽字符转换成多字节(窄字符),使用MultiByteToWideChar可以将多字节字符转成宽字符。这个方案或许是最方便的一种,互转很方便,通用性很好。
    具体的例子就不列举了,不过就是构造函数时、初始化赋值、赋值、格式化函数、内存复制。如果有必要,可以按照这些类型,去试试,学习效果会更好。