转自:http://blog.sina.com.cn/s/blog_4b7e71290100b1aj.html
五.使用TCHAR
TCHAR是一种字符串类型,它让你在以MBCS和UNNICODE来build程序时可以使用同样的代码,不需要使用繁琐的宏定义来包含你的代码。 TCHAR的定义如下:
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
所以用MBCS来build时,TCHAR是char,使用UNICODE时,TCHAR是wchar_t。还有一个宏来处理定义Unicode字符串常量时所需的L前缀。
#ifdef UNICODE
#define _T(x) L##x
#else
#define _T(x) x
#endif
##是一个预处理操作符,它可以把两个参数连在一起。如果你的代码中需要字符串常量,在它前面加上_T宏。如果你使用Unicode来build,它会在字符串常量前加上L前缀。像是用宏来隐藏SetWindowTextA/W的细节一样,还有很多可以供你使用的宏来实现str***()和_mbs***()等字符串函数。例如,你可以使用_tcsrchr宏来替换strrchr()、 _mbsrchr()和wcsrchr()。_tcsrchr根据你预定义的宏是_MBCS还是UNICODE来扩展成正确的函数,就像 SetWindowText所作的一样。
不仅str***()函数有TCHAR宏。其他的函数如, _stprintf(代替sprinft()和swprintf()),_tfopen(代替fopen()和_wfopen())。 MSDN中"Generic-Text Routine Mappings."标题下有完整的宏列表。
六.字符串宏定义
由于Win32 API文档的函数列表使用函数的常用名字(例如,"SetWindowText"),所有的字符串都是用TCHAR来定义的。(除了XP中引入的只适用于 Unicode的API)。下面列出一些常用的typedefs,你可以在MSDN中看到他们。
type
Meaning in MBCS builds
Meaning in Unicode builds
LPSTR
zero-terminated string of char (char*)
zero-terminated string of char (char*)
LPCSTR
constant zero-terminated string of char (const char*)
constant zero-terminated string of char (const char*)
WCHAR
wchar_t
wchar_t
LPWSTR
zero-terminated Unicode string (wchar_t*)
zero-terminated Unicode string (wchar_t*)
LPCWSTR
constant zero-terminated Unicode string (const wchar_t*)
constant zero-terminated Unicode string (const wchar_t*)
TCHAR
char
wchar_t
LPTSTR
zero-terminated string of TCHAR (TCHAR*)
zero-terminated string of TCHAR (TCHAR*)
LPCTSTR
constant zero-terminated string of TCHAR (const TCHAR*)
constant zero-terminated string of TCHAR (const TCHAR*)
一个增加的字符类型是OLETYPE。它表示自动化接口(如word提供的可以使你操作文档的接口)中使用的字符类型。这种类型一般被定义成 wchar_t,然而如果你定义了OLE2ANSI预处理标记,OLECHAR将会被定义成char类型。我知道现在已经没有理由定义 OLE2ANSI(从MFC3以后,微软已经不使用它了),所以从现在起我将把OLECHAR当作Unicode字符。
这里给出你将会看到的一些OLECHAR相关的typedefs:
Type
Meaning
OLECHAR
Unicode character (wchar_t)
LPOLESTR
string of OLECHAR (OLECHAR*)
LPCOLESTR
constant string of OLECHAR (const OLECHAR*)
还有两个用于字符串和字符常量的宏定义,它们可以使同样的代码被用于MBCS和Unicode builds :
Type
Meaning
_T(x)
Prepends L to the literal in Unicode builds.
OLESTR(x)
Prepends L to the literal to make it an LPCOLESTR.
在文档或例程中,你还会看到好多_T的变体。有四个等价的宏定义,它们是TEXT, _TEXT, __TEXT和__T,它们都起同样的做用。
七.字符串扩展类型及封装类
字符串的种类多种多样,有些可以应用在很多场合(比如C字符串的基础char类型),也有一些可能只是在特定情况下才会使用(比如使用MFC一般会用到 CString,而开发COM组件一般会涉及到BSTR或CComBSTR)。希望通过下面的总结能让大家清楚地了解到各种不同类型字符串的出处和通常情况下的使用场合。
封装类
出处
功能简介
使用
BSTR
COM
特殊的数据结构,可以保存字符串的长度
需要调用专门的API函数,容易造成内存泄漏。建议使用封装类。比如,CComBSTR。
VARIANT
COM
特殊结构,被设计用来实现跨语言的特性
用来在无类型(typeless)语言(如Jscript和VBScript)来传递数据。
CString
MFC
封装TCHAR类型的字符串
MFC中使用
COleVariant
MFC
继承自VARIANT
很少用
_bstr_t
CRT
是一对BSTR的完整封装类,隐藏了底层的BSTR。
_variant_t
CRT
是一个对VARIANT的完整封装,隐藏了底层的VARIANT。
basic_string
STL
类模版
string
wstring
CComBSTR
ATL
BSTR 封装类,允许直接访问底层BSTR。
它在某些情况下比_bstr_t有用的多。
CComVariant
ATL
VARIANT的封装类,但是VARIANT没有被隐藏。
CString
WTL
行为和MFC的 CString完全一样。
System::String
CLR 和 VC 7 类
一个String对象包含一个不可改变的字符串序列。
八.常用字符串转换
1、函数 WideCharToMultiByte(),转换 UNICODE 到 MBCS。使用范例:
LPCOLESTR lpw = L"Hello,你好";
size_t wLen = wcslen( lpw ) + 1; // 宽字符字符长度,+1表示包含字符串结束符
int aLen=WideCharToMultiByte( // 第一次调用,计算所需 MBCS 字符串字节长度
CP_ACP,
0,
lpw, // 宽字符串指针
wLen, // 字符长度
NULL,
0, // 参数0表示计算转换后的字符空间
NULL,
NULL);
LPSTR lpa = new char [aLen];
WideCharToMultiByte(
CP_ACP,
0,
lpw,
wLen,
lpa, // 转换后的字符串指针
aLen, // 给出空间大小
NULL,
NULL);
// 此时,lpa 中保存着转换后的 MBCS 字符串
... ... ... ...
delete [] lpa;
2、函数 MultiByteToWideChar(),转换 MBCS 到 UNICODE。使用范例:
LPCSTR lpa = "Hello,你好";
size_t aLen = strlen( lpa ) + 1;
int wLen = MultiByteToWideChar(
CP_ACP,
0,
lpa,
aLen,
NULL,
0);
LPOLESTR lpw = new WCHAR [wLen];
MultiByteToWideChar(
CP_ACP,
0,
lpa,
aLen,
lpw,
wLen);
... ... ... ...
delete [] lpw;
3、使用 ATL 提供的转换宏。
A2BSTR
OLE2A
T2A
W2A
A2COLE
OLE2BSTR
T2BSTR
W2BSTR
A2CT
OLE2CA
T2CA
W2CA
A2CW
OLE2CT
T2COLE
W2COLE
A2OLE
OLE2CW
T2CW
W2CT
A2T
OLE2T
T2OLE
W2OLE
A2W
OLE2W
T2W
W2T
上表中的宏函数,其实非常容易记忆:
2
好搞笑的缩写,to 的发音和 2 一样,所以借用来表示“转换为、转换到”的含义。
A
ANSI 字符串,也就是 MBCS。
W、OLE
宽字符串,也就是 UNICODE。
T
中间类型T。如果定义了 _UNICODE,则T表示W;如果定义了 _MBCS,则T表示A
C
const 的缩写
使用范例:
#include
void fun()
{
USES_CONVERSION; // 只需要调用一次,就可以在函数中进行多次转换
LPCTSTR lp = OLE2CT( L"Hello,你好") );
... ... ... ...
// 不用显式释放 lp 的内存,因为
// 由于 ATL 转换宏使用栈作为临时空间,函数结束后会自动释放栈空间。
}
使用 ATL 转换宏,由于不用释放临时空间,所以使用起来非常方便。但是考虑到栈空间的尺寸(VC 默认2M),使用时要注意几点:
1、只适合于进行短字符串的转换;
2、不要试图在一个次数比较多的循环体内进行转换;
3、不要试图对字符型文件内容进行转换,因为文件尺寸一般情况下是比较大的;
4、对情况 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();