VisualC.NET中的字符串转换方法

时间:2007-06-15 来源: 作者: 【字体: 减小 增大收藏 | 投稿
  
VisualC.NET涉及到ATL/ATLServer、MFC和托管C等多种编程方式,不仅功能强大而且应用广泛。在编程中,我们常常会遇到ANSI、Unicode以及BSTR不同编码类型的字符串转换操作。本文先介绍基本字符串类型,然后说明相关的类,如CComBSTR、_bstr_t、CStringT等,最后讨论它们的转换方法,其中还包括使用最新ATL7.0的转换类和宏,如CA2CT、CA2TEX等。

  一、BSTR、LPSTR和LPWSTR

  在VisualC.NET的所有编程方式中,我们常常要用到这样的一些基本字符串类型,如BSTR、LPSTR和LPWSTR等。之所以出现类似上述的这些数据类型,是因为不同编程语言之间的数据交换以及对ANSI、Unicode和多字节字符集(MBCS)的支持。

  那么什么是BSTR、LPSTR以及LPWSTR呢?

  BSTR(BasicSTRing,Basic字符串)是一个OLECHAR*类型的Unicode字符串。它被描述成一个与自动化相兼容的类型。由于操作系统提供相应的API函数(如SysAllocString)来管理它以及一些默认的调度代码,因此BSTR实际上就是一个COM字符串,但它却在自动化技术以外的多种场合下得到广泛使用。图1描述了BSTR的结构,其中DWORD值是字符串中实际所占用的字节数,且它的值是字符串中Unicode字符的两倍。 财软联盟,fs119.net

  LPSTR和LPWSTR是Win32和VC所使用的一种字符串数据类型。LPSTR被定义成是一个指向以NULL(‘\0’)结尾的8位ANSI字符数组指针,而LPWSTR是一个指向以NULL结尾的16位双字节字符数组指针。在VC中,还有类似的字符串类型,如LPTSTR、LPCTSTR等,它们的含义如图2所示。

  例如,LPCTSTR是指“longpointertoaconstantgenericstring”,表示“一个指向一般字符串常量的长指针类型”,与C/C的constchar*相映射,而LPTSTR映射为char*。

  一般地,还有下列类型定义:

#ifdefUNICODE
 typedefLPWSTRLPTSTR;
 typedefLPCWSTRLPCTSTR;
#else
 typedefLPSTRLPTSTR;
 typedefLPCSTRLPCTSTR;
#endif
  二、CString、CStringA和CStringW

  VisualC.NET中将CStringT作为ATL和MFC的共享的“一般”字符串类,它有CString、CStringA和CStringW三种形式,分别操作不同字符类型的字符串。这些字符类型是TCHAR、char和wchar_t。TCHAR在Unicode平台中等同于WCHAR(16位Unicode字符),在ANSI中等价于char。wchar_t通常定义为unsignedshort。由于CString在MFC应用程序中经常用到,这里不再重复。
财,软联盟,fs119.net


  三、VARIANT、COleVariant和_variant_t

  在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版:

