因爲程序中需要把CString轉爲char*來使用,沒想到轉換的套路挺深所以也順便記錄一下。
一般來說普通的情況只需要這樣就能轉換:
CString strFilepath = _T("d:\\新建文件夾");
char *pFilepath = strFilepath.GetBuffer(0);
CString自身就有提供方法進行轉換。但是如果你的工程設置的是Unicode字符集:
編譯時就會提示例如“不能從wchar_t*轉換爲char*”等錯誤。
那就再找找unicode字符轉換成多字節字符的方法唄。
總的來說找到兩種方法,分別是C和C++的:
1.wcstombs_s函數(C下)
(Wide Const String To Multiple Byte String)
相對的也有mbstowcs_s
頭文件<stdlib.h>
函數原型 : errno_t wcstombs_s( size_t *pReturnValue, char *mbstr, size_t sizeInBytes, const wchar_t *wcstr, size_t count );
pReturnValue代表該次wchar_t轉換成char*後其字符個數;
mbstr代表接收轉換結果的char指針;
sizeInBytes代表轉到mbstr的字節數(mbstr是提前已經分配好空間的,因此它做的不是單純複製了一個首地址,而是完整內容的複製,正式點叫做深度拷貝吧);
wcstr代表要進行轉換的wchar_t*字符串;
count就是一個限制器,代表最多能存進mbstr內的字節數(如果你不想做限制,那就直接設置成_TRUNCATE吧);
如果轉換成功返回值爲0,否則就爲以下的幾項:
error code:
#define EINVAL 22
#define ERANGE 34
#define EILSEQ 42
#define STRUNCATE 80
CString strFilepath = _T("d:\\新建文件夾");
size_t iLengh = strFilepath.GetLength() * 2 + 1;
size_t iConverted = 0;
char * pFilepath = new char[iLengh];
wcstombs_s(&iConverted, pFilepath, iLengh, strFilepath, _TRUNCATE);
注意:因爲一箇中文佔兩個字節,所以如果你直接設置iLengh = strFilepath.GetLength() + 1的話,估計得到的pFilepth中存儲的就是"d:\\新建□"等之類的東西了。
這裏直接設置爲兩倍加1是爲了應付最極端的情況:都是中文。
2.WideCharToMultiByte函數(C++下)
頭文件<winnls.h>
函數原型 :
int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr,
int cchMultiByte, LPCSTR lpDefaultChar, LPBOOL pfUsedDefaultChar);
CodePage代表轉換目標的字符集,一般來說直接用CP_ACP(當前系統ANSI代碼頁)就行了;
其他你要看看也可以:(來源於網上http://blog.sina.com.cn/s/blog_55a406730100rgtt.html)
CP_ACP 當前系統ANSI代碼頁
CP_MACCP 當前系統Macintosh代碼頁
CP_OEMCP 當前系統OEM代碼頁,一種原始設備製造商硬件掃描碼
CP_SYMBOL Symbol代碼頁,用於Windows 2000及以後版本
CP_THREAD_ACP 當前線程ANSI代碼頁,用於Windows 2000及以後版本
CP_UTF7 UTF-7,設置此值時lpDefaultChar和lpUsedDefaultChar都必須爲NULL
CP_UTF8 UTF-8,設置此值時lpDefaultChar和lpUsedDefaultChar都必須爲NULL
dwFlags指定如何處理那些無法轉換/無法匹配的字符,一般設置爲0;
lpWideCharStr代表將要處理的wchar_t字符串;
cchWideChar代表需要處理的wchar_t字符串長度,-1的話代表整個字符串都處理;
lpMultiByteStr代表接收轉換結果的char字符串,如果這個值設置爲NULL的話;
cchMultiByte代表輸出的緩衝區大小,如果爲0,lpMultiByteStr將被忽略,函數將返回所需緩衝區大小而不使用lpMultiByteStr;
lpDefaultChar代表無法匹配時替換的默認字符(一個字符,不是字符串大兄弟),一般設置爲NULL就好了;
pfUsedDefaultChar代表是否使用默認字符進行替換了,如果上面用了NULL,那這個也用NULL就行;
小技巧 : 可以把cchMultiByte設置爲0,跑一次獲取到所需空間大小,再正式調用函數完成轉換。
示例:
CString strFilepath = _T("d:\\新建文件夾");
//從wchar_t*轉換爲char*
int iSize = WideCharToMultiByte(CP_ACP, 0, strFilepath.GetBuffer(0), -1, NULL, 0, NULL, NULL);
char *pFilepath = new char[iSize + 1];
WideCharToMultiByte(CP_ACP, 0, strFilepath.GetBuffer(0), -1, pFilepath, iSize, NULL, NULL);
之前我也嘗試過用for循環直接一個一個處理過來,畢竟一箇中文就是佔了兩個英文的字節大小,只要遇到值不在0~255範圍內的字符,那一般都是中文字符。
然後把這個寬字符拆成兩部分存在兩個char中就行了。但是這個拆的方法應該是跟字符編碼有關,我直接根據二進制位數把它拆成前8位和後8位並沒有什麼卵用。
有關於字符編碼的轉換算法就暫不深究了,老老實實先用着上面兩個轉換函數吧。
話說csdn總喜歡把一些字↑設置爲超鏈接啊,事先說明不是我弄的,大兄弟你別亂點。
總之問題解決,可喜可賀可喜可賀。