MFC工程中的字符集問題,主要體現在字符串中包含中文時,CString與const char*的轉換上,在此把自己遇到的問題及解決方法稍微記錄一下,以便以后查閱。
首先說明一下 LPCTSTR 是什么東西。
1.LP 表示長指針,在win16下有長指針(LP)和短指針(P)的區別,而在win32下是沒有區別的,都是32位.所以這里的LP和P是等價的.
2.C 表示const;
3.T 是什么東西呢,我們知道TCHAR在采用 UNICODE 方式編譯時是wchar_t, 在普通時編譯成char.
那么就可以看出 LPCTSTR(PCTSTR) 在UINCODE時是 const wchar_t * , 在多字節字符模式時是 const char * .
接下來我們看如何把CString轉換成const char*.
(1)如果工程屬性為Unicode, 問題就要簡單的多,LPCTSTR就等於const char*, 在上面我們剛剛講過,系統會在編譯時自動判斷。
CString轉換成const char*則可以使用以下方法,通常情況下不會有問題:
CString cstring;
const char * constChar=(LPCTSTR)cstring;
或者可直接把CString變量賦值給const char* 和 LPCTSTR變量,MFC編繹器會自動地使用LPCTSTR把CString轉換成const char*如:
CString str="hello,你好!";
AfxMessageBox(str); //AfxMessageBox(LPCTSTR str,......) ;
test(str); //test(const char* ch);
(2)如果工程屬性為多字節字符集,問題就要復雜的多。有的時候采用(1)中所述的方法也是沒有問題的 ,有的時候卻會出現中文亂碼。
個人認為跟具體的函數相關,測試過的函數如,sqlite數據庫的打開函數 int sqlite3_open(const char *filename, sqlite3 **ppDb )
和標准c++庫函數 std::fstream::open(const char* filename,...) ,都不成功。
通過在網上搜集資料,對於上面兩個open函數都找到了解決辦法。
a. int sqlite3_open(const char *filename, sqlite3 **ppDb ) 采用方法如下:
使用函數_tcscpy_s:
【 CString theString( "你好,This is a test" );
int sizeOfString = theString.GetLength() + 1;
LPTSTR lpsz = new TCHAR[ sizeOfString ];
_tcscpy_s(lpsz, sizeOfString, theString); //_tstrcpy_s( char * _Dst, rsize_t _DstSize, const char * _Src)
sqlite3_open(lpsz, ...); 】
b. std::fstream::open(const char* filename,...) ,使用上述方法不成功,無奈之下,使用了該函數的另外一個實現
std::fstream::open(const wchar_t* filename,...) ,所以下面這個方法,其實是把CString轉換成const wchar_t *的方法。
【
CString channelPath="d:\\你好.txt";
int nlen=MultiByteToWideChar(CP_ACP, 0, channelPath, -1, NULL, 0);// MultiByteToWideChar( UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
// int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
WCHAR wBuf[128];
MultiByteToWideChar(CP_ACP, 0, channelPath, -1, wBuf, nlen);
std::fstream file;
file.open(wBuf,std::ios::out);
】