闲谈字符串转换

      计算机发明后,为了在计算机中表示字符,人们制定了一种编码,叫ASCII码。ASCII码由一个字节中的7位(bit)表示,范围是0x00 - 0x7F 共128个字符。他们以为这128个数字就足够表示abcd....ABCD....1234 这些字符了。
       咳......说英语的人就是“笨”!后来他们突然发现,如果需要按照表格方式打印这些字符的时候,缺少了“制表符”。于是又扩展了ASCII的定义,使用一个字节的全部8位(bit)来表示字符了,这就叫扩展ASCII码。范围是0x00 - 0xFF 共256个字符。
  咳......说中文的人就是聪明!中国人利用连续2个扩展ASCII码的扩展区域(0xA0以后)来表示一个汉字,该方法的标准叫GB-2312。后来,日文、韩文、阿拉伯文、台湾繁体(BIG-5)......都使用类似的方法扩展了本地字符集的定义,现在统一称为 MBCS 字符集(多字节字符集)。这个方法是有缺陷的,因为各个国家地区定义的字符集有交集,因此使用GB-2312的软件,就不能在BIG-5的环境下运行(显示乱码),反之亦然。
  咳......说英语的人终于变“聪明”一些了。为了把全世界人民所有的所有的文字符号都统一进行编码,于是制定了UNICODE标准字符集。UNICODE 使用2个字节表示一个字符(unsigned shor int、WCHAR、_wchar_t、OLECHAR)。这下终于好啦,全世界任何一个地区的软件,可以不用修改地就能在另一个地区运行了。虽然我用 IE 浏览日本网站,显示出我不认识的日文文字,但至少不会是乱码了。UNICODE 的范围是 0x0000 - 0xFFFF 共6万多个字符,其中光汉字就占用了4万多个。嘿嘿,中国人赚大发了:0).

在程序中使用各种字符集的方法:

// 使用 ASCII 字符集 
 const char * p = "Hello"; 

 // 使用MBCS 字符集,由于MBCS完全兼容ASCII,多数情况下,我们并不严格区分他们. 
 const char * p = "你好";  

 // 使用MBCS 字符集,由于MBCS完全兼容ASCII,多数情况下,我们并不严格区分他们.  
 LPCSTR p = "Hello,你好";  

 // 使用 UNICODE 字符集
 const WCHAR * p = L"Hello,你好"; 

 // 使用 UNICODE 字符集
 LPCOLESTR p = L"Hello,你好";	 

 // 如果预定义了_UNICODE,则表示使用UNICODE字符集;如果定义了_MBCS,则表示使用 MBCS .
 const TCHAR * p = _T("Hello,你好");  

 // 如果预定义了_UNICODE,则表示使用UNICODE字符集;如果定义了_MBCS,则表示使用 MBCS .
 LPCTSTR p = _T("Hello,你好");

   

      在上面的例子中,T是非常有意思的一个符号(TCHAR、LPCTSTR、LPTSTR、_T()、_TEXT()...),它表示使用一种中间类型,既不明确表示使用 MBCS,也不明确表示使用 UNICODE。那到底使用哪种字符集那?嘿嘿......编译的时候决定吧。

设置条件编译的方式是:

VC6中,"Project => Settings => C/C++ => Preprocessor  => Preprocessor definitions" 中添加或修改 _MBCS、_UNICODE;

VC.NET中,"Project => Properties => Configuration Properties => C/C++ => Preprocessor  => Preprocessor definitions" 然后用组合窗进行选择。

使用 T 类型,是非常好的习惯,严重推荐!

 

