Visual C++.NET中 字串轉換方法

來源:互聯網
上載者:User
Visual C++.NET中 字串轉換方法[1]
2002-12-06 14:48:39

丁有和

 
 Visual C++.NET涉及到ATL/ATL
Server、MFC和託管C++等多種編程方式,不僅功能強大而且應用廣泛。在編程中,我們常常會遇到ANSI、Unicode以及BSTR不同編碼類別
型的字串轉換操作。本文先介紹基底字元串類型,然後說明相關的類,如CComBSTR、_bstr_t、CStringT等,最後討論它們的轉換方法,
其中還包括使用最新ATL7.0的轉換類和宏,如CA2CT、CA2TEX等。

  一、BSTR、LPSTR和LPWSTR

  在Visual
C++.NET的所有編程方式中,我們常常要用到這樣的一些基底字元串類型,如BSTR、LPSTR和LPWSTR等。之所以出現類似上述的這些資料類型,是因為不同程式設計語言之間的資料交換以及對ANSI、Unicode和多位元組字元集(MBCS)的支援。

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

 
 BSTR(Basic
STRing,Basic字串)是一個OLECHAR*類型的Unicode字串。它被描述成一個與自動化相相容的類型。由於作業系統提供相應的
API函數(如SysAllocString)來管理它以及一些預設的調度代碼,因此BSTR實際上就是一個COM字串,但它卻在自動化技術以外的多種
場合下得到廣泛使用。圖1描述了BSTR的結構,其中DWORD值是字串中實際所佔用的位元組數,且它的值是字串中Unicode字元的兩倍。

 
 LPSTR和LPWSTR是Win32和VC++所使用的一種字串資料型別。LPSTR被定義成是一個指向以NULL(‘\0’)結尾的8位ANSI
字元數組指標,而LPWSTR是一個指向以NULL結尾的16位雙位元組字元數組指標。在VC++中,還有類似的字串類型,如LPTSTR、
LPCTSTR等,它們的含義2所示。

  例如,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++.NET中將CStringT作為ATL和MFC的共用的“一般”字串類,它有CString、CStringA和CStringW三種形式,分
別操作不同字元類型的字串。這些字元類型是TCHAR、char和wchar_t。TCHAR在Unicode平台中等同於WCHAR(16位
Unicode字元),在ANSI中等價於char。wchar_t通常定義為unsigned
short。由於CString在MFC應用程式中經常用到,這裡不再重複。

  三、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));
// 定義長度為5
wcscpy(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)類型,常常使用下列三種方法:

  方法一,使用強制轉換。例如:

CString theString( "This is a test" );
LPTSTR lpsz
=(LPTSTR)(LPCTSTR)theString; 

  方法二,使用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),系統編譯器將會自動對其進行轉換。

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

CString s(_T("This is a test "));
LPTSTR p =
s.GetBuffer();
// 在這裡添加使用p的代碼
if(p != NULL) *p =
_T('\0');
s.ReleaseBuffer();
//
使用完後及時釋放,以便能使用其它的CString成員函數

  (3) BSTR轉換成char*

  方法一,使用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;

  方法二,使用_bstr_t的賦值運算子多載。例如:

_bstr_t b = bstrText;
char* lpszText2 = b;

  (4) char*轉換成BSTR

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

BSTR bstrText = ::SysAllocString(L"Test");
BSTR bstrText
= ::SysAllocStringLen(L"Test",4);
BSTR bstrText =
::SysAllocStringByteLen("Test",4);

  方法二,使用COleVariant或_variant_t。例如:

//COleVariant strVar("This is a test");
_variant_t
strVar("This is a test");
BSTR bstrText = strVar.bstrVal;

  方法三,使用_bstr_t,這是一種最簡單的方法。例如:

BSTR bstrText = _bstr_t("This is a test");

  方法四,使用CComBSTR。例如:

BSTR bstrText = CComBSTR("This is a test");

  或

CComBSTR bstr("This is a test");
BSTR bstrText =
bstr.m_str;

  方法五,使用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字元。

  方法二,使用“_T”將ANSI轉換成“一般”類型字串,使用“L”將ANSI轉換成Unicode,而在託管C++環境中還可使用S將ANSI字串轉換成String*對象。例如:

TCHAR tstr[] = _T("this is a test");
wchar_t wszStr[] =
L"This is a test";
String* str = S”This is a test”;

  方法三,使用ATL
7.0的轉換宏和類。ATL7.0在原有3.0基礎上完善和增加了許多字串轉換宏以及提供相應的類,它具有3所示的統一形式:

 
 其中,第一個C表示“類”,以便於ATL
3.0宏相區別,第二個C表示常量,2表示“to”,EX表示要開闢一定大小的緩衝。SourceType和DestinationType可以是A、
T、W和OLE,其含義分別是ANSI、Unicode、“一般”類型和OLE字串。例如,CA2CT就是將ANSI轉換成一般類型的字串常量。下面
是一些範例程式碼:

LPTSTR tstr= CA2TEX<16>("this is a test");
LPCTSTR
tcstr= CA2CT("this is a test");
wchar_t wszStr[] = L"This
is a test";
char* chstr = CW2A(wszStr); 

  六、結語

  幾乎所有的程式都要用到字串,而Visual
C++.NET由於功能強大、應用廣泛,因而字串之間的轉換更為頻繁。本文幾乎涉及到目前的所有轉換方法。當然對於.NET架構來說,還可使用Convert和Text類進行不同資料類型以及字元編碼之間的相互轉換。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.