最近學了兩天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、CStringA
和CStringW
,它們分別提供對TCHAR
、char
和wchar_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
可選,爲要格式化的數據,一般每個argument
在pszFormat
中都有對應的表示其類型的子字符串,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"
CString
和std::string
的相互轉換
CString
-> string
這裏我使用了一下網上查到的方法,發現並不能用,其實想一想也對,string
內置存儲的是一個字節長的char
類型字符,而CString
存儲的是兩字節長的wchar_t
類型。不能相互轉換也比較正常,雖然可以直接強行轉換。但也太過於粗暴了。
但是有一點我覺得比較奇怪,因爲在我印象中string
雖然內部是char
類型的元素,但是在初始化的時候,會自動將那個漢字元素擴充成兩個字符位置進行存儲。
比如如下代碼:
int main()
{
string str = "hi,你好";
return 0;
}
調用調試,我們可以很容易的發現string
內部的存儲形式爲如下方式:
可以發現,string
內部還是使用的char
類型進行漢字的存儲,不過卻是使用的兩個char來存儲。
不過如果我們如果單獨用wchar_t
字符串對string
進行初始化,就會出錯。
所以我們在使用CString
對string
挨個元素進行初始化的時候,發現string
內部的元素卻是使用的一個char
進行存儲wchar_t
,這就導致了無法用CString
對string
進行初始化的問題。
這樣的字符轉碼真的導致了很大的問題,而且不好解決。解決方式有以下幾種:
- 我們可以使用
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());
真的是…..很奇特。
就這樣吧,等有空了再仔細看看字符的不同編碼方式之間的轉換吧。