1. 程式人生 > >有關Unicode和非Unicode之間的轉化問題

有關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分。