转自:http://hi.baidu.com/hehehehello/item/dcc44a4a6afc690e6dc2f08b
C++处理中文的问题困扰我很久了。之前一旦遇到中文基本就投诸java怀抱了。
今天看到一个漂亮的c++程序,遂豁然开朗。总结一下分享给大家:
问题描述:
c++ 中 char*/string 形式的字符串无法正确的对中文字符串进行处理(如 find, strlen, substr 等常规操作) 。
比如当你在char* 中 find 英文逗号时,有可能匹配的不只是逗号,还找到了某个汉字的一个字节,而你无法在char*中区分它们。
问题原因:
中文字符长度不固定,按字节处理往往出现乱码或错误分割。在unicode中每个中文为2个字节,而中文中间夹杂的英文和半角标点则仍然是1个字节。
解决方案:
构造三层逻辑结构:输入层、逻辑处理层、输出层。
-- 输入层接收char*输入,并将其转换为wchar*.
-- 逻辑处理层在 wchar* 或 wstring 的基础上进行字符串操作,此时操作最小单位为中文字符,不会再有乱码。
-- 输出层将wchar*的结果再次转换为char* ,返回给外部。
这样,对外部来说,仍然是输入char*, 输出char*, 但在这个过程中不再有分割汉字的操作或乱码。
核心转换代码:
#include<wchar.h> wchar_t * MBCS2Unicode(wchar_t * buff, const char * str) { wchar_t * wp = buff; char * p = (char *)str; while(*p) { if(*p & 0x80) { *wp = *(wchar_t *)p; p++; } else{ *wp = (wchar_t) *p; } wp++; p++; } *wp = 0x0000; return buff; } char * Unicode2MBCS(char * buff, const wchar_t * str) { wchar_t * wp = (wchar_t *)str; char * p = buff, * tmp; while(*wp){ tmp = (char *)wp; if(*wp & 0xFF00){ *p = *tmp; p++;tmp++; *p = *tmp; p++; } else{ *p = *tmp; p++; } wp++; } *p = 0x00; return buff; } wstring str2wstr(string str) { size_t len = str.size(); wchar_t * b = (wchar_t *)malloc((len+)*sizeof(wchar_t)); MBCS2Unicode(b,str.c_str()); wstring r(b); free(b); return r; } string wstr2str(wstring wstr) { size_t len = wstr.size(); char * b = (char *)malloc((*len+)*sizeof(char)); Unicode2MBCS(b,wstr.c_str()); string r(b); free(b); return r; } int wputs(wstring wstr) { wputs(wstr.c_str()); return ; } int wputs(const wchar_t * wstr) { int len = wcslen(wstr); char * buff = (char *)malloc((len * + )*sizeof(char)); Unicode2MBCS(buff,wstr); printf("%s",buff); free(buff); return ; }
=============================================
(另外大家关心的UTF8如何转换,添加一段转自End2012的UTF8--Unicode转换程序)
wchar_t * UTF8ToUnicode( const char* str )
{
int textlen ;
wchar_t * result;
textlen = MultiByteToWideChar( CP_UTF8, , str,-, NULL, );
result = (wchar_t *)malloc((textlen+)*sizeof(wchar_t));
memset(result,,(textlen+)*sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, ,str,-,(LPWSTR)result,textlen );
return result;
}
char * UnicodeToUTF8( const wchar_t* str )
{
char* result;
int textlen;
textlen = WideCharToMultiByte( CP_UTF8, , str, -, NULL, , NULL, NULL );
result =(char *)malloc((textlen+)*sizeof(char));
memset(result, , sizeof(char) * ( textlen + ) );
WideCharToMultiByte( CP_UTF8, , str, -, result, textlen, NULL, NULL );
return result;
}