各種微軟不維護MFC的訊息使得許多人不再將MFC作為自己的軟體開發架構,但是 本人覺得MFC為軟體開發帶來了巨大的方便,尤其對於電腦科班出身的人來說,所以我到現在仍然是MFC的忠實使用者。
今天解決一下CString中的漢字儲存的問題:
問題提出:讀取硬碟中的一幅映像,映像的絕對位址存在CString變數之中,使用賦值建構函式CString graPath;graPath="F:\映像庫\a.tif"。但是在MFC的AfxMessageBox中顯示的路徑名卻是一堆亂碼。
解釋:這個一個很有趣的問題,理論上來說,我對初始化用的字串使用_T("")規範就可以解決這個問題了。但是,事與願違。於是我試了一下用這個字串:graPath="映像庫\a.tif",如此顯示的字串正常,然後我又用這個字串:graPath="F:映像庫\a.tif",還是一切正常,於是我把焦點對準在了”\“上。哎,貌似是漢字與英文的混合輸入產生的錯誤,竟然來到了逸出字元上面。下面好好來說說這個既熟悉又陌生的逸出字元(escape sequence)。
為了遇到同樣問題的網友能夠第一時間找到問題的解決方案,我先把結論列上:
CString字串中,英文用ASCII表示,漢字是用Unicode表示。其中英文每個字母佔用一個byte,漢字佔2個byte,逸出字元”\“及其之後的字母佔1個byte。除了規定的轉義項之外,不能隨便將”\“加入到字串中。
就這麼簡單。
所以說如下從字串中將漢字和英文分別提取出來的程式就很顯而易見了。但是別忘了我們今天的主題:逸出字元。我更關心的是逸出字元在整個字串中的位置。
逸出字元屬於ASCII的範疇,逸出字元”\“只有和一個特定的字母結合才具有轉義的含義,但是逸出字元的使用會出現兩種錯誤的情況:
①”\“後沒有接指定的字母
②"\"後接漢字,就像我所犯的那樣的錯誤。
下面一一分析。對於沒有接指定字母的情況,比如我們初始化如下字串:CString sss="\u你好hello" 。\u在ASCII表中並沒有對應值。如此,我們調用printf函數輸出字串會產生什麼結果呢?printf函數會無視‘\’,直接輸出"u你好hello"。也就是該字串字串在記憶體中實際存成的是u的ASCII。
對於第二種情況,我們初始化如下字串:CString sss="\你好hello"。調用printf函數輸出字串輸出的結果的是: 愫胔ello。實驗多次,我們發現Unicode編碼會吃掉其後的ASCII碼的第一個,介於Unicode編碼的複雜性,我們只需要記住一條簡單的結論即可“:逸出字元後面千萬別加漢字了。
#include "stdafx.h"#include <afx.h> CString GetChinese(const CString &Dst);CString GetEnglish(const CString &Dst);int main(int argc, char* argv[]){//CString sss=_T("ha:\a\你好是個什麼是呢he");CString sss="中國haha";CString schn=GetChinese(sss);CString seng=GetEnglish(sss);printf("%s\n",schn); printf("%s\n",seng); //cout<<sss<<endl;return 0;}CString GetChinese(const CString &Dst){int i;int Length=Dst.GetLength();CString StrCHN=_T("");for (i=0;i<Length;i++){if ((unsigned char)Dst.GetAt(i)>=128){StrCHN+=Dst.GetAt(i++);StrCHN+=Dst.GetAt(i);}}return StrCHN;}CString GetEnglish(const CString &Dst){int i;int Length=Dst.GetLength();CString StrEng=_T("");for (i=0;i<Length;i++){if ((unsigned char)Dst.GetAt(i)<128){StrEng+=Dst.GetAt(i);}}return StrEng;}
附上一篇介紹CString API的部落格 http://www.cnblogs.com/Caiqinghua/archive/2009/02/16/1391190.html