Unicode编码下,如何把char*转化为CString,char*中含有汉字,请给出具体代码.
在线等。

解决方案 »

  1.   

    char *p="我爱你"; 
    CString csStr(p);
      

  2.   

    #include<locale.h>
    int main(int argc, char* argv[])
    {
    char* p = "a中文ba";
    setlocale( LC_ALL , "chs" ); size_t len = mbstowcs( NULL , p , 0 );
    printf("%d\n",len);
    CString str;
    mbstowcs(str.GetBuffer( len +1 ) , p , len );
    str.ReleaseBuffer();
    MessageBoxW( 0 , str, 0 , 0 );
    return 0;
    }
      

  3.   

    1楼的应该就可以了吧。
    CString( LPCSTR lpsz ); 这个CString的构造函数就可以把char*构造成为CString了啦。
      

  4.   

    char[]是不能直接转化为CString的,得先用multibytetowidechar()转化为WCHAR[],wchar[]可以直接给CString赋值了。
      

  5.   

    4、CString 型和 char* 類型的相互轉化  這是初學者使用 CString 時最常見的問題。有了 C++ 的幫助,很多問題你不需要深入的去考慮它,直接拿來用就行了,但是如果你不能深入瞭解它的運行機制,又會有很多問題讓你迷惑,特別是有些看起來沒有問題的代碼,卻偏偏不能正常工作。
    比如,你會奇怪為什麼不能寫向下面這樣的代碼呢:CString graycat = "Gray" + "Cat";
    或者這樣:CString graycat("Gray" + "Cat");
       事實上,編譯器將抱怨上面的這些嘗試。為什麼呢?因為針對CString 和 LPCTSTR資料類型的各種各樣的組合,“ +” 運算符 被定義成一個重載操作符。而不是兩個 LPCTSTR 資料類型,它是底層資料類型。你不能對基本資料(如 int、char 或者 char*)類型重載 C++ 的運算符。你可以象下面這樣做:CString graycat = CString("Gray") + CString("Cat");
    或者這樣:CString graycat = CString("Gray") + "Cat";
    研究一番就會發現:“ +”總是使用在至少有一個 CString 物件和一個 LPCSTR 的場合。注意,編寫有 Unicode 意識的代碼總是一件好事,比如:CString graycat = CString(_T("Gray")) + _T("Cat");
    這將使得你的代碼可以直接移植。char* 轉化為 CString  現在你有一個 char* 類型的資料,或者說一個字串。怎麼樣創建 CString 物件呢?這裏有一些例子:char * p = "This is a test";
    或者象下面這樣更具有 Unicode 意識:TCHAR * p = _T("This is a test")
    或LPTSTR p = _T("This is a test");
    你可以使用下面任意一種寫法:CString s = "This is a test"; // 8-bit only
    CString s = _T("This is a test"); // Unicode-aware
    CString s("This is a test"); // 8-bit only
    CString s(_T("This is a test")); // Unicode-aware
    CString s = p;
    CString s(p);
      用這些方法可以輕鬆將常量字串或指標轉換成 CString。需要注意的是,字元的賦值總是被拷貝到 CString 物件中去的,所以你可以象下面這樣操作:TCHAR * p = _T("Gray");
    CString s(p);
    p = _T("Cat");
    s += p;
    結果字串肯定是“GrayCat”。CString 類還有幾個其他的構造函數,但是這裏我們不考慮它,如果你有興趣可以自己查看相關文檔。事實上,CString 類的構造函數比我展示的要複雜,比如:CString s = "This is a test"; 
       這是很草率的編碼,但是實際上它在 Unicode 環境下能編譯通過。它在運行時調用構造函數的 MultiByteToWideChar 操作將 8 位元字串轉換成 16 位元字串。不管怎樣,如果 char * 指標是網路上傳輸的 8 位元資料,這種轉換是很有用的。CString 轉化成 char* 之一:強制類型轉換為 LPCTSTR;  這是一種略微硬性的轉換,有關“正確”的做法,人們在認識上還存在許多混亂,正確的使用方法有很多,但錯誤的使用方法可能與正確的使用方法一樣多。
       我們首先要瞭解 CString 是一種很特殊的 C++ 物件,它裏面包含了三個值:一個指向某個資料緩衝區的指標、一個是該緩衝中有效的字元記數以及一個緩衝區長度。 有效字元數的大小可以是從0到該緩衝最大長度值減1之間的任何數(因為字串結尾有一個NULL字元)。字元記數和緩衝區長度被巧妙隱藏。
      除非你做一些特殊的操作,否則你不可能知道給CString物件分配的緩衝區的長度。這樣,即使你獲得了該0緩衝的位址,你也無法更改其中的內容,不能截短字串,也 絕對沒有辦法加長它的內容,否則第一時間就會看到溢出。
      LPCTSTR 操作符(或者更明確地說就是 TCHAR * 操作符)在 CString 類中被重載了,該操作符的定義是返回緩衝區的位址,因此,如果你需要一個指向 CString 的 字串指標的話,可以這樣做:
    CString s("GrayCat");
    LPCTSTR p = s;
      它可以正確地運行。這是由C語言的強制類型轉化規則實現的。當需要強制類型轉化時,C++規測容許這種選擇。比如,你可以將(浮點數)定義為將某個複數 (有一對浮點數)進行強制類型轉換後只返回該複數的第一個浮點數(也就是其實部)。可以象下面這樣:Complex c(1.2f, 4.8f);
    float realpart = c;
    如果(float)操作符定義正確的話,那麼實部的的值應該是1.2。
      這種強制轉化適合所有這種情況,例如,任何帶有 LPCTSTR 類型參數的函數都會強制執行這種轉換。 於是,你可能有這樣一個函數(也許在某個你買來的DLL中):BOOL DoSomethingCool(LPCTSTR s);
    你像下面這樣調用它:CString file("c:\\myfiles\\coolstuff")
    BOOL result = DoSomethingCool(file);
      它能正確運行。因為 DoSomethingCool 函數已經說明了需要一個 LPCTSTR 類型的參數,因此 LPCTSTR 被應用於該參數,在 MFC 中就是返回的串地址。如果你要格式化字串怎麼辦呢?CString graycat("GrayCat");
    CString s;
    s.Format("Mew! I love %s", graycat);
      注意由於在可變參數列表中的值(在函數說明中是以“...”表示的)並沒有隱含一個強制類型轉換操作符。你會得到什麼結果呢?
      一個令人驚訝的結果,我們得到的實際結果串是:"Mew! I love GrayCat"。
       因為 MFC 的設計者們在設計 CString 資料類型時非常小心, CString 類型運算式求值後指向了字串,所以這裏看不到任何象 Format 或 sprintf 中的強制類型轉換,你仍然可以得到正確的行為。描述 CString 的附加資料實際上在 CString 名義位址之後。
      有一件事情你是不能做的,那就是修改字串。比如,你可能會嘗試用“,”代替“.”(不要做這樣的,如果你在乎國際化問題,你應該使用十進位轉換的 National Language Support 特性,),下面是個簡單的例子:CString v("1.00"); // 貨幣金額,兩位小數
    LPCTSTR p = v;
    p[lstrlen(p) - 3] = '','';
      這時編譯器會報錯,因為你賦值了一個常量串。如果你做如下嘗試,編譯器也會錯:strcat(p, "each");
      因為 strcat 的第一個參數應該是 LPTSTR 類型的資料,而你卻給了一個 LPCTSTR。  不要試圖鑽這個錯誤消息的牛角尖,這只會使你自己陷入麻煩!   原因是緩衝有一個計數,它是不可存取的(它位於 CString 位址之下的一個隱藏區域),如果你改變這個串,緩衝中的字元計數不會反映所做的修改。此外,如果字串長度恰好是該字串物理限制的長度(梢後還會講到這 個問題),那麼擴展該字串將改寫緩衝以外的任何資料,那是你無權進行寫操作的記憶體(不對嗎?),你會毀換壞不屬於你的記憶體。這是應用程式真正的死亡處 方。CString轉化成char* 之二:使用 CString 物件的 GetBuffer 方法;  如果你需要修改 CString 中的內容,它有一個特殊的方法可以使用,那就是 GetBuffer,它的作用是返回一個可寫的緩衝指標。 如果你只是打算修改字元或者截短字串,你完全可以這樣做:CString s(_T("File.ext"));
    LPTSTR p = s.GetBuffer();
    LPTSTR dot = strchr(p, ''.''); // OK, should have used s.Find...
    if(p != NULL)
    *p = _T(''\0'');
    s.ReleaseBuffer();
      這是 GetBuffer 的第一種用法,也是最簡單的一種,不用給它傳遞參數,它使用預設值 0,意思是:“給我這個字串的指標,我保證不加長它”。當你調用 ReleaseBuffer 時,字串的實際長度會被重新計算,然後存入 CString 物件中。
       必須強調一點,在 GetBuffer 和 ReleaseBuffer 之間這個範圍,一定不能使用你要操作的這個緩衝的 CString 物件的任何方法。因為 ReleaseBuffer 被調用之前,該 CString 物件的完整性得不到保障。研究以下代碼:CString s(...);LPTSTR p = s.GetBuffer();//... 這個指標 p 發生了很多事情int n = s.GetLength(); // 很糟D!!!!! 有可能給出錯誤的答案!!!s.TrimRight(); // 很糟!!!!! 不能保證能正常工作!!!!s.ReleaseBuffer(); // 現在應該 OKint m = s.GetLength(); // 這個結果可以保證是正確的。s.TrimRight(); // 將正常工作。
      假設你想增加字串的長度,你首先要知道這個字串可能會有多長,好比是聲明字串陣列的時候用:char buffer[1024];
    表示 1024 個字元空間足以讓你做任何想做得事情。在 CString 中與之意義相等的表示法:LPTSTR p = s.GetBuffer(1024);
      調用這個函數後,你不僅獲得了字串緩衝區的指標,而且同時還獲得了長度至少為 1024 個字元的空間(注意,我說的是“字元”,而不是“位元組”,因為 CString 是以隱含方式感知 Unicode 的)。
       同時,還應該注意的是,如果你有一個常量串指標,這個串本身的值被存儲在唯讀記憶體中,如果試圖存儲它,即使你已經調用了 GetBuffer ,並獲得一個唯讀記憶體的指標,存入操作會失敗,並報告存取錯誤。我沒有在 CString 上證明這一點,但我看到過大把的 C 程式師經常犯這個錯誤。
      C 程式師有一個通病是分配一個固定長度的緩衝,對它進行 sprintf 操作,然後將它賦值給一個 CString:char buffer[256];
    sprintf(buffer, "%......", args, ...); // ... 部分省略許多細節
    CString s = buffer;
    雖然更好的形式可以這麼做:CString s;
    s.Format(_T("%...."), args, ...);
    如果你的字串長度萬一超過 256 個字元的時候,不會破壞堆疊。  另外一個常見的錯誤是:既然固定大小的記憶體不工作,那麼就採用動態分配位元組,這種做法弊端更大:int len = lstrlen(parm1) + 13lstrlen(parm2) + 10 + 100;char * buffer = new char[len];sprintf(buffer, "%s is equal to %s, valid data", parm1, parm2);CString s = buffer;......delete [] buffer;
    它可以能被簡單地寫成:CString s;s.Format(_T("%s is equal to %s, valid data"), parm1, parm2);
      需要注意 sprintf 例子都不是 Unicode 就緒的,儘管你可以使用 tsprintf 以及用 _T() 來包圍格式化字串,但是基本 思路仍然是在走彎路,這這樣很容易出錯。CString to char * 之三:和控制項的介面;   我們經常需要把一個 CString 的值傳遞給一個控制項,比如,CTreeCtrl。MFC為我們提供了很多便利來重載這個操作,但是 在大多數情況下,你使用“原始”形式的更新,因此需要將墨某個串指標存儲到 TVINSERTITEMSTRUCT 結構的 TVITEM 成員中。如下:TVINSERTITEMSTRUCT tvi;
    CString s;
    // ... 為s賦一些值。
    tvi.item.pszText = s; // Compiler yells at you here
    // ... 填寫tvi的其他域
    HTREEITEM ti = c_MyTree.InsertItem(&tvi);
      為什麼編譯器會報錯呢?明明看起來很完美的用法啊!但是事實上如果你看看 TVITEM 結構的定義你就會明白,在 TVITEM 結構中 pszText 成員的聲明如下:LPTSTR pszText;
    int cchTextMax;
      因此,賦值不是賦給一個 LPCTSTR 類型的變數,而且編譯器無法知道如何將賦值語句右邊強制轉換成 LPCTSTR。好吧,你說,那我就改成這樣:tvi.item.pszText = (LPCTSTR)s; //編譯器依然會報錯。
       編譯器之所以依然報錯是因為你試圖把一個 LPCTSTR 類型的變數賦值給一個 LPTSTR 類型的變數,這種操作在C或C++中是被禁止的。你不能用這種方法 來濫用常量指針與非常量指針概念,否則,會擾亂編譯器的優化機制,使之不知如何優化你的程式。比如,如果你這麼做:const int i = ...;
    //... do lots of stuff
    ... = a[i]; // usage 1
    // ... lots more stuff
    ... = a[i]; // usage 2
      那麼,編譯器會以為既然 i 是 const ,所以 usage1和usage2的值是相同的,並且它甚至能事先計算好 usage1 處的 a[i] 的位址,然後保留著在後面的 usage2 處使用,而不是重新計算。如果你按如下方式寫的話:const int i = ...;
    int * p = &i;
    //... do lots of stuff
    ... = a[i]; // usage 1
    // ... lots more stuff
    (*p)++; // mess over compiler''s assumption
    // ... and other stuff
    ... = a[i]; // usage 2
       編譯器將認為 i 是常量,從而 a[i] 的位置也是常量,這樣間接地破壞了先前的假設。因此,你的程式將會在 debug 編譯模式(沒有優化)和 release 編譯模式(完全優化)中反映出不同的行為,這種情況可不好,所以當你試圖把指向 i 的指標賦值給一個 可修改的引用時,會被編譯器診斷為這是一種偽造。這就是為什麼(LPCTSTR)強制類型轉化不起作用的原因。
      為什麼不把該成員聲明成 LPCTSTR 類型呢?因為這個結構被用於讀寫控制項。當你向控制項寫資料時,文本指標實際上被當成 LPCTSTR,而當你從控制項讀數據 時,你必須有一個可寫的字串。這個結構無法區分它是用來讀還是用來寫。因此,你會常常在我的代碼中看到如下的用法:tvi.item.pszText = (LPTSTR)(LPCTSTR)s;
      它把 CString 強制類型轉化成 LPCTSTR,也就是說先獲得改字串的位址,然後再強制類型轉化成 LPTSTR,以便可以對之進行賦值操作。 注意這只有在使用 Set 或 Insert 之類的方法才有效!如果你試圖獲取資料,則不能這麼做。
      如果你打算獲取存儲在控制項中的資料,則方法稍有不同,例如,對某個 CTreeCtrl 使用 GetItem 方法,我想獲取專案的文本。我知道這些 文本的長度不會超過 MY_LIMIT,因此我可以這樣寫:TVITEM tvi;
    // ... assorted initialization of other fields of tvi
    tvi.pszText = s.GetBuffer(MY_LIMIT);
    tvi.cchTextMax = MY_LIMIT;
    c_MyTree.GetItem(&tvi);
    s.ReleaseBuffer();
       可以看出來,其實上面的代碼對所有類型的 Set 方法都適用,但是並不需要這麼做,因為所有的類 Set 方法(包括 Insert方法)不會改變字串的內容。但是當你需要寫 CString 物件時,必須保證緩衝是可寫的,這正是 GetBuffer 所做的事情。再次強調: 一旦做了一次 GetBuffer 調用,那麼在調用 ReleaseBuffer 之前不要對這個 CString 物件做任何操作。
      

  6.   

    这是我将char*转到CString再转到char*的办法,char*中可以有中文英文,没关系。
    第一步用memcpy将char*拷贝到wchar_t*中,直接赋值给CString再用memcpy从CString直接拷贝到char*中。
    memcpy(bufArray,msg.m_strMsg.GetBuffer(),msg.m_strMsg.GetLength()*2);
    memcpy函数真是好用!这个我在自己机器上调试成功,用的是MFC程序。
      

  7.   

    http://apps.hi.baidu.com/share/detail/15410386
    我就是参考这个的,蛮具体的