【C++】MFC中的CString和std::string,以及兩者之間的相互轉換(基於VS201X版本)

最近學了兩天MFC,發現還比較有意思,準備過一段時間買一本《深入淺出MFC》,去好好學一下圖形界面的框架以及其內部對系統調用的使用。
在使用MFC的時候,雖然界面和其表面邏輯框架都是使用MFC的,但其實大部分的內部邏輯我還是使用C++原生庫去寫的,比如今天花了兩個小時寫了兩個MFC小程序——輸入型多項式計算器(中綴轉後綴,支持加減乘除括號的混合運算)、一個簡單的漢英詞典軟件(解決一下自己平常打代碼的時候的命名問題),其內部邏輯都是用C++內部自帶的庫(STL等)和命名空間std去實現的。
由於上面的兩個小Demo都用到了比較多的字符串處理,而內部邏輯使用的是std::string,而在MFC這邊,我取得的Edit_Control 中的數據是CString類型的,所以就要經過一些簡單的轉換。
所以,下面對CString和C++自帶字符串類型(std::string)之間,進行轉換的方法做一個小總結吧。

經過這幾天的搜索學習,我發現網上介紹CString的東西特別少,所以我先介紹一下CString

CString

CStringT,實際上它是一個操作可變長度字符串的模板類。CStringT模板類有三個實例:CString、CStringACStringW,它們分別提供對TCHARcharwchar_t字符類型的字符串的操作。char類型定義的是Ansi字符,wchar_t類型定義的是Unicode字符,而TCHAR取決於MFC工程的屬性對話框中的Configuration Properties->General->Character Set屬性,如果此屬性爲Use Multi-Byte Character Set,則TCHAR類型定義的是Ansi字符,而如果爲Use Unicode Character Set,則TCHAR類型定義的是Unicode字符。

幾個常用函數:

  CString& MakeLower();

將字符串中的所有大寫字符轉換爲小寫字符。

     CString& MakeUpper();

將字符串中的所有小寫字符轉換爲大寫字符。

     CString& MakeReverse();

將字符串中所有字符的順序顛倒。


CString對象的連接

多個CString對象的連接可以通過重載運算符+、+=實現。例如:

CString str(_T("google"));      // str內容爲"google"   
str = _T("www.") + str + _T("."); // str爲"www.google."   
str += _T("com");                 // str爲"www.google.com"  

CString對象字符串的提取操作

CString Left(int nCount) const;

提取該字符串左邊nCount個字符的子字符串,並返回一個包含這個子字符串的拷貝的CString對象。

CString Right(int nCount) const;

提取該字符串右邊nCount個字符的子字符串,並返回一個包含這個子字符串的拷貝的CString對象。

CString Mid(int iFirst,int nCount) const;

提取該字符串中以索引iFirst位置開始的nCount個字符組成的子字符串,並返回一個包含這個子字符串的拷貝的CString對象。

CString Mid(int iFirst) const;

提取該字符串中以索引iFirst位置開始直至字符串結尾的子字符串,並返回一個包含這個子字符串的拷貝的CString對象。
如下:

CString str1 = _T("google");   
CString str2 = str1.Left(3);    // str2爲"goo"   
str2 = str1.Right(2);           // str2爲"le"   
str2 = str1.Mid(1,3);           // str2爲"oog"   
str2 = str1.Mid(5);             // str2爲"le"  

CString類的格式化字符串方法

使用CString類的Format成員函數可以將int、short、long、float、double等數據類型格式化爲字符串對象。

 void __cdecl Format(PCXSTR pszFormat,[, argument]...);

參數pszFormat爲格式控制字符串;參數argument可選,爲要格式化的數據,一般每個argumentpszFormat中都有對應的表示其類型的子字符串,int型的argument對應的應該是"%d"float型的應對應"%f",等等。
例如:

CString str;   
int a = 1;   
float b = 2.3f;   
str.Format(_T("a=%d,b=%f"), a, b);  // str爲"a=1,b=2.300000"  

CStringstd::string的相互轉換

CString -> string

這裏我使用了一下網上查到的方法,發現並不能用,其實想一想也對,string內置存儲的是一個字節長的char類型字符,而CString存儲的是兩字節長的wchar_t類型。不能相互轉換也比較正常,雖然可以直接強行轉換。但也太過於粗暴了。

但是有一點我覺得比較奇怪,因爲在我印象中string雖然內部是char類型的元素,但是在初始化的時候,會自動將那個漢字元素擴充成兩個字符位置進行存儲。
比如如下代碼:


int main() 
{
    string str = "hi,你好";
    return 0;
}

調用調試,我們可以很容易的發現string內部的存儲形式爲如下方式:

這裏寫圖片描述

可以發現,string內部還是使用的char類型進行漢字的存儲,不過卻是使用的兩個char來存儲。
不過如果我們如果單獨用wchar_t 字符串對string進行初始化,就會出錯。
所以我們在使用CStringstring挨個元素進行初始化的時候,發現string內部的元素卻是使用的一個char進行存儲wchar_t,這就導致了無法用CStringstring進行初始化的問題。

這樣的字符轉碼真的導致了很大的問題,而且不好解決。解決方式有以下幾種:

  • 我們可以使用wstring來進行字符串的存儲和輸出,然後用一對一的下標賦值的方式進行解決
  • 也可以直接用vs2015左右版本支持的方式CT2A(之前版本的也應該有相應的轉換宏定義,不過是不是這個就不一定了,可以去查一下官方手冊):
string c_str("你好");
string str = CT2A(mfc_str);
  • GetBuffer(0) 然後加一點轉換,記得ReleaseBuffer()
CString mfc_str("Nihao1");
string str(CT2CA(mfc_str.GetBuffer(0)));

還是自己學的不好啊,看來這些基礎還要再次重溫一下。


string ->CString

相對於上面的轉換,下面的轉換就很簡單了,直接用如下代碼就OK:

string p("你好");
CString Cstr(p.c_str());

真的是…..很奇特。

就這樣吧,等有空了再仔細看看字符的不同編碼方式之間的轉換吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章