本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9690708
建立时间:2004年12月20日




[c++]VC字符串转换
文章收藏,  网上资源,  软件技术

邢红瑞 发表于 2005/7/24 10:39:11

一、BSTR、LPSTR和LPWSTR   在Visual C++编程中,常常要用到这样的一些基本字符串类型,如BSTR、LPSTR和LPWSTR等。  BSTR(Basic String,Basic字符串)是一个OLECHAR*类型的Unicode字符串。它被描述成一个与自动化相兼容的类型。由于操作系统提供相应的 API函数(如SysAllocString)来管理它以及一些默认的调度代码,因此BSTR实际上就是一个COM字符串。COM版本OLECHAR是wchar_t,但是TCHAR 对于UNICODE程序才是wchar_t。   LPSTR和LPWSTR是Win32和VC++所使用的一种字符串数据类型。LPSTR被定义成是一个指向以NULL(‘\0’)结尾的8位 ANSI字符数组指针,而LPWSTR是一个指向以NULL结尾的16位双字节字符数组指针。在VC++中,还LPTSTR、 LPCTSTR等。LPCTSTR是指“long pointer to a constant generic string”,表示“一个指向一般字符串常量的长指针类型”,与C/C++的const char*相映射,而LPTSTR映射为 char*。类型定义:#ifdef UNICODE  typedef LPWSTR LPTSTR;  typedef LPCWSTR LPCTSTR;#else  typedef LPSTR LPTSTR;  typedef LPCSTR LPCTSTR;#endif 二、CString、CStringA 和 CStringW  Visual C++中将CStringT作为ATL和MFC的共享的“一般”字符串类,它有CString、CStringA和CStringW三种形式,分别操作不同字符类型的字符串。这些字符类型是TCHAR、char和wchar_t。TCHAR在Unicode平台中等同于WCHAR(16位 Unicode字符),在ANSI中等价于char。wchar_t通常定义为unsigned short。三、VARIANT、COleVariant 和_variant_t在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版: struct tagVARIANT {  VARTYPE vt;  union {   short iVal; // VT_I2.   long lVal; // VT_I4.   float fltVal; // VT_R4.   double dblVal; // VT_R8.   DATE date; // VT_DATE.   BSTR bstrVal; // VT_BSTR.   …   short * piVal; // VT_BYREF|VT_I2.   long * plVal; // VT_BYREF|VT_I4.   float * pfltVal; // VT_BYREF|VT_R4.   double * pdblVal; // VT_BYREF|VT_R8.   DATE * pdate; // VT_BYREF|VT_DATE.   BSTR * pbstrVal; // VT_BYREF|VT_BSTR.  };};   显然,VARIANT类型是一个C结构,它包含了一个类型成员vt、一些保留字节以及一个大的union类型。例如,如果vt为VT_I2,那么我们可以从iVal中读出VARIANT的值。同样,当给一个VARIANT变量赋值时,也要先指明其类型。例如: VARIANT va;:: VariantInit(&va); // 初始化int a = 2002;va.vt = VT_I4; // 指明long数据类型va.lVal = a; // 赋值   为了方便处理VARIANT类型的变量,Windows还提供了这样一些非常有用的函数:   VariantInit —— 将变量初始化为VT_EMPTY;   VariantClear —— 消除并初始化VARIANT;   VariantChangeType —— 改变VARIANT的类型;   VariantCopy —— 释放与目标VARIANT相连的内存并复制源VARIANT。   COleVariant类是对VARIANT结构的封装。它的构造函数具有极为强大大的功能,当对象构造时首先调用VariantInit进行初始 化,然后根据参数中的标准类型调用相应的构造函数,并使用VariantCopy进行转换赋值操作,当VARIANT对象不在有效范围时,它的析构函数就 会被自动调用,由于析构函数调用了VariantClear,因而相应的内存就会被自动清除。除此之外,COleVariant的赋值操作符在与 VARIANT类型转换中为我们提供极大的方便。例如下面的代码: COleVariant v1("This is a test"); // 直接构造COleVariant v2 = "This is a test";// 结果是VT_BSTR类型,值为"This is a test"COleVariant v3((long)2002);COleVariant v4 = (long)2002;// 结果是VT_I4类型,值为2002   _variant_t是一个用于COM的VARIANT类,它的功能与COleVariant相似。不过在Visual C++.NET的MFC应用程序中使用时需要在代码文件前面添加下列两句:   #include "comutil.h"    #pragma comment( lib, "comsupp.lib" ) 四、CComBSTR和_bstr_t   CComBSTR是对BSTR数据类型封装的一个ATL类,它的操作比较方便。例如:CComBSTR bstr1;bstr1 = "Bye"; // 直接赋值OLECHAR* str = OLESTR("ta ta"); // 长度为5的宽字符CComBSTR bstr2(wcslen(str)); // 定义长度为5wcscpy(bstr2.m_str, str); // 将宽字符串复制到BSTR中CComBSTR bstr3(5, OLESTR("Hello World"));CComBSTR bstr4(5, "Hello World");CComBSTR bstr5(OLESTR("Hey there"));CComBSTR bstr6("Hey there");CComBSTR bstr7(bstr6);// 构造时复制,内容为"Hey there"   _bstr_t是是C++对BSTR的封装,它的构造和析构函数分别调用SysAllocString和SysFreeString函数,其他操作是借用BSTR API函数。与_variant_t相似,使用时也要添加comutil.h和comsupp.lib。 五、BSTR、char*和CString转换   (1) char*转换成CString   若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:char chArray[] = "This is a test";char * p = "This is a test";或LPSTR p = "This is a test";或在已定义Unicode应的用程序中TCHAR * p = _T("This is a test");或LPTSTR p = _T("This is a test");CString theString = chArray;theString.Format(_T("%s"), chArray);theString = p;   (2) CString转换成char*   若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法:   a 使用强制转换。例如: CString theString( "This is a test" );LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;   b 使用strcpy。例如: CString theString( "This is a test" );LPTSTR lpsz = new TCHAR[theString.GetLength()+1];_tcscpy(lpsz, theString);   需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。   c 使用CString::GetBuffer。例如: CString s(_T("This is a test "));LPTSTR p = s.GetBuffer();// 在这里添加使用p的代码if(p != NULL) *p = _T('\0');s.ReleaseBuffer(); 使用完后及时释放,以便能使用其它的CString成员函数,而且一般不要修改,修改时strcpy到一个新的数组。   (3) BSTR转换成char*a   使用ConvertBSTRToString。例如:#include#pragma comment(lib, "comsupp.lib")int _tmain(int argc, _TCHAR* argv[]){BSTR bstrText = ::SysAllocString(L"Test");char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);SysFreeString(bstrText); // 用完释放delete[] lpszText2;return 0;} b 使用_bstr_t的赋值运算符重载。例如: _bstr_t b = bstrText;char* lpszText2 = b;   (4) char*转换成BSTR  a 使用SysAllocString等API函数。例如: BSTR bstrText = ::SysAllocString(L"Test");BSTR bstrText = ::SysAllocStringLen(L"Test",4);BSTR bstrText = ::SysAllocStringByteLen("Test",4);   b 使用COleVariant或_variant_t。例如: //COleVariant strVar("This is a test");_variant_t strVar("This is a test");BSTR bstrText = strVar.bstrVal;   c 使用_bstr_t,这是一种最简单的方法。例如: BSTR bstrText = _bstr_t("This is a test");   d 使用CComBSTR。例如: BSTR bstrText = CComBSTR("This is a test");   或 CComBSTR bstr("This is a test");BSTR bstrText = bstr.m_str;   e 使用ConvertStringToBSTR。例如: char* lpszText = "Test";BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);   (5) CString转换成BSTR   通常是通过使用CStringT::AllocSysString来实现。例如: CString str("This is a test");BSTR bstrText = str.AllocSysString();…SysFreeString(bstrText); // 用完释放   (6) BSTR转换成CString   一般可按下列方法进行: BSTR bstrText = ::SysAllocString(L"Test");CStringA str;str.Empty();str = bstrText;或CStringA str(bstrText);   (7) ANSI、Unicode和宽字符之间的转换使用MultiByteToWideChar将ANSI字符转换成Unicode字符,使用WideCharToMultiByte将Unicode字符转换成ANSI字符。注意的是 在基于mfc的activex中函数返回值是 BSTR,这个没有什么疑问,但参数类型怎么居然是 LPCTSTR?在 COM 中,字符串不是应该使用 BSTR 吗?是的,是应该使用 BSTR,但由于我们是用 MFC 写自动化组件,它帮我们进行 BSTR 和 LPCTSTR 之间的转换了。 From To Sample 字符串常量 BSTR Right: BSTR bs = ::SysAllocString(_T("Test string")); … ::SysFreeString(); Wrong: BSTR bs = _T("Test string"); //ERROR LPWSTR / LPCWSTR / WCHAR* / wchar_t BSTR Right: LPCTSTR sz1 = _T("Test String"); BSTR bs = ::SysAllocString(sz1); … ::SysFreeString();   Wrong: LPTSTR sz1 = _T("Test String"); BSTR bs = sz1; //ERROR BSTR LPCWSTR / const WCHAR * / const wchar_t * Right: BSTR bs = ...; // ... LPCTSTR sz = static_cast<LPCTSTR>bs; ... ::SysFreeString(bs); //Never use sz after this line   Wrong: BSTR bs = ...; // ...   LPCTSTR sz = bs; ... ::SysFreeString(bs); //Never use sz after this line _tcslen(sz); //ERROR   BSTR LPWSTR / WCHAR* / wchar_t* Right: BSTR bs = ...; // //... UINT len = ::SysStringLen(bs);   // Do not modify the BSTR content by // C/C++ string functions LPTSTR sz = new TCHAR[len+1]; _tcsncpy(sz, bs, len); ::SysFreeString(bs);   delete []sz; Wrong: BSTR bs = ...; // //...   // Do not modify the BSTR content by // C/C++ string functions LPTSTR sz = bs; //Error   CString BSTR Right:   CString str1 = ...;   BSTR bs = str1.AllocSysString(); SomeMethod(bs); // void SomeMethod([in]BSTR) ::SysFreeString(bs);   CComBSTR bs1(static_cast<LPCTSTR>(str1)); SomeMethod(static_cast<BSTR> (bs1) );   // void SomeMethod([in] BSTR ) _bstr_t bs2( static_cast<LPCTSTR>(str1)); SomeMethod(static_cast<BSTR> (bs2) );   Wrong: CString str1 = ...;   SomeMethod(str1.AllocSysString());   // No one will releasee the return BSTR of // str1.AllocSysString()   BSTR CString Right:   BSTR bs = SysAllocString(_T(“Test”)); CString str1(bs); CString str2; Str2 = bs; SysFreeString(bs); // Never forget this line char* / LPSTR / LPCSTR BSTR Right: Solution 1: char str[MAX_STR_LEN] = "ANSI string"; WCHAR wstr[MAX_WSTR_LEN]; // Convert ANSI to Unicode   MultiByteToWideChar( CP_ACP, 0, str,         strlen(str)+1, wstr,        sizeof(wstr)/sizeof(wstr[0]) );   BSTR bs1 = ::SysAllocString(wstr);   CString cs = str; BSTR bs2 = cs.AllocSysString()   Solution 2: char str[MAX_STR_LEN] = "ANSI string"; _bstr_t bs1(str); CComBSTR bs2(str);   Wrong: char *str = "ANSI string"; BSTR bstr1 = SysAllocString(             (const OLECHAR*) str); BSTR char* / LPSTR / LPCSTR Right: Solution 1: char str[MAX_STR_LEN]; BSTR bs = ::SysAllocString(L"Test"); // Convert ANSI to Unicode WideCharToMultiByte( CP_ACP, 0,    (LPCWSTR)bs, -1,    str, MAX_STR_LEN, NULL, NULL ); ::SysFreeString(bs);   Solution 2: BSTR bs = ::SysAllocString(L"Test"); _bstr_t bs1(bs, false); const char* str = static_cast <const char*> bs1;   Wrong: BSTR bstr1 = SysAllocString(L”ANSI string"); char *str = (char*) bstr1;    


阅读全文(3219) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.299 second(s), page refreshed 144751591 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号