size_t len = wcslen(WStr) + 1;
size_t converted = 0;
char *CStr;
CStr=(char*)malloc(len*sizeof(char));
wcstombs_s(&converted, CStr, len, WStr, _TRUNCATE);
这时WStr中的内容将被转化为char版本储存在CStr中。
wcstombs和mbstowcs是C/C++的实现,WideCharToMultiByte和MultiByteToWideChar是Windows API的实现。
一、UNICODE转ANSI
char* WideChartoAnsi(wchar_t * pWideChar)
{
if (NULL == pWideChar)
return NULL;
char* pAnsi = NULL;
int needBytes = WideCharToMultiByte(CP_ACP,0,pWideChar,-1, NULL,0, NULL, NULL);
if (needBytes >0)
{
pAnsi = new char[needBytes + 1];
ZeroMemory(pAnsi, needBytes + 1);
WideCharToMultiByte(CP_ACP, 0, pWideChar, -1, pAnsi,needBytes, NULL, NULL);
}
return pAnsi;
}
二、ANSI转UNICODE
wchar_t* MultiByteToWide(char* pMultiChar)
{
if (!pMultiChar)
return NULL;
wchar_t* pWideBuf = NULL;
int needWideBytes = MultiByteToWideChar(CP_ACP, 0, pMultiChar, -1, NULL, NULL);
if (needWideBytes >0)
{
pWideBuf = new wchar_t[needWideBytes + 1];
ZeroMemory(pWideBuf, (needWideBytes+1) * sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, 0, pMultiChar, -1, pWideBuf, needWideBytes);
}
return pWideBuf;
}
还需要注意缓冲的释放。否则内存泄露。
关于C++中的char*与wchar_t*这两种类型的相互转换,网上说的大多很繁琐,可行性也不高。下面这个方法是在MSDN里面找到的,个人认为还比较不错:
把char*转换为wchar_t*
用stdlib.h中的mbstowcs_s函数,可以通过下面的例子了解其用法:
char *CStr = "string to convert";
size_t len = strlen(CStr) + 1;
size_t converted = 0;
wchar_t *WStr;
WStr=(wchar_t*)malloc(len*sizeof(wchar_t));
mbstowcs_s(&converted, WStr, len, CStr, _TRUNCATE);
其结果是WStr中储存了CStr的wchar_t版本。
把wchar_t*转换为char*
和上面的方法类似,用stdlib.h中的wcstombs_s函数,例子:
wchar_t *WStr = L"string to convert";
size_t len = wcslen(WStr) + 1;
size_t converted = 0;
char *CStr;
CStr=(char*)malloc(len*sizeof(char));
wcstombs_s(&converted, CStr, len, WStr, _TRUNCATE);
这时WStr中的内容将被转化为char版本储存在CStr中。
另外还可以通过流的方法来char*类型转换为wchar_t*类型,但这样的转换得到的结果将是const类型,而类似的方法不能将wchar_t*类型转换为char*类型。
把(const)char*转换为const wchar_t*
需要用到 sstream 头文件:
char *cstr="string to convert";
wstringstream wss;
wss<<cstr;
再调用wss.str().c_str(); 即可得到 const wchar_t* 类型的返回值。
虽然stringstream流不能将wchar_t*转换成char*,但可以用来进行数值类型和字符串之间的转换,例如:
double d=2734792.934f;
stringstream ss;
ss<<d;
-
CString和char*的转换及汉字乱码的解决 - [Windows\C++编程]
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://www.blogbus.com/hx1987-logs/211009970.html在VS2005及以上版本的编译器中,默认开启了宽字符UNICODE,这就增加了CString和char*之间的转换难度,在转换到到CString类型时,尤其是涉及到汉字等字符的操作时,有可能会出现乱码的形式。经过测试找到了几种比较简便的转换方式。CString主要包含三个部分:一个是指向某个数据缓冲区的指针,一个是该缓冲区中有效字符的个数,一个是该缓冲区的大小,其中有效字符的个数为0到缓冲区大小减1之间的任何一个整数,(CString也是C风格字符串形式,最后一个字符以\0结尾)。
(1) char*转换成CString类型
方法一
对于仅包括英语字符的字符串,只需要强制类型转换即可,可以使用static_cast完成,例
char * pca = “hello”;
CString cstr = static_cast(pca);
注:1、这里可以直接相等来赋值是因为CString类里面重载了赋值操作符。
2、若含有汉字等,则可能会出现乱码,但是单纯转换英文字符时则比较方便
方法二
对于含有汉字的字符串,可以采用A2W或者A2T函数
例
char * pca = “测试”;
USES_CONVERSION;
CString cstr = A2W( pca );
Or
USES_CONVERSION;
CString cstr = A2T( pca );
注:该方法对于直接初始化的char *可以较好的转换,若对于经过其他处理后的char*可能会出现乱码的情况,比如说你的 char* 是经过strncpy拷贝过来的,则有可能出现问题(没有分析出原因),对于const char*,会尽可能的避免乱码的出现
方法三
采用MultiByteToWideChar函数进行转换
MultiByteToWideChar可以将多字节字符串转换为宽字节字符,具体参数可以参考MSDN。
例:
char * pca = “Test”;
size_t pcaLen = strlen(pca);
//获取多字节字符串的字节数,不包括’\0’截止符
int len = MultiByteToWideChar(CP_ACP, 0, cpc1, pcaLen, NULL, 0 );
//申请UNICODE字符串的存储区
TCHAR * ptChar = new TCHAR[len + 1];//加1包括进’\0’截止符
MultiByteToWideChar r(CP_ACP, 0, pca , pcaLen, ptChar, len );
ptChar[len] = ‘\0’;//单独添加’\0’截止符
CString cstr( ptChar );
Or
CString cstr;
Cstr.Append( ptChar );
注:和方法二一样,该方法对于直接初始化的char *可以较好的转换,若对于经过其他处理后的char*可能会出现乱码的情况,对于const char*,会尽可能的避免乱码的出现
(2) VS2008中CString转换成char*类型
在VS2005之前的编译器中,都是默认关闭UNICODE的,在VS2005以后,打开了对UNICODE的支持。在基于UNICODE的编译系统中,CString存储的字符是wchar_t类型的,因而不能直接进行类似(1)中的强制类型转换,否则编译过程中会报错。
方法一
可以使用宽字节转多字节的函数来实现,函数wcstombs_s(wide char string to multiple byte string)可以实现这个功能,函数声明:
wcstombs_s
(
size_t * pReturnValue //转换后的字符个数
char * mbstr, //转换后的多字节字符串的存储区
size_t sizeInBytes, //转换后的多字节字符串的字节个数,即缓冲区mbstr的大小
const wchar_t *wcstr, //需要转换的宽字符
size_t count //缓冲区的截断方式,常使用_TRUNCATE
)
注:这里的截断方式是指由于缓冲区大小的不同,并不能保证将wchar_t*全部转换成char*,用_TRUNCATE截断功能,当wchar_t*和char*的存储区字节数目相同时,可以完全复制并成功返回;当char*存储区字节长度小于wchar_t*时,复制到最后一个存储字节时,填充\0并成功返回;当char*存储区的长度大于wchar_t*时,会将wchar_t*的字符完全复制并成功返回,(一般情况下都要先计算好wchar_t*的大小并使得char*的大小和其一致)。
例:
CString cstr = _T(“test”);
const size_t pcaSize = cstr.GetLength() *2;
//CString中的GetLength函数获取的是字符的个数,不包括'\0'截止符
char * pca = new char[pcaSize + 1];
size_t sz = 0;
wcstombs_s( &sz, pc, pcaSize, cstr, _TRUNCATE);
pca[pcaSize] = '\0';//单独添加'\0'
Or
CString cstr = _T(“test”);
const size_t pcaSize = (cstr.GetLength() + 1)*2;//包'\0'包括进去
//CString中的GetLength函数获取的是字符的个数
char * pca = new char[cstrsize];
size_t sz = 0;
//这里利用_TRUNCATE功能,多申请了'\0'的存储空间,使得char*pca自动添加'\0'
wcstombs_s( &sz, pca, pcaSize, cstr, _TRUNCATE );
注:
1、char * c = (LPSTR)(LPCTSTR)cstr;只会获取第一个字符
2、有时上述方法不能够获得字符串,例如有时不能获得非根目录下面的文件路径、
3、用这种方法不可以正确显示带有汉字字符的字符串,我在获取文件路径时发现的这个问题
方法二
使用宽字节转ANSI字符形式的函数W2A和T2A函数,他们可以正确转换含有汉字的字符串
例:
CString cstr( _T(“test”) );
USES_CONVERSION;
char * pca = W2A( cstr );
or
USES_CONVERSION;
char * pcb = T2A( cstr );
注:ANSI字符为每个字节表示一个字符,因而可以有256个字符,ASCII码为7位表示一个字符,可以表示128个字符。
方法三
使用宽字节转换为多字节的函数WideCharToMultiByte,具体参数可以查找MSDN。
例:
CString cstr( TEXT(“Test”) );
size_t cstrLen = cstr.GetLenth();//获取的是字符数
int pcaLen = WideCharToMultiChar(CP_ACP, 0, cstr, cstrLen, NULL, 0, 0, 0 );//len为字节数
char * pca = new char[pcaLen + 1];
WideCharToMultiChar(CP_ACP, 0, cstr, cstrLen, pca, pcaLen, 0, 0 );
pca[pcaLen] = ‘\0’;//添加’\0’截止符
以上方法都是在通过搜索论坛和博客并整理而成,同时自己写程序测试过,其中添加了自己的理解,如有不正确,还请见谅。