BSTR
  COM 中除了使用一些简单标准的数据类型外(注2),字符串类型需要特别重点地说明一下。还记得原则吗?COM 组件是运行在分布式环境中的。通俗地说,你不能直接把一个内存指针直接作为参数传递给COM函数。你想想,系统需要把这块内存的内容传递到“地球另一 边”的计算机上,因此,我至少需要知道你这块内存的尺寸吧?不然让我如何传递呀?传递多少字节呀?!而字符串又是非常常用的一种类型,因此 COM 设计者引入了 BASIC 中字符串类型的表示方式---BSTR。BSTR 其实是一个指针类型,它的内存结构是:(输入程序片段 BSTR p = ::SysAllocString(L"Hello, 你好"); 断点执行,然后观察p的内存.

BSTR是一个指向UNICODE 字符串的指针,BSTR前的4个字节中,使用DWORD保存着这个字符串的字节长度(没有含字符串的结束符)。因此系统就能够正确处理并传送这个字符串到地球另一边了。特别需要注意的是,由于BSTR的指针就是指向UNICODE 串,因此BSTRLPOLESTR可以在一定程度上混用,但一定要注意:

例如
有函数 Testfun(LPCOLESTR lp),则你调用BSTR p = Testfun(p); 正确
有函数 Testfun(const BSTR bstr),则你调用 LPCOLESTR p = Testfun(p);错误!!!
有关BSTR的处理函数:

API 函数说明
SysAllocString()申请一个 BSTR 指针,并初始化为一个字符串
SysFreeString()释放 BSTR 内存
SysAllocStringLen()申请一个指定字符长度的 BSTR 指针,并初始化为一个字符串
SysAllocStringByteLen()申请一个指定字节长度的 BSTR 指针,并初始化为一个字符串
SysReAllocStringLen()重新申请 BSTR 指针

CString 函数

说明

AllocSysString()从 CString 得到 BSTR
SetSysString()重新申请 BSTR 指针,并复制到 CString 中

CComBSTR 函数

ATL 的 BSTR 包装类。在 atlbase.h 中定义

Append()、AppendBSTR()、AppendBytes()、ArrayToBSTR()、BSTRToArray()、AssignBSTR()、Attach()、Detach()、Copy()、CopyTo()、Empty()、Length()、ByteLength()、ReadFromStream()、WriteToStream()、LoadString()、ToLower()、ToUpper()
运算符重载:!,!=,==,<,>,&,+=,+,=,BSTR
    太多了,但从函数名称不能看出其基本功能。详细资料,查看MSDN 吧。另外,左侧函数,有很多是 ATL 7.0 提供的,VC6.0 下所带的 ATL 3.0 不支持。
    由于我们将来主要用 ATL 开发组件程序,因此使用 ATL 的 CComBSTR 为主。VC也提供了其它的包装类 _bstr_t。


各种字符串类型之间的转换
     1、函数 WideCharToMultiByte(),转换 UNICODE 到 MBCS。使用范例:

LPCOLESTR lpwStr = L"Hello,你好"; 
size_t wLen = wcslen(lpwStr) + 1; // 宽字符字符长度,+1表示包含字符串结束符 

// 第一次调用,计算所需 MBCS 字符串字节长度.
int aLen = WideCharToMultiByte(CP_ACP, 0, lpwStr, wLen, NULL, 0,  NULL, NULL);

// 此时,lpa 中保存着转换后  MBCS 字符串
LPSTR lpaStr = new char [aLen]; 
WideCharToMultiByte( CP_ACP, 0, lpwStr, wLen, lpaStr, aLen, NULL, NULL);  

    2、函数 MultiByteToWideChar(),转换 MBCS 到 UNICODE。使用范例:

LPCSTR lpaStr = "Hello,你好"; 
size_t aLen = strlen(lpaStr) + 1; 
int wLen = MultiByteToWideChar( CP_ACP, 0, lpaStr, aLen, NULL, 0);
LPOLESTR lpwStr = new WCHAR [wLen]; 
::MultiByteToWideChar( CP_ACP, 0, lpaStr, aLen, lpwStr, wLen);
//... ... ... ... 
delete [] lpwStr;

     3、使用 ATL 提供的转换宏。

A2BSTROLE2AT2AW2A
A2COLEOLE2BSTRT2BSTRW2BSTR
A2CTOLE2CAT2CAW2CA
A2CWOLE2CTT2COLEW2COLE
A2OLEOLE2CWT2CWW2CT
A2TOLE2TT2OLEW2OLE
A2WOLE2WT2WW2T
上表中的宏函数,其实非常容易记忆:
2好搞笑的缩写,to 的发音和 2 一样,所以借用来表示“转换为、转换到”的含义。
AANSI 字符串,也就是 MBCS。
W、OLE宽字符串,也就是 UNICODE。
T中间类型T。如果定义了 _UNICODE,则T表示W;如果定义了 _MBCS,则T表示A
Cconst 的缩写

使用范例:

#include <atlconv.h> 
void Fun() 
{ 
	// 只需要调用一次,就可以在函数中进行多次转换 
	USES_CONVERSION; 

	// 不用显式释放lpszStr的内存,因为由于ATL转换宏使用栈作为临时空间,函数结束后会自动释放栈空间。 
	LPCTSTR lpszStr = OLE2CT(L"Hello,你好"); 
	//......
}

 

使用 ATL 转换宏,由于不用释放临时空间,所以使用起来非常方便。但是考虑到栈空间的尺寸(VC 默认2M),使用时要注意几点:
    1、只适合于进行短字符串的转换;
    2、不要试图在一个次数比较多的循环体内进行转换;
    3、不要试图对字符型文件内容进行转换,因为文件尺寸一般情况下是比较大的;
    4、对情况2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值