[MFC]CString与其他类型的转换

  • Post author:
  • Post category:其他


在MFC中CString是字符串的常用表示方法,但是还有很多别的类型,例如数字类型等。(PS:微软的人真是不容易,折腾出这么多种类型来。。。)

==================================基础知识=====================================

这一部分肯定是要首先知道什么叫“单字节字符”、“宽字符”和“多字节字符”。

参见:

http://www.dzsc.com/data/html/2008-9-12/69107.html

所以“单字节字符”=ANSI

“宽字符”= UNICODE

多字节字符往往在实际中叫做“multi-byte”。

==============================================================================

【CString】

CString实质上是一个TCHAR类型的容器,如下:

typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;

而TCHAR类型在Unicode环境下被定义为WCHAR,非如下:

#ifdef UNICODE

typedef wchar_t TCHAR;

#else

typedef unsigned char TCHAR;

#endif

wchar_t是Unicode用的宽字符类型,用双字表示的字符。

也就是说虽然CString基于TCHAR这个定义是固定的,但是由于TCHAR在不同环境下所代表的不一样,所以也就导致CString具有一定的灵活性。所以在用CString编程的时候一定要注意其是否是Unicode环境下。

=================================CString转数字=================================

下面以数字中的ULONGLONG型为例。int整型仅需要更改格式化字符串即可。

【CString转ULONGLONG】

我们记得,从标准输入读入数据的C函数是scanf(),那从字符串读取数据的函数就是sscanf()。可以参见相应的百度百科词条(

http://baike.baidu.com/view/1364018.htm

)。其Unicode版本就是swscanf(),这个函数在VC2008中也等价于_stscanf()函数。

#define _stscanf        swscanf

用法如下:


ULONGLONG l;

CString str;

_stscanf( (LPCTSTR)str, _T(“%I64u”), &l);

当然,现在应该使用安全版本的swscanf_s()函数了。

【ULONGLONG转CString】

其实从数字转化到字符串属于“格式化”的情况,格式化函数常用于将非字符串类型的数据转换为CString。这个跟printf和scanf的情况类似,需要使用格式化符号。而CString的格式化函数就叫做Format()。用法如下:


ULONGLONG l;

CString str;

str.Format( _T(“%I64u”) , l );

“I64”表示64位,“u”表示无符号,前面的“_T()”表示结果要转化为Unicode模式,如果你现在的工作环境并不是Unicode环境,那就没有必要转化了。

===============================CString转char===============================

char型其实不仅仅是char型,实际上这里还指char*/const char*/char []等类型。这里请注意:写明char型实际上已经表示这是单字节型,肯定不是Unicode,所以只要你在Unicode环境中看到char类型,那转换肯定是必不可少的了。

PS:Windows中的LPCSTR类型与const char*是完全等价的,这不存在是否Unicode问题。因为其定义就是:

typedef __nullterminated CONST CHAR *LPCSTR

PS2:请注意区别LPCSTR和LPCTSTR这一对,区别LPSTR和LPTSTR这一对。也就是中间带T的就表示它们是基于TCHAR的,也就跟CString一样,能用于两种环境。而不带T的只能用于ANSI环境。搞清这一点,其实这些类型就不容易混了。

用个比喻的说法就是:带T的类型LPTSTR和LPCTSTR就是人妖,又可以当男的,又可以当女的。。。看环境不同吧。。。

【const char*转CString】

这个虽然看起来很难,但实际上很简单。

在非Unicode环境中,我们可以直接用:


CString str = “hello world”;

来初始化CString。用构造函数形式也是没有问题的:


CString str(“hello world”);

但是在Unicode环境下,必须要转型:


CString str( _T(“hello world”) );

也就是说,CString的构造函数和_T()转型符替我们完成了从const char*向CString转型的过程,细节被隐藏了。

当然,你也可以用下面说到的两种方法的逆向方法。参见这里:

http://hi.baidu.com/unix_dnybz/blog/item/21713354fd6511163b2935f0.html

注意哦:下面的代码在Unicode环境下面会出现乱码。



char* ch = “hello”;

CString str;

str.Format( “%s”, ch );//小写s

【CString转const char*】

这个问题的实质在于CString是一个数组,而const char*是一个指针,是以null字符结尾的。这个网上似乎有不少办法,但是都离不开使用Windows API。

法1:USES_CONVERSION和W2A宏。W2A宏实际上就是“wide character to ansi”的意思。


CString str;

USES_CONVERSION;

const char* ch = W2A( str.LockBuffer() );

str.UnlockBuffer();

法2:WideCharToMultiByte(),以及wctomb()函数–函数名也是wide char to multi byte的意思。

这个用法太麻烦了。但是它的功能更强大,可以用在中文内码转换上(不懂。。。),参见这里:


http://www.vckbase.com/document/viewdoc/?id=1709


===============================CString转宽字符===================================

宽字符除了前面说过的在Unicode环境下的LPTSTR和LPCTSTR(人妖。。。)以外,还有专用的宽字符字符串LPWSTR,其定义为:

typedef __nullterminated WCHAR *LPWSTR;

这就表示这是一个以NULL字符结尾的字符串指针。基于的类型是WCHAR,即wchar_t。

这其实就是相当于在C语言中一直就存在的char []和char*问题一样。MFC的CString类提供了这样一个函数将字符数组转化为以NULL字符结尾的字符串指针,用法如下:


CString cstr = _T(“hello world”);

LPWSTR pszText = cstr.AllocSysString();