structtagVARIANT{
 VARTYPEvt;
 union{
  shortiVal;//VT_I2.
  longlVal;//VT_I4.
  floatfltVal;//VT_R4.
  doubledblVal;//VT_R8.
  DATEdate;//VT_DATE.
  BSTRbstrVal;//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变量赋值时,也要先指明其类型。例如: 财管.家园.fs119.net

VARIANTva;
::VariantInit(&va);//初始化
inta=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类型转换中为我们提供极大的方便。例如下面的代码: 财管家园,fs119.net

COleVariantv1("Thisisatest");//直接构造
COleVariantv2="Thisisatest";
//结果是VT_BSTR类型,值为"Thisisatest"
COleVariantv3((long)2002);
COleVariantv4=(long)2002;
//结果是VT_I4类型,值为2002


  _variant_t是一个用于COM的VARIANT类,它的功能与COleVariant相似。不过在VisualC.NET的MFC应用程序中使用时需要在代码文件前面添加下列两句:

  #include"comutil.h"

  #pragmacomment(lib,"comsupp.lib")
财软,联盟,fs119.net

财 软联盟 fs119.net

财.软联盟.fs119.net


财管家园,fs119.net

财管家,园,fs119.net

  四、CComBSTR和_bstr_t

  CComBSTR是对BSTR数据类型封装的一个ATL类,它的操作比较方便。例如:

CComBSTRbstr1;
bstr1="Bye";//直接赋值
OLECHAR*str=OLESTR("tata");//长度为5的宽字符
CComBSTRbstr2(wcslen(str));//定义长度为5
wcscpy(bstr2.m_str,str);//将宽字符串复制到BSTR中
CComBSTRbstr3(5,OLESTR("HelloWorld"));
CComBSTRbstr4(5,"HelloWorld");
CComBSTRbstr5(OLESTR("Heythere"));
CComBSTRbstr6("Heythere");
CComBSTRbstr7(bstr6);
//构造时复制,内容为"Heythere"
  _bstr_t是是C对BSTR的封装,它的构造和析构函数分别调用SysAllocString和SysFreeString函数,其他操作是借用BSTRAPI函数。与_variant_t相似,使用时也要添加comutil.h和comsupp.lib。

  五、BSTR、char*和CString转换

  (1)char*转换成CString 财,管家园,fs119.net

  若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:

charchArray[]="Thisisatest";
char*p="Thisisatest";
  或

LPSTRp="Thisisatest";
  或在已定义Unicode应的用程序中

TCHAR*p=_T("Thisisatest");
  或

LPTSTRp=_T("Thisisatest");
CStringtheString=chArray;
theString.Format(_T("%s"),chArray);
theString=p;
  (2)CString转换成char*

  若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法:

  方法一,使用强制转换。例如:

CStringtheString("Thisisatest");

财软.联盟.fs119.net


LPTSTRlpsz=(LPTSTR)(LPCTSTR)theString;
  方法二,使用strcpy。例如:

CStringtheString("Thisisatest");
LPTSTRlpsz=newTCHAR[theString.GetLength()1];
_tcscpy(lpsz,theString);
  需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是constwchar_t*(Unicode)或constchar*(ANSI),系统编译器将会自动对其进行转换。

  方法三,使用CString::GetBuffer。例如:

CStrings(_T("Thisisatest"));
LPTSTRp=s.GetBuffer();
//在这里添加使用p的代码
if(p!=NULL)*p=_T('\0');
s.ReleaseBuffer();
//使用完后及时释放,以便能使用其它的CString成员函数
  (3)BSTR转换成char*

  方法一,使用ConvertBSTRToString。例如:

#include 财软联,盟,fs119.net
#pragmacomment(lib,"comsupp.lib")
int_tmain(intargc,_TCHAR*argv[]){
BSTRbstrText=::SysAllocString(L"Test");
char*lpszText2=_com_util::ConvertBSTRToString(bstrText);
SysFreeString(bstrText);//用完释放
delete[]lpszText2;
return0;
}
  方法二,使用_bstr_t的赋值运算符重载。例如:

_bstr_tb=bstrText;
char*lpszText2=b;
  (4)char*转换成BSTR

  方法一,使用SysAllocString等API函数。例如:

BSTRbstrText=::SysAllocString(L"Test");
BSTRbstrText=::SysAllocStringLen(L"Test",4);
BSTRbstrText=::SysAllocStringByteLen("Test",4);
  方法二,使用COleVariant或_variant_t。例如:

//COleVariantstrVar("Thisisatest");
_variant_tstrVar("Thisisatest");
财管.家园.fs119.net

BSTRbstrText=strVar.bstrVal;
  方法三,使用_bstr_t,这是一种最简单的方法。例如:

BSTRbstrText=_bstr_t("Thisisatest");
  方法四,使用CComBSTR。例如:

BSTRbstrText=CComBSTR("Thisisatest");
  或

CComBSTRbstr("Thisisatest");
BSTRbstrText=bstr.m_str;
  方法五,使用ConvertStringToBSTR。例如:

char*lpszText="Test";
BSTRbstrText=_com_util::ConvertStringToBSTR(lpszText);
  (5)CString转换成BSTR

  通常是通过使用CStringT::AllocSysString来实现。例如:

CStringstr("Thisisatest");
财软联盟.fs119.net

BSTRbstrText=str.AllocSysString();

SysFreeString(bstrText);//用完释放
  (6)BSTR转换成CString

  一般可按下列方法进行:

BSTRbstrText=::SysAllocString(L"Test");
CStringAstr;
str.Empty();
str=bstrText;
  或

CStringAstr(bstrText);
  (7)ANSI、Unicode和宽字符之间的转换

  方法一,使用MultiByteToWideChar将ANSI字符转换成Unicode字符,使用WideCharToMultiByte将Unicode字符转换成ANSI字符。

  方法二,使用“_T”将ANSI转换成“一般”类型字符串,使用“L”将ANSI转换成Unicode,而在托管C环境中还可使用S将ANSI字符串转换成String*对象。例如:

TCHARtstr[]=_T("thisisatest");
wchar_twszStr[]=L"Thisisatest";

财软联 盟 fs119.net


String*str=S”Thisisatest”;
  方法三,使用ATL7.0的转换宏和类。ATL7.0在原有3.0基础上完善和增加了许多字符串转换宏以及提供相应的类,它具有如图3所示的统一形式:

  其中,第一个C表示“类”,以便于ATL3.0宏相区别,第二个C表示常量,2表示“to”,EX表示要开辟一定大小的缓冲。SourceType和DestinationType可以是A、T、W和OLE,其含义分别是ANSI、Unicode、“一般”类型和OLE字符串。例如,CA2CT就是将ANSI转换成一般类型的字符串常量。下面是一些示例代码:

LPTSTRtstr=CA2TEX<16>("thisisatest");
LPCTSTRtcstr=CA2CT("thisisatest");
wchar_twszStr[]=L"Thisisatest";
char*chstr=CW2A(wszStr);
  六、结语

  几乎所有的程序都要用到字符串,而VisualC.NET由于功能强大、应用广泛,因而字符串之间的转换更为频繁。本文几乎涉及到目前的所有转换方法。当然对于.NET框架来说,还可使用Convert和Text类进行不同数据类型以及字符编码之间的相互转换。
财,软联盟,fs119.net

财 软联盟 fs119.net

财软,联盟,fs119.net


上一篇:在managedC应用中使用ADO.NET
下一篇:VC.NET2003代码优化方法

精品课程推荐