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);
】