有關Unicode和非Unicode之間的轉化問題
自昨天開了部落格之後,就打算今天晚上寫點什麼來作為我的第一篇部落格(處女作)。
經過百般考量,小編決定寫寫有關Unicode和非Unicode編碼下,一些型別轉化的問題。(其實是小編對這整整一個晚上的程式碼除錯,對Unicode和非Unicode之間的轉化的麻煩報以深深的控訴。難道統一一下會死啊)
好,小編的白癜風發完了。我們進入正題。
什麼是Unicode?
百度百科的定義:
Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字元編碼。Unicode
是為了解決傳統的字元編碼方案的侷限而產生的,它為每種語言中的每個字元設定了統一併且唯一的
非Unicode則顧名思義。
在vs2013中,編譯器都會預設設定為“使用Unicode字符集”,也就是說我們使用的都是Unicode字元編碼。然而Unicode環境下字元佔兩個位元組,而在非Unicode環境下只佔一個位元組。正是因為如此,導致字元型別之間轉化的困難。
問題一:
在vs2013 MFC開發中,預設基於Unicode環境下,獲取編輯框中的字元,賦給string型別變數。
CString name;
m_name.GetWindowText(name);
string tempName = name.GetBuffer(); //通常情況下,CString轉化為string型別可以呼叫GetBuffer()函式
錯誤:
無法從“wchar_t *”轉換為“std::basic_string<char,std::char_traits<char>,std::allocator<char>>”
這是小編面臨的第一個問題。錯誤顯示:無法從wchar_t 轉化為 char , 或者是從wstring 轉化為 string 。
MFC的開發環境中,使用的控制元件都會有自己特定的類。比如CEdit,CListCtrl,這些類的成員方法(無論是形參還是返回值)大部分都是關於Unicode字符集的。也就是說使用string、char等作為這些方法的實參是都會出現編譯錯誤。
例如:
CListCtrl.InsertItem(0, str);
CListCtrl.SetItemText(0, 1, str);
以上兩個是CListCtrl的成員方法,其中str必須是基於Unicode的型別變數,例如CString、char*。
當我們想到string 轉化為 char*可以直接使用.c_str() 這個方法。然而在Unicode編碼不同的情況下,就會出現const char*無法轉化為char*的錯誤。
解決方法:
解決這型別的錯誤,主要原因是我們的變數轉化的時候位元組數一個是1,一個是2。我們要把位元組數統一。
Unicode轉非Unicode:
可以使用CT2A,如剛才的例子
CString name;
m_name.GetWindowText(name);
string tempName = CT2A(name.GetBuffer()); 可以解決。
在一些方法裡,會留有非Unicode的方法,例如:
TextOut(xdc,x,y,_T(text),strlen(text)); (非Unicode版)-> TextOutA(xdc,x,y,_T(text),strlen(text));
最根本的,可以在專案的管理器裡把“Unicode字符集”改為“多字符集”,但是在專案中途改動會出現錯誤。
改動的路徑為:專案 -> 屬性 -> 配置屬性 -> 常規 -> 字符集
非Unicode轉Unicode:
使用_T("")巨集和L都是比較簡單的方法,但實用性不強。
這裡介紹最為安全和實用的函式MultiByteToWideChar函式,使用方法如下:
nLen = (int)getname.length();
name.resize(nLen, L' ');
nResult = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)getname.c_str(), nLen, (LPWSTR)name.c_str(), nLen);
CListCtrl.InsertItem(i, name.c_str());
這情況下,可以把一個非Unicode的string型別轉化為Unicode的wstring型別。
與其相對應的wstring轉string型別使用的函式是WideCharToMultiByte(),程式碼例項如下:
int nLen = (int)wstr.length();
str.resize(nLen, ' ');
int nResult = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wstr.c_str(), nLen, (LPSTR)str.c_str(), nLen, NULL, NULL);
以上兩個方法是專屬解決多位元組和寬位元組問題的。
以上問題同時關係到LPCTSTR、LPCWSTR轉化問題。
最後附上幾個轉化的方法(正確性和使用性未知)
1、string 轉 CString
CString.format("%s", string.c_str());
2、char * 轉 CString
CString.format("%s", char*);
3、char * 轉 string
string s(char *);
4、string 轉 char *
char *p = string.c_str();
5、CString 轉 string
string s(CString.GetBuffer(CString.GetLength()));
6、CString 轉 char *
charpoint=strtest.GetBuffer(strtest.GetLength());
不建議用(LPCTSTR)進行強制型別轉化,這樣strtest大小發生變化時會出現錯誤。
7、CString 轉 char[100]
char a[100];
CString str("aaaaaa");
strncpy(a,(LPCTSTR)str,sizeof(a));
最後感謝我找到的所有的部落格、文章和百度。
最後的最後,現在是凌晨2點43分。