CString位於頭文件afx.h中。
CString 是一種很有用的數據類型。它們很大程度上簡化了MFC中的許多操作,使得MFC在做字符串操作的時候方便了很多。不管怎樣,使用CString有很多特殊的技巧,特別是對於純C背景下走出來的程序員來說有點難以學習。這篇文章就來討論這些技巧。
使用CString可以讓你對字符串的操作更加直截了當。這篇文章不是CString的完全手冊,但囊括了大部分常見基本問題。
這篇文章包括以下內容:
CString 對象的連接
格式化字符串(包括 int 型轉化爲 CString )
CString 型轉化成 int 型
CString 型和 char* 類型的相互轉化
char* 轉化成 CString
CString 轉化成 char* 之一:使用LPCTSTR強制轉化
CString 轉化成 char* 之二:使用CString對象的GetBuffer方法
CString 轉化成 char* 之三: 和控件的接口
CString 型轉化成 BSTR 型;
BSTR 型轉化成 CString 型;
VARIANT 型轉化成 CString 型;
載入字符串表資源;
CString 和臨時對象;
CString 的效率;
總結
下面我分別討論。
1、CString 對象的連接
能體現出 CString 類型方便性特點的一個方面就是字符串的連接,使用 CString 類型,你能很方便地連接兩個字符串,正如下面的例子:
CString gray("Gray");
CString cat("Cat");
CString graycat = gray + cat;
要比用下面的方法好得多:
char gray[] = "Gray";
char cat[] = "Cat";
char * graycat = malloc(strlen(gray) + strlen(cat) + 1);
strcpy(graycat, gray);
strcat(graycat, cat);
2、格式化字符串
與其用 sprintf() 函數或 wsprintf() 函數來格式化一個字符串,還不如用 CString 對象的Format()方法:
CString s;
s.Format(_T("The total is %d"), total);
用這種方法的好處是你不用擔心用來存放格式化後數據的緩衝區是否足夠大,這些工作由CString類替你完成。
格式化是一種把其它不是字符串類型的數據轉化爲CString類型的最常用技巧,比如,把一個整數轉化成CString類型,可用如下方法:
CString s;
s.Format(_T("%d"), total);
我總是對我的字符串使用_T()宏,這是爲了讓我的代碼至少有Unicode的意識,當然,關於Unicode的話題不在這篇文章的討論範圍。_T()宏在8位字符環境下是如下定義的:
#define _T(x) x // 非Unicode版本(non-Unicode version)
而在Unicode環境下是如下定義的:
#define _T(x) L##x // Unicode版本(Unicode version)
所以在Unicode環境下,它的效果就相當於:
s.Format(L"%d", total);
如果你認爲你的程序可能在Unicode的環境下運行,那麼開始在意用 Unicode 編碼。比如說,不要用 sizeof() 操作符來獲得字符串的長度,因爲在Unicode環境下就會有2倍的誤差。我們可以用一些方法來隱藏Unicode的一些細節,比如在我需要獲得字符長度的時候,我會用一個叫做DIM的宏,這個宏是在我的dim.h文件中定義的,我會在我寫的所有程序中都包含這個文件:
#define DIM(x) ( sizeof((x)) / sizeof((x)[0]) )
這個宏不僅可以用來解決Unicode的字符串長度的問題,也可以用在編譯時定義的表格上,它可以獲得表格的項數,如下:
class Whatever { ... };
Whatever data[] = {
{ ... },
...
{ ... },
};
for(int i = 0; i < DIM(data); i++) // 掃描表格尋找匹配項。
這裏要提醒你的就是一定要注意那些在參數中需要真實字節數的API函數調用,如果你傳遞字符個數給它,它將不能正常工作。如下:TCHAR data[20];
lstrcpyn(data, longstring, sizeof(data) - 1); // WRONG!
lstrcpyn(data, longstring, DIM(data) - 1); // RIGHT
WriteFile(f, data, DIM(data), &bytesWritten, NULL); // WRONG!
WriteFile(f, data, sizeof(data), &bytesWritten, NULL); // RIGHT
造成以上原因是因爲lstrcpyn需要一個字符個數作爲參數,但是WriteFile卻需要字節數作爲參數。
同樣需要注意的是有時候需要寫出數據的所有內容。如果你僅僅只想寫出數據的真實長度,你可能會認爲你應該這樣做:
WriteFile(f, data, lstrlen(data), &bytesWritten, NULL); // WRONG
但是在Unicode環境下,它不會正常工作。正確的做法應該是這樣:
WriteFile(f, data, lstrlen(data) * sizeof(TCHAR), &bytesWritten, NULL); // RIGHT
因爲WriteFile需要的是一個以字節爲單位的長度。(可能有些人會想"在非Unicode的環境下運行這行代碼,就意味着總是在做一個多餘的乘1操作,這樣不會降低程序的效率嗎?"這種想法是多餘的,你必須要了解編譯器實際上做了什麼,沒有哪一個C或C++編譯器會把這種無聊的乘1操作留在網站優化代碼中。在Unicode環境下運行的時候,你也不必擔心那個乘2操作會降低程序的效率,記住,這只是一個左移一位的操作而已,使用_T宏並不是意味着你已經創建了一個Unicode的程序,你只是創建了一個有Unicode意識的程序而已。如果你在默認的8-bit模式下編譯你的程序的話,得到的將是一個普通的8-bit的應用程序(這裏的8-bit指的只是8位的字符編碼,並不是指8位的計算機系統);當你在Unicode環境下編譯你的程序時,你纔會得到一個Unicode的程序。記住,CString 在 Unicode 環境下,裏面包含的可都是16位的字符哦。