CString與LPCWSTR、LPSTR、char*、LPWSTR等型別的轉換以及CString和LPCTSTR的關係
一.CString與LPCWSTR
LPCWSTR 是Unicode字串指標,初始化時串有多大,申請空間就有多大,以後存貯若超過則出現無法預料的結果,這是它與CString的不同之處。
CString是一個串類,記憶體空間類會自動管理。
CString轉換成LPCWSTR
Cstring str;
方法一:(只適用於UNICODE字符集)
LPWSTR lpstr = (LPWSTR)(LPCWSTR)str;
方法er(只適用於ANSI字符集)
CString str=_T("TestStr");
USES_CONVERSION;
LPCWSTR lpcwStr = A2CW((LPCSTR)str);
Cstring和LPCTSTR可以通用,在使用ANSI字符集時,LPCTSTR == LPCSTR
A2CW表示(LPCSTR) -> (LPCWSTR)
USER_CONVERSION表示用來定義一些中間變數,在使用ATL的轉換巨集之前必須定義該語句。
LPCWSTR轉換成CString(通用)
LPCWSTR lpcwStr = L"TestWStr";
CString str(lpcwStr);//使用Cstring的建構函式,傳入lpcsStr時,構造臨時物件
CString轉換成LPWSTR(通用)
LPWSTR lpcwStr = str.AllocSysString();//返回Whart_t*
二.CString與LPSTR轉換
LPSTR是ANSI字串指標
CString轉換成LPSTR:
方法一:(只使用於ANSI字符集):
CString strFileName;
LPSTR lpStr = (LPSTR)(LPCSTR)strFileName;
方法二(通用):
CString strFileName;
LPSTR lpStr = strFileName.GetBuffer();//ANSI
或
LPWSTR lpStr = strFileName.GetBuffer();//UICODE
strFileName.ReleaseBuffer();//注意釋放Buffer
//GetBuffer返回PXSTR(LPTSTR),不是Const常量,
LPSTR轉換成CString:
LPSTR lpStr = _T("TestStr"); //ANSI
CString str(lpStr);//使用Cstring的建構函式,傳入lpStr時,構造臨時物件
三.CString和char*轉換
CString轉換成char*
方法一(適用於ANSI字符集):
CString str;
char* p = str.GetBuffer();//返回LPTSTR
str.ReleaseBuffer();
不給 GetBuffer 傳遞引數時,它使用預設值 0,意思是:“給我這個字串的指標,我保證不加長它”。假設你想增加字串的長度,就必須將你需要的字元空間大小(注意:Getbuffer字元而不是位元組,因為 CString 是以隱含方式感知 Unicode 的)傳給它。當呼叫 ReleaseBuffer 時,字串的實際長度會被重新計算,然後存入CString 物件中。
在 GetBuffer 和 ReleaseBuffer 之間這個範圍,一定不能使用你要操作的這個緩衝的 CString 物件的任何方法。因為 ReleaseBuffer 被呼叫之前,該 CString 物件的完整性得不到保障。
LPTSTR p = s.GetBuffer();
// do something with p
int m = s.GetLength(); // 可能出錯!!!
s.ReleaseBuffer();
int n = s.GetLength(); // 正確!!!
方法二(適用於ANSI字符集):
CString str;
char* p = (LPSTR)(LPCSTR)str;
char*轉換成CString
char* p = "test";
CString str = ("%s",p);//或 Cstring str(p);
四.CString和LPCTSTR互換
ANSI模式下,const char* 等價於LPCTSTR,即轉換Cstring到const Char*即可.
UNICODE模式下,const wchar_t*等價於LPCTSTR,即轉換Cstring到Const Char*即可.
CString 轉LPCTSTR
C++編譯器自動呼叫CString過載的操作符 LPCTSTR()來進行隱式的型別轉換
CString cStr;
const char *lpctStr 或 const wchar_t * lpctstr=(LPCTSTR)cStr;
LPCTSTR轉CString C++編譯器則自動呼叫CString的建構函式來構造臨時的CString物件
LPCTSTR lpctStr;
CString cStr=lpctStr;//Cstring cStr(lpctStr);
轉載內容:
五.String和int、float的轉換
可以使用atoi,atof,atol等函式來完成。
六.LPSTR(char*)和LPWSTR的轉換
可以使用下面的ATL巨集來進行,最好是將變數定義成TCHAR、LPTSTR等T型別,可以避免轉換。
ATL巨集介紹:
A2BSTR OLE2A T2A W2A
A2COLE OLE2BSTR T2BSTR W2BSTR
A2CT OLE2CA T2CA W2CA
A2CW OLE2CT T2COLE W2COLE
A2OLE OLE2CW T2CW W2CT
A2T OLE2T T2OLE W2OLE
A2W OLE2W T2W W2T
A :ANSI 字串,也就是 MBCS。
W、OLE 寬字串,也就是 UNICODE。
T 中間型別T。如果定義了 _UNICODE,則T表示W;如果定義了 _MBCS,則T表示A
C const 的縮寫
利用這些巨集,可以快速的進行各種字元間的轉換。使用前必須包含標頭檔案,並且申明USER_CONVERSION;使用 ATL 轉換巨集,由於不用釋放臨時空間,所以使用起來非常方便。但是考慮到棧空間的尺寸(VC 預設2M),使用時要注意幾點:
1、只適合於進行短字串的轉換;
2、不要試圖在一個次數比較多的迴圈體內進行轉換;
3、不要試圖對字元型檔案內容進行轉換,因為檔案尺寸一般情況下是比較大的;
4、對情況 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();
void Func1(LPSTR lpStr);
void Func2(LPWSTR lpwStr);
TCHAR name[256];
TCHAR* pName = new TCHAR[256];
Func1(name); // Func1(pName);
Func2(name); // Func2(pName);
在VS2005中適用於ANSI的程式碼已經不成立。
VS2005中CString已經改為寬字元型,一些轉換如下:
char name[10];
TCHAR sex[5] ;
char *p = name;
TCHAR *pw = sex;
LPSTR lpstr = name;
LPCSTR lpcstr = name;
lpcstr = lpstr;
lpstr = p;
p = (char*)sex;
pw = (WCHAR*)name;
LPWSTR lpwstr = (LPWSTR)lpstr;
lpwstr = (LPWSTR)lpcstr;
LPCWSTR lpcwstr = (LPCWSTR)lpstr;
lpcwstr = (LPCWSTR)name;
CString str(lpstr);
CString str1(lpcstr);
CString str2(lpwstr);
CString str3(lpcwstr);
CString str4(name);
CString str5(sex);
lpwstr = (LPWSTR)(LPCWSTR)str;
lpstr = (LPSTR)(LPCWSTR)str;
lpcstr = (LPCSTR)(LPCWSTR)str;
p = (char*)str.GetBuffer();
pw = str.GetBuffer();
可以看出轉換更加簡單了,基本上可以直接轉換,A2W等巨集基本上不需要啦
CString和LPCTSTR的關係
型別理解LPCTSTR型別:
L表示long指標 這是為了相容Windows 3.1等16位作業系統遺留下來的,在win32中以及其他的32位作業系統中, long指標和near指標及far修飾符都是為了相容的作用。沒有實際意義。
P表示這是一個指標
C表示是一個常量
T表示在Win32環境中, 有一個_T巨集
STR表示這個變數是一個字串 詳細釋義 這個巨集用來表示你的字元是否使用UNICODE, 如果你的程式定義了UNICODE或者其他相關的巨集,那麼這個字元或者字串將被作為UNICODE字串,否則就是標準的ANSI字串。
所以LPCTSTR就表示一個指向常固定地址的可以根據一些巨集定義改變語義的字串。
在程式中我們大部分時間要使用帶T的型別定義。
LPCTSTR == Const TCHAR *
CString 和 LPCTSTR 可以說通用。 原因在於CString定義的自動型別轉換,沒什麼奇特的,最簡單的C++操作符過載而已。
常量字串ansi和unicode的區分是由巨集_T來決定的。但是用_T("abcd")時, 字串"abcd"就會根據編譯時的是否定一_UNICODE來決定是char* 還是 w_char*。 同樣,TCHAR 也是相同目的字元巨集。 看看定義就明白了。
簡單起見,下面只介紹 ansi 的情況,unicode 可以類推。
ANSI字符集時,LPCTSTR 就是 const char*, 是常量字串(不能修改的)。
而LPTSTR 就是 char*, 即普通字串(非常量,可修改的)。 UNICODE字符集時,LPCTSTR 就是 const wchar_t*, 是常量字串(不能修改的)。
而LPTSTR 就是 wchar_t*, 即普通字串(非常量,可修改的)。
這兩種都是基本型別, 而CString 是 C++類, 相容這兩種基本型別是最起碼的任務了。
由於const char* 最簡單(常量,不涉及記憶體變更,操作迅速), CString 直接定義了一個型別轉換函式:
operator LPCTSTR( )
{.
.....
}
函式直接返回所維護的字串。
當你需要一個const char* 而傳入了CString時, C++編譯器自動呼叫 CString過載的操作符 LPCTSTR()來進行隱式的型別轉換。
當需要CString , 而傳入了 const char* 時(其實 char* 也可以),C++編譯器則自動呼叫CString的建構函式來構造臨時的 CString物件。
因此CString 和 LPCTSTR 基本可以通用。
但是 LPTSTR又不同了,它是 char*, 意味著你隨時可能修改裡面的資料,這就需要記憶體管理了(如字串變長,原來的存貯空間就不夠了,則需要重新調整分配記憶體)。
所以 不能隨便的將 const char* 強制轉換成 char* 使用。
例如:
LPSTR lpstr = (LPSTR)(LPCTSTR)string; 就是這種不安全的使用方法。
這個地方使用的是強制型別轉換,你都強制轉換了,C++編譯器當然不會拒絕你,但同時他也認為你確實知道自己要做的是什麼。因此是不會給出警告的。
強制的任意型別轉換是C(++)的一項強大之處,但也是一大弊端。這一問題在 vc6 以後的版本(僅針對vc而言)中得到逐步的改進(你需要更明確的型別轉換宣告)。
其實在很多地方都可以看到類似 LPSTR lpstr = (LPSTR)(LPCTSTR)string; 的用法,這種情況一般是函式的約束定義不夠完善的原因, 比如一個函式接受一個字串引數的輸入,裡面對該字串又沒有任何的修改,那麼該引數就應該定義成 const char*, 但是很多初學者弄不清const地用法,或者是懶, 總之就是隨意寫成了 char* 。 這樣子傳入CString時就需要強制的轉換一下。
這種做法是不安全的,也是不被建議的用法,你必須完全明白、確認該字串沒有被修改。
CString 轉換到 LPTSTR (char*), 預定的做法是呼叫CString的GetBuffer函式,使用完畢之後一般都要再呼叫ReleaseBuffer函式來確認修改 (某些情況下也有不呼叫ReleaseBuffer的,同樣你需要非常明確為什麼這麼做時才能這樣子處理,一般應用環境可以不考慮這種情況)。
同時需要注意的是, 在GetBuffer 和 ReleaseBuffer之間,CString分配了記憶體交由你來處理,因此不能再呼叫其他的CString函式。