1. 程式人生 > >VS中遇到的 UNICODE和ANSI 編碼問題

VS中遇到的 UNICODE和ANSI 編碼問題

以前編碼問題總能讓自己湊或蒙過去,最近要做一個專案伺服器端用python寫,客戶端用c++,工程編譯的字符集使用UNICODE。之間通過socket進行通訊,通訊過程中編碼轉換問題把我搞得暈頭轉向,逼著我將編碼問題好好研究一番。

首先先談談VC中的編碼問題,首先編碼我們大致可以分為兩類:檔案編碼和記憶體編碼。檔案編碼即原始碼檔案的編碼,gbk,UTF-8等。記憶體編碼即原始碼編譯成為二進位制檔案的時候採用的編碼。


比如,在VC 2008中我們寫下如下的程式碼:


char* a = “a中”;


讓我們分別來看一下檔案編碼和記憶體編碼的區別。


用UntraEdit開啟該cpp檔案,進入十六進位制模式:我們可以看到”a中”對應的編碼為:0×61 0xD6 0xD0,0×61是ASCII碼中的a,0xD6 0xD0是GBK裡”中”的編碼。說明,在中文windows環境下,VC建立的檔案編碼預設是GBK的。那麼我們將檔案修改為UTF-8的編碼格式,重新用UE以十六進位制模式進入。我們看到”a中”的編碼變為了0×61 0xE4 0xB8 0xAD,0×61仍然是a的編碼,而中的編碼變成了,0xE4 0xB8 0xAD。


從上面的試驗我們還可以知道,GBK中中文為2個位元組,UTF-8是3個位元組。

下面我們研究一下記憶體編碼,記憶體編碼在VC中只有3個選項:Not Set,Use Multi-Byte Character Set和Use Unicode Character Set。這個屬性的修改可以在工程的屬性欄中找到:

讓我們繼續觀察上面的例子。來檢視一下什麼是記憶體編碼。我們在程式中設定斷點,除錯程式來觀察在程式執行過程中,三種工程屬性下,char* a所指向的那篇記憶體空間的值是什麼,是不是如我們所認為的那樣:


工程屬性
 Not Set
 Use Multi-Byte Character Set
 Use Unicode Character Set
 
記憶體
 0×61 0xd6 0xd0
 0×61 0xd6 0xd0
 0×61 0xd6 0xd0
 

如上表所示,無論工程屬性如何設定,”中”在記憶體中都是gbk編碼。這樣的程式拿到非中文的作業系統中執行是會出現亂碼的,那麼怎麼才能將其用UNICODE進行編碼呢?我們需要用到wchar_t這個型別,wchar_t是一種寬字型別,寬字型別的變數使用方法如下wchar_t* a = L”a中”;即在”a中”前面加上L。


現在,除錯一下可以看到,a在記憶體中的值為0×61 0×00 0×2d 0×4e。wchar_t型別的變數會將用兩個位元組儲存英文變數,即在原有ASCII的基礎上補上兩個0.而後面的0×2d 0×4e就是”中”的編碼。


這樣,變數a就在多種語言平臺上都可以正確顯示了。那麼,工程屬性中的三種字符集選項有什麼作用呢?


讓我們引用MSDN中的原文:


Generic-text


data type name
 SBCS (_UNICODE,


_MBCS not


defined)
 _MBCS


defined
 _UNICODE


defined
 
_TCHAR
 char
 char
 wchar_t
 
_tfinddata_t
 _finddata_t
 _finddata_t
 _wfinddata_t
 
_tfinddata64_t
 __finddata64_t
 __finddata64_t
 __wfinddata64_t
 
_tfinddatai64_t
 _finddatai64_t
 _finddatai64_t
 _wfinddatai64_t
 
_TINT
 int
 int
 wint_t
 
_TSCHAR
 signed char
 signed char
 wchar_t
 
_TUCHAR
 unsigned char
 unsigned char
 wchar_t
 
_TXCHAR
 char
 unsigned char
 wchar_t
 
_T or _TEXT
 No effect (removed by preprocessor)
 No effect (removed by preprocessor)
 L (converts following character or string to its Unicode counterpart)
 

SBCS、_MBCS和_UNICODE是三個巨集,會分別在設定了Not Set、Use Multi-Byte Character Set、Use Unicode Character Set的時候定義。為了程式的可移植性,我們通常不會直接使用wchar_t和L,而是使用TCHAR和T()。這樣,在工程屬性設定不同的情況下,TCHAR和T()會被解釋為不同的內容。


同樣,我們以前測試字串長度的函式strlen也不要直接使用,為了可移植性,我們通常使用_tcslen或者_tcsclen。

TCHAR.H routine
 _UNICODE & _MBCS not defined
 _MBCS defined
 _UNICODE defined
 
_tcslen
 strlen
 strlen
 wcslen
 
_tcsclen
 strlen
 _mbslen
 wcslen
 
_tcsclen_l
 strlen_l
 _mbslen_l
 wcslen_l
 

那麼現在的問題是,我想要把資料經過網路傳輸,現在是否可以直接傳輸wchar_t*的變數呢,答案是不行的,因為wchar_t*的字串的英文字元表示中存在00,中文英文都用兩個byte。這樣既浪費空間又可能會導致網路的錯誤。因此我們需要先將其轉換成char*的那種型別,即,英文用一個byte,中文用兩個byte。怎麼轉換呢?要使用MultiByteToWideChar和WideCharToMultiByte來互相進行轉換。轉換完了之後再通過網路傳輸。

好了,現在資料到了Python端,想想看,現在Python端收到的是什麼編碼?對,中文是gbk的編碼。然後我們為了在python端實現國際化,要將gbk轉化成unicode。方法很簡單,首先先用


s = struct.unpack(’s’,mysocket.recv(2))來接收一箇中文字,然後呼叫s.decode(”gbk”)來將編碼轉化成為unicode編碼。這樣,編碼問題就完全解決了~

VC++.NET中字串之間的轉換
2007-09-28 20:51
一、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);
 


一.               VC常用資料型別列表

二.               常用資料型別轉化

2.1數學型別變數與字串相互轉換

2.2 CString及string,char *與其他資料型別的轉換和操作

●CString,string,char*的綜合比較

●數學型別與CString相互轉化

●CString與char*相互轉換舉例

●CString 與 BSTR 型轉換

●VARIANT 型轉化成 CString 型

2.3 BSTR、_bstr_t與CComBSTR

2.4 VARIANT 、_variant_t 與 COleVariant

附錄CString及字串轉及操作詳解

參考書籍:CSDN,<<MFC深入淺出(Second Edit)>>

                              一.VC常用資料型別列表

 Type
 Default Size
 Description
 


 說明:這些基礎資料型別對於MFC還是API都是被支援的
 
boolean
 unsigned 8 bit ,
 取值TRUE/FALSE
 
byte
 unsigned 8 bit,
 整數,輸出按字元輸出
 
char
 unsigned 8 bit,
 字元
 
double
 signed 64 bit
 浮點型
 
float
 signed32 bit
 浮點型
 
handle_t
  Primitive handle type
 
hyper
 signed 64 bit
 整型
 
int
 signed 32 bit
 整型
 
long
 signed 32 bit
 整型
 
short
 signed 16 bit
 整型
 
small
 signed 8 bit
 整型
 
void *
 32-bit
 指向未知型別的指標
 
wchar_t
 unsigned 16 bit
 16位字元,比char可容納更多的字元
 
  
Win32

API


 說明: 這些Win32API支援的簡單資料型別主要是用來定義函式返回值,訊息引數,結構成員。這類資料型別大致可以分為五大類:字元型、布林型、整型、指標型和控制代碼型(?). 總共大概有100多種不同的型別,
 
BOOL/BOOLEAN
 8bit,TRUE/FALSE
 布林型
 
BYTE
 unsigned 8 bit
 
BSTR

CComBSTR

_bstr_t
 32 bit
 BSTR是指向字串的32位指標

是對BSTR的封裝

是對BSTR的封裝
 
CHAR
 8 bit
 (ANSI)字元型別
 
COLORREF
 32 bit
 RGB顏色值 整型
 
DWORD
 unsigned 32 bit
 整型
 
FLOAT
 float型
 float型
 
HANDLE
  Object控制代碼
 
HBITMAP
  bitmap控制代碼
 
HBRUSH
  brush控制代碼
 
HCURSOR
  cursor控制代碼
 
HDC
  裝置上下文控制代碼
 
HFILE
  OpenFile開啟的File控制代碼
 
HFONT
  font控制代碼
 
HHOOK
  hook控制代碼
 
HKEY
  登錄檔鍵控制代碼
 
HPEN
  pen控制代碼
 
HWND
  window控制代碼
 
INT
 --------
 --------
 
LONG
 --------
 ---------
 
LONGLONG
  64位帶符號整型
 
LPARAM
 32 bit
 訊息引數
 
LPBOOL
  BOOL型指標
 
LPBYTE
  BYTE型指標
 
LPCOLOREF
  COLORREF型指標
 
LPCSTR/LPSTR/PCSTR
  指向8位(ANSI)字串型別指標
 
LPCWSTR/LPWSTR/PCWSTR
  指向16位Unicode字串型別
 
LPCTSTR/LPTSTR/PCTSTR
  指向一8位或16位字串型別指標
 
LPVOID
  指向一個未指定型別的32位指標
 
LPDWORD
  指向一個DWORD型指標
 
其他相似型別: LPHANDLE、LPINT、LPLONG、LPWORD、LPRESULT

PBOOL、PBOOLEAN、PBYTE、PCHAR、PDWORD、PFLOAT、PHANDLE、PINT、PLONG、PSHORT……

說明:(1)在16位系統中 LP為16bit,P為8bit,在32位系統中都是32bit(此時等價)

(2)LPCSTR等 中的C指Const,T表示TCHAR模式即可以工作在ANSI下也可UNICODE
 
SHORT
 usigned
 整型
 
其他UCHAR、UINT、ULONG、ULONGLONG、USHORT為無符號相應型別
 
TBYTE
  WCHAR型或者CHAR型
 
TCHAR
  ANSI與unicode均可
 
VARIANT

_variant_t

COleVariant
  一個結構體參考OAIDL.H

_variant_t是VARIANT的封裝類

COleVariant也是VARIANT的封裝類
 
  
  
WNDPROC
  指向一個視窗過程的32位指標
 
WCHAR
  16位Unicode字元型
 
WORD
  16位無符號整型
 
WPARAM
  訊息引數
 
MFC

獨有

資料

型別
 下面兩個資料型別是微軟基礎類庫中獨有的資料型別
 
POSITION
 標記集合中一個元素的位置的值,被MFC中的集合類所使用
 
LPCRECT
 指向一個RECT結構體常量(不能修改)的32位指標
 
CString
 其實是MFC中的一個類
 
  

說明:

(1)-------表示省略

(2)1Byte=8Bit,

字與機器有關,在8位系統中:字=1位元組,16位系統中,1字=2位元組,32位中:1字=4位元組,

64位中1字=8位元組.不要搞混這些概念.

二.常用資料型別轉化及操作

2.1 數學型別變數與字串相互轉換(這些函式都在STDLIB.H裡)

(1)將數學型別轉換為字串可以用以下一些函式:

舉例: _CRTIMP char * __cdecl _itoa(int, char *, int);//這是一個將數字轉換為一個字串型別的函式,最後一個int表示轉換的進位制

如以下程式:

int iTyep=3;

char *szChar;

itoa(iType,szChar,2);

cout<<szChar;//輸出為1010

類似函式列表:

_CRTIMP char * __cdecl _itoa(int, char *, int);//為了完整性,也列在其中

_CRTIMP char * __cdecl _ultoa(unsigned long, char *, int);

_CRTIMP char * __cdecl _ltoa(long, char *, int);

_CRTIMP char * __cdecl _i64toa(__int64, char *, int);

_CRTIMP char * __cdecl _ui64toa(unsigned __int64, char *, int);

_CRTIMP wchar_t * __cdecl _i64tow(__int64, wchar_t *, int);

_CRTIMP wchar_t * __cdecl _ui64tow(unsigned __int64, wchar_t *, int);

_CRTIMP wchar_t * __cdecl _itow (int, wchar_t *, int);//轉換為長字串型別

_CRTIMP wchar_t * __cdecl _ltow (long, wchar_t *, int);

_CRTIMP wchar_t * __cdecl _ultow (unsigned long, wchar_t *, int);

還有很多,請自行研究

(2)將字串型別轉換為數學型別變數可以用以下一些函式:

舉例: _CRTIMP int   __cdecl atoi(const char *);//引數一看就很明瞭

char *szChar=”88”;

int temp(0);

temp=atoi(szChar);

cout<<temp;

類似的函式列表:

_CRTIMP int     __cdecl atoi(const char *);

_CRTIMP double __cdecl atof(const char *);

_CRTIMP long    __cdecl atol(const char *);

_CRTIMP long double __cdecl _atold(const char *);

_CRTIMP __int64 __cdecl _atoi64(const char *);

_CRTIMP double __cdecl strtod(const char *, char **);//

_CRTIMP long    __cdecl strtol(const char *, char **, int);//

_CRTIMP long double __cdecl _strtold(const char *, char **);

_CRTIMP unsigned long __cdecl strtoul(const char *, char **, int);

_CRTIMP double __cdecl wcstod(const wchar_t *, wchar_t **);//長字串型別轉換為數學型別

_CRTIMP long    __cdecl wcstol(const wchar_t *, wchar_t **, int);

_CRTIMP unsigned long __cdecl wcstoul(const wchar_t *, wchar_t **, int);

_CRTIMP int __cdecl _wtoi(const wchar_t *);

_CRTIMP long __cdecl _wtol(const wchar_t *);

_CRTIMP __int64    __cdecl _wtoi64(const wchar_t *);

還有很多,請自行研究

2.2.CString及string,char *與其他資料型別的轉換和操作

(1)CString,string,char*的綜合比較(這部分CSDN上的作者joise的文章

<< CString,string,char*的綜合比較>>寫的很詳細,請大家在仔細閱讀他的文章.

或參考附錄:

(2)轉換:

●數學型別與CString相互轉化

數學型別轉化為CString

可用Format函式,舉例:

CString s;

int i = 64;

s.Format("%d", i)

CString轉換為數學型別:舉例CString strValue("1.234");

double dblValue;

dblValue = atof((LPCTSTR)strValue);

●CString與char*相互轉換舉例

CString strValue(“Hello”);

char *szValue;

szValue=strValue.GetBuffer(szValue);

也可用(LPSTR)(LPCTSTR)對CString//   進行強制轉換. 

szValue=(LPSTR)(LPCTSTR)strValue;

反過來可直接賦值:

char *szChar=NULL;

CString strValue;

szChar=new char[10];

memset(szChar,0,10);

strcpy(szChar,”Hello”);

strValue=szChar;

●CString 與 BSTR 型轉換

CString 型轉化成 BSTR 型

當我們使用 ActiveX 控制元件程式設計時,經常需要用到將某個值表示成 BSTR 型別.BSTR 是一種記數字符串,Intel平臺上的寬字串(Unicode),並且可以包含嵌入的 NULL 字元。

可以呼叫 CString 物件的 AllocSysString 方法將 CString 轉化成 BSTR:

CString str;

str = .....; // whatever

BSTR bStr = str.AllocSysString();

BSTR型轉換為CString

如果你在 UNICODE 模式下編譯程式碼,你可以簡單地寫成:

CString convert(BSTR bStr)

{

     if(bStr == NULL)

         return CString(_T(""));

     CString s(bStr); // in UNICODE mode

     return s;

}

如果是 ANSI 模式

CString convert(BSTR b)

{

     CString s;

     if(b == NULL)

        return s; // empty for NULL BSTR

#ifdef UNICODE

     s = b;

#else

     LPSTR p = s.GetBuffer(SysStringLen(b) + 1);

     ::WideCharToMultiByte(CP_ACP,             // ANSI Code Page

                           0,                  // no flags

                           b,                  // source widechar string

                           -1,                 // assume NUL-terminated

                           p,                  // target buffer

                           SysStringLen(b)+1, // target buffer length

                           NULL,               // use system default char

                           NULL);              // don''t care if default used

     s.ReleaseBuffer();

#endif

     return s;

}

●VARIANT 型轉化成 CString 型

VARIANT 型別經常用來給 COM 物件傳遞引數,或者接收從 COM 物件返回的值。你也能自己編寫返回 VARIANT 型別的方法,函式返回什麼型別 依賴可能(並且常常)方法的輸入引數(比如,在自動化操作中,依賴與你呼叫哪個方法。IDispatch::Invoke 可能返回(通過其一個引數)一個 包含有BYTE、WORD、float、double、date、BSTR 等等 VARIANT 型別的結果,(詳見 MSDN 上的 VARIANT 結構的定義)。在下面的例子中,假設 型別是一個BSTR的變體,也就是說在串中的值是通過 bsrtVal 來引用,其優點是在 ANSI 應用中,有一個建構函式會把 LPCWCHAR 引用的值轉換為一個 CString(見 BSTR-to-CString 部分)。在 Unicode 模式中,將成為標準的 CString 建構函式,參見對預設::WideCharToMultiByte 轉換的告誡,以及你覺得是否可以接受(大多數情況下,你會滿意的)。VARIANT vaData;

vaData = m_com.YourMethodHere();

ASSERT(vaData.vt == VT_BSTR);

CString strData(vaData.bstrVal);

你還可以根據 vt 域的不同來建立更通用的轉換例程。為此你可能會考慮:

CString VariantToString(VARIANT * va)

{

     CString s;

     switch(va->vt)

       { /* vt */

        case VT_BSTR:

           return CString(vaData->bstrVal);

        case VT_BSTR | VT_BYREF:

           return CString(*vaData->pbstrVal);

        case VT_I4:

           s.Format(_T("%d"), va->lVal);

           return s;

        case VT_I4 | VT_BYREF:

           s.Format(_T("%d"), *va->plVal);

        case VT_R8:

           s.Format(_T("%f"), va->dblVal);

           return s;

        ... 剩下的型別轉換由讀者自己完成

        default:

           ASSERT(FALSE); // unknown VARIANT type (this ASSERT is optional)

           return CString("");

       } /* vt */

}

2.3 BSTR、_bstr_t與CComBSTR

CComBSTR、_bstr_t是對BSTR的封裝,BSTR是指向字串的32位指標。

char *轉換到BSTR可以這樣:

BSTR b=_com_util::ConvertStringToBSTR("資料");///使用前需要加上標頭檔案comutil.h

反之可以使用char *p=_com_util::ConvertBSTRToString(b);

2.4(引)VARIANT 、_variant_t 與 COleVariant

VARIANT的結構可以參考標頭檔案VC98/Include/OAIDL.H中關於結構體tagVARIANT的定義。

對於VARIANT變數的賦值:首先給vt成員賦值,指明資料型別,再對聯合結構中相同資料型別的變數賦值,舉個例子:

VARIANT va;

int a=2001;

va.vt=VT_I4;///指明整型資料

va.lVal=a; ///賦值

對於不馬上賦值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);進行初始化,其本質是將vt設定為VT_EMPTY,下表我們列舉vt與常用資料的對應關係:

unsigned char bVal; VT_UI1

short iVal; VT_I2

long lVal; VT_I4

float fltVal; VT_R4

double dblVal; VT_R8

VARIANT_BOOL boolVal; VT_BOOL

SCODE scode; VT_ERROR

CY cyVal; VT_CY

DATE date; VT_DATE

BSTR bstrVal; VT_BSTR

IUnknown FAR* punkVal; VT_UNKNOWN

IDispatch FAR* pdispVal; VT_DISPATCH

SAFEARRAY FAR* parray; VT_ARRAY|*

unsigned char FAR* pbVal; VT_BYREF|VT_UI1

short FAR* piVal; VT_BYREF|VT_I2

long FAR* plVal; VT_BYREF|VT_I4

float FAR* pfltVal; VT_BYREF|VT_R4

double FAR* pdblVal; VT_BYREF|VT_R8

VARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL

SCODE FAR* pscode; VT_BYREF|VT_ERROR

CY FAR* pcyVal; VT_BYREF|VT_CY

DATE FAR* pdate; VT_BYREF|VT_DATE

BSTR FAR* pbstrVal; VT_BYREF|VT_BSTR

IUnknown FAR* FAR* ppunkVal; VT_BYREF|VT_UNKNOWN

IDispatch FAR* FAR* ppdispVal; VT_BYREF|VT_DISPATCH

SAFEARRAY FAR* FAR* pparray; VT_ARRAY|*

VARIANT FAR* pvarVal; VT_BYREF|VT_VARIANT

void FAR* byref; VT_BYREF

_variant_t是VARIANT的封裝類,其賦值可以使用強制型別轉換,其建構函式會自動處理這些資料型別。

例如:

long l=222;

ing i=100;

_variant_t lVal(l);

lVal = (long)i;

COleVariant的使用與_variant_t的方法基本一樣,請參考如下例子:

COleVariant v3 = "字串", v4 = (long)1999;

CString str =(BSTR)v3.pbstrVal;

long i = v4.lVal;