1. 程式人生 > >CString類的轉化(高階)及小技巧(轉)

CString類的轉化(高階)及小技巧(轉)

CString類的轉化(高階)

通過閱讀本文你可以學習如何有效地使用 CString。

  CString 是一種很有用的資料型別。它們很大程度上簡化了MFC中的許多操作,使得MFC在做字串操作的時候方便了很多。不管怎樣,使用CString有很多特殊的技巧,特別是對於純C背景下走出來的程式設計師來說有點難以學習。這篇文章就來討論這些技巧。
  使用CString可以讓你對字串的操作更加直截了當。這篇文章不是CString的完全手冊,但囊括了大部分常見基本問題。

這篇文章包括以下內容:
  1. CString 物件的連線

  2. 格式化字串(包括 int 型轉化為 CString )
  3. CString 型轉化成 int 型
  4. CString 型和 char* 型別的相互轉化
  5. char* 轉化成 CString
  6. CString 轉化成 char* 之一:使用LPCTSTR強制轉化
  7. CString 轉化成 char* 之二:使用CString物件的GetBuffer方法
  8. CString 轉化成 char* 之三: 和控制元件的介面
  9. CString 型轉化成 BSTR 型;
  10. BSTR 型轉化成 CString 型;
  11. VARIANT 型轉化成 CString 型;
  12. 載入字串表資源;
  13. CString 和臨時物件;
  14. CString 的效率;
  15. 總結

下面我分別討論。

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); // RIGHTWriteFile(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位的字元哦。

3、CString 型轉化成 int 型

  把 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));
  以前做程式遇到的小問題

1. 將CString 轉為WCHAR *
    CString str;
     WCHAR * p = str.AllocSysString() ;
  --------or - -----------
   WCHAR *p = CT2W(str);

2. 轉為LPCWSTR 
   LPCWSTR strW= T2CW_EX( str, _ATL_SAFE_ALLOCA_DEF_THRESHOLD );

3. 轉為char * / LPSTR
   char *p  =  str.GetBuffer(str.GetLength());

4. 轉為int
   CString str = "23";
   UINT uint;
   sscanf(str, "%d", uint);

5. 轉為LPCTSTR
  LPCTSTR = str; //比較直接 :)

6. 從string建立CString;
  CString str;
  string st;
  str =   st.c_str ()