把 CString 類型的數據轉化成整數類型最簡單的方法就是使用標准的字符串到整數轉換例程。
雖然通常你懷疑使用_atoi()函數是一個好的選擇,它也很少會是一個正確的選擇。如果你准備使用 Unicode 字符,你應該用_ttoi(),它在 ANSI 編碼系統中被編譯成_atoi(),而在 Unicode 編碼系統中編譯成_wtoi()。你也可以考慮使用_tcstoul()或者_tcstol(),它們都能把字符串轉化成任意進制的長整數(如二進制、八進制、十進制或十六進制),不同點在於前者轉化後的數據是無符號的(unsigned),而後者相反。看下面的例子:
CString hex = _T("FAB"); CString decimal = _T("4011"); ASSERT(_tcstoul(hex, 0, 16) == _ttoi(decimal));
這是初學者使用 CString 時最常見的問題。有了 C++ 的幫助,很多問題你不需要深入的去考慮它,直接拿來用就行了,但是如果你不能深入了解它的運行機制,又會有很多問題讓你迷惑,特別是有些看起來沒有問題的代碼,卻偏偏不能正常工作。
比如,你會奇怪為什麼不能寫向下面這樣的代碼呢:
CString graycat = "Gray" + "Cat"; CString graycat("Gray" + "Cat");
事實上,編譯器將抱怨上面的這些嘗試。為什麼呢?因為針對CString 和 LPCTSTR數據類型的各種各樣的組合,“ +” 運算符被定義成一個重載操作符。而不是兩個 LPCTSTR 數據類型,它是底層數據類型。你不能對基本數據(如 int、char 或者 char*)類型重載 C++ 的運算符。你可以象下面這樣做:
CString graycat = CString("Gray") + CString("Cat");
或者這樣:
CString graycat = CString("Gray") + "Cat";
研究一番就會發現:“ +”總是使用在至少有一個 CString 對象和一個 LPCSTR 的場合。注意,編寫有 Unicode 意識的代碼總是一件好事,比如: CString graycat = CString(_T("Gray")) + _T("Cat"); 這將使得你的代碼可以直接移植。
現在你有一個 char* 類型的數據,或者說一個字符串。怎麼樣創建 CString 對象呢?這裡有一些例子:
char * p = "This is a test";
或者象下面這樣更具有 Unicode 意識:
TCHAR * p = _T("This is a test"); 或 LPTSTR p = _T("This is a test");
你可以使用下面任意一種寫法:
CString s = "This is a test"; // 8-bit only CString s = _T("This is a test"); // Unicode-aware CString s("This is a test"); // 8-bit only CString s(_T("This is a test")); // Unicode-aware CString s = p; CString s(p);
用這些方法可以輕松將常量字符串或指針轉換成 CString。需要注意的是,字符的賦值總是被拷貝到 CString 對象中去的,所以你可以象下面這樣操作:
TCHAR * p = _T("Gray"); CString s(p); p = _T("Cat"); s += p;
結果字符串肯定是“GrayCat”。
CString 類還有幾個其它的構造函數,但是這裡我們不考慮它,如果你有興趣可以自己查看相關文檔。事實上,CString 類的構造函數比我展示的要復雜,比如:
CString s = "This is a test";
這是很草率的編碼,但是實際上它在 Unicode 環境下能編譯通過。它在運行時調用構造函數的 MultiByteToWideChar 操作將 8 位字符串轉換成 16 位字符串。不管怎樣,如果 char * 指針是網絡上傳輸的 8 位數據,這種轉換是很有用的。
CString 轉化成 char* 之一:強制類型轉換為 LPCTSTR;
這是一種略微硬性的轉換,有關“正確”的做法,人們在認識上還存在許多混亂,正確的使用方法有很多,但錯誤的使用方法可能與正確的使用方法一樣多。我們首先要了解 CString 是一種很特殊的 C++ 對象,它裡面包含了三個值:一個指向某個數據緩沖區的指針、一個是該緩沖中有效的字符記數以及一個緩沖區長度。有效字符數的大小可以是從0到該緩沖最大長度值減1之間的任何數(因為字符串結尾有一個NULL字符)。字符記數和緩沖區長度被巧妙隱藏。
除非你做一些特殊的操作,否則你不可能知道給CString對象分配的緩沖區的長度。這樣,即使你獲得了該0緩沖的地址,你也無法更改其中的內容,不能截短字符串,也絕對沒有辦法加長它的內容,否則第一時間就會看到溢出。
LPCTSTR 操作符(或者更明確地說就是 TCHAR * 操作符)在 CString 類中被重載了,該操作符的定義是返回緩沖區的地址,因此,如果你需要一個指向 CString 的 字符串指針的話,可以這樣做:
CString s("GrayCat"); LPCTSTR p = s;
它可以正確地運行。這是由C語言的強制類型轉化規則實現的。當需要強制類型轉化時,C++規測容許這種選擇。比如,你可以將(浮點數)定義為將某個復數(有一對浮點數)進行強制類型轉換後只返回該復數的第一個浮點數(也就是其實部)。
CString轉化成char* 之二:使用 CString 對象的 GetBuffer 方法;
如果你需要修改 CString 中的內容,它有一個特殊的方法可以使用,那就是 GetBuffer,它的作用是返回一個可寫的緩沖指針。 如果你只是打算修改字符或者截短字符串,你完全可以這樣做:
CString s(_T("File.ext")); LPTSTR p = s.GetBuffer(); LPTSTR dot = strchr(p, ''.''); // OK, should have used s.Find... if(p != NULL) *p = _T(''/0''); s.ReleaseBuffer();
這是 GetBuffer 的第一種用法,也是最簡單的一種,不用給它傳遞參數,它使用默認值 0,意思是:“給我這個字符串的指針,我保證不加長它”。當你調用 ReleaseBuffer 時,字符串的實際長度會被重新計算,然後存入 CString 對象中。
必須強調一點,在 GetBuffer 和 ReleaseBuffer 之間這個范圍,一定不能使用你要操作的這個緩沖的 CString 對象的任何方法。因為 ReleaseBuffer 被調用之前,該 CString 對象的完整性得不到保障。研究以下代碼:
CString s(...); LPTSTR p = s.GetBuffer(); //... 這個指針 p 發生了很多事情 int n = s.GetLength(); // 很糟D!!!!! 有可能給出錯誤的答案!!! s.TrimRight(); // 很糟!!!!! 不能保證能正常工作!!!! s.ReleaseBuffer(); // 現在應該 OK int m = s.GetLength(); // 這個結果可以保證是正確的。 s.TrimRight(); // 將正常工作。
假設你想增加字符串的長度,你首先要知道這個字符串可能會有多長,好比是聲明字符串數組的時候用: char buffer[1024]; 表示 1024 個字符空間足以讓你做任何想做得事情。在 CString 中與之意義相等的表示法:LPTSTR p = s.GetBuffer(1024);
調用這個函數後,你不僅獲得了字符串緩沖區的指針,而且同時還獲得了長度至少為 1024 個字符的空間(注意,我說的是“字符”,而不是“字節”,因為 CString 是以隱含方式感知 Unicode 的)。
下面給個MFC CString轉int、double、char類型。
//CString轉int CString szPort = L"2589"; int nPort = _ttoi(szPort); //CString轉double CString szPort = L"2589.00"; double nPort = _ttol(szPort); //其它類型轉CString int nPort = 2589; char ip[32] = "這樣啊"; CString str;str.Empty(); str.Format(_T("%d:%s"), nPort, ip); //CString轉TCHAR* CString cstr(L"hello"); TCHAR *pstr = cstr.GetBuffer(str);
char 與 wchar_t
/*---------------------------------------- File: mr.h 使用宏定義同函數名可以避免修改編譯器編譯環境 -----------------------------------------*/ #pragma once #ifndef MR_H #define MR_H #ifdef UNICODE #define _mrstrncpy wcsncpy #define _mrstrcpy wcscpy #define _mrstrlen wcslen #define _mrstrcat wcscat #define _mrstrcmp wcscmp #else #define _mrstrncpy strncpy #define _mrstrcpy strcpy #define _mrstrlen strlen #define _mrstrcat strcat #define _mrstrcmp strcmp #endif #endif