在UNICODE介绍中已经说到,windows使用的Unicode实际上就是UCS-2,也就是说每个Unicode字符其实是两个byte的。因此,我们就不要使用char来存放字符了,放不下的,我们应该使用其他的类型,这里就给大家介绍一下在Windows编程中关于Unicode的处理。

数据类型

通用类型

首先我们需要知道在C/C++数据类型中有个 内置的数据类型wchar_t *,不知道你注意过没有,他是至少2个字节的,也有可能是4个字节,因此,用来存放UCS-2足以。
这里需要注意的是 wchar_t 是平台无关的,不仅仅Windows可以使用,Linux也可以使用。

Windows专用

Windows定义了自己的UNICODE数据类型,分别是:

数据类型 含义
WCHAR Unicode 字符
PWSTR WCHAR*
PCWSTR CONST WCHAR*

UNICODE 常量

为了让我们定义的字符串常量使用 UNICODE 编码,我们可以在字符串前面加个 “L”,

  1. #include <Windows.h>
  2. WCHAR *wcs = L“这是UNICODE编码的字符串”

ANSI和UNICODE通用

有时,我们不知道是该使用ANSI还是UNICODE,这时,我们就可以使用通用的编写方式,不过会稍微麻烦一些。但是,我们不需要关注使用的ANSI还是UNICODE编码。

通用的方式就是统一使用TCHAR表示字符,对字符串常量使用_TEXT宏。

  1. TCHAR *strs = _TEXT("我不需要关心这里使用什么编码")
  2. `

此外,_TEXT不仅可以作用于字符串,还可以作用于字符,例如,可以这样使用

  1. if (strs[0] == _TEXT('中'))
  2. {
  3. ...
  4. }

ANSI和UNICODE互相转换

要对ANSI和UNICODE进行互相转换,我们可以使用函数MultiByteToWideChar和WideCharToMultiByte。

MultiByteToWideChar

MultiByteToWideChar用于将多字节字符串转换成宽字符串,这里给出他的函数原型:

  1. int MultiByteToWideChar(
  2. UINT uCodePage, //指定执行转换的代码页
  3. DWORD dwFlags, //这个一般不使用,设置为0
  4. PCSTR pMultiByteStr, //需要转换的字符串
  5. int cchMultiByte, //需要转换字符串的长度,字节数.如果设置为-1,则这个函数返回源字符串的长度
  6. PWSTR pWideCharStr, //结果字符串
  7. int cchWideChar //结果字符串的最大长度,不是字符串的长度。如果设置为0,则该函数不进行转换,而是返回需要的长度。
  8. )

WideCharToMultiByte

WideCharToMultiByte用于将宽字符转换成多字节字符串,这里同样给出它的函数原型:

  1. int WideCharToMultiByte(
  2. UINT CodePage, //指定执行转换的代码页
  3. DWORD dwFlags, //这个一般不使用,设置为0
  4. LPCWSTR lpWideCharStr, //要转换为宽字节字符串
  5. int cchWideChar, //需要转换的字符串的字符个数,如果设置为-1,则这个函数不进行转换,返回源字符串的长度
  6. LPSTR lpMultiByteStr, //结果字符串
  7. int cchMultiByte, //结果字符串的最大长度,如果设置为0,这个函数不转换,返回结果字符串需要的长度。
  8. LPCSTR lpDefaultChar, //遇到一个不能转换的宽字符,函数便会使用这个字符。
  9. //如果为NULL,则使用默认字符,通常为'?',对文件名有危险!!因为表示通配符。
  10. LPBOOL pfUsedDefaultChar //至少有一个字符不能转换为其多字节形式,函数就会把这个变量设为TRUE
  11. )

下面给出一个ANSI和UNICODE互转的例子:

  1. wstring ANSIToUnicode( const string& str )
  2. {
  3. int len = 0;
  4. len = str.length();
  5. int unicodeLen = ::MultiByteToWideChar( CP_ACP, 0, str.c_str(), -1, NULL, 0 );
  6. wchar_t * pUnicode;
  7. pUnicode = new wchar_t[unicodeLen+1];
  8. memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
  9. MultiByteToWideChar( CP_ACP, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen );
  10. wstring rt;
  11. rt = ( wchar_t* )pUnicode;
  12. delete pUnicode;
  13. return rt;
  14. }
  15. string UnicodeToANSI( const wstring& str )
  16. {
  17. char* pElementText;
  18. int iTextLen;
  19. iTextLen = WideCharToMultiByte( CP_ACP, 0, str.c_str(), -1, NULL, 0, NULL, NULL );
  20. pElementText = new char[iTextLen + 1];
  21. memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
  22. WideCharToMultiByte( CP_ACP, 0, str.c_str(), -1, pElementText, iTextLen, NULL, NULL );
  23. string strText;
  24. strText = pElementText;
  25. delete[] pElementText;
  26. return strText;
  27. }
  28. wstring UTF8ToUnicode( const string& str )
  29. {
  30. int len = 0;
  31. len = str.length();
  32. int unicodeLen = ::MultiByteToWideChar( CP_UTF8, 0, str.c_str(), -1, NULL, 0 );
  33. wchar_t * pUnicode;
  34. pUnicode = new wchar_t[unicodeLen+1];
  35. memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
  36. MultiByteToWideChar( CP_UTF8, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen );
  37. wstring rt;
  38. rt = ( wchar_t* )pUnicode;
  39. delete pUnicode;
  40. return rt;
  41. }
  42. string UnicodeToUTF8( const wstring& str )
  43. {
  44. char* pElementText;
  45. int iTextLen;
  46. iTextLen = WideCharToMultiByte( CP_UTF8, 0, str.c_str(), -1, NULL, 0, NULL, NULL );
  47. pElementText = new char[iTextLen + 1];
  48. memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
  49. WideCharToMultiByte( CP_UTF8, 0, str.c_str(), -1, pElementText, iTextLen, NULL, NULL );
  50. string strText;
  51. strText = pElementText;
  52. delete[] pElementText;
  53. return strText;
  54. }

参考