- 2.1 字符编码
本地化的问题就是处理不同字符集的问题。
- 2.2 ANSI字符和Unicode字符与字符串数据类型
在编译器内建对wchar_t的支持之前,ANSI C头文件(<wchar.h>和<wctype.h>)定义了一个wchar_t数据类型。
在Windows头文件WinNT.h中Windows团队定义了自己的数据类型以及可用于处理字符和字符串指针的大量便利的数据类型。
WinNT.h中定义的UNICODE、TEXT宏:
//
// Neutral ANSI/UNICODE types and macros
//
#ifdef UNICODE // r_winnt
#ifndef _TCHAR_DEFINED
typedef WCHAR TCHAR, *PTCHAR;
typedef WCHAR TBYTE , *PTBYTE ;
#define _TCHAR_DEFINED
#endif /* !_TCHAR_DEFINED */
typedef LPWCH LPTCH, PTCH;
typedef LPCWCH LPCTCH, PCTCH;
typedef LPWSTR PTSTR, LPTSTR;
typedef LPCWSTR PCTSTR, LPCTSTR;
typedef LPUWSTR PUTSTR, LPUTSTR;
typedef LPCUWSTR PCUTSTR, LPCUTSTR;
typedef LPWSTR LP;
typedef PZZWSTR PZZTSTR;
typedef PCZZWSTR PCZZTSTR;
typedef PUZZWSTR PUZZTSTR;
typedef PCUZZWSTR PCUZZTSTR;
typedef PNZWCH PNZTCH;
typedef PCNZWCH PCNZTCH;
typedef PUNZWCH PUNZTCH;
typedef PCUNZWCH PCUNZTCH;
#define __TEXT(quote) L##quote // r_winnt
#else /* UNICODE */ // r_winnt
#ifndef _TCHAR_DEFINED
typedef char TCHAR, *PTCHAR;
typedef unsigned char TBYTE , *PTBYTE ;
#define _TCHAR_DEFINED
#endif /* !_TCHAR_DEFINED */
- 2.3 Windows中的Unicode和ANSI函数
调用Windows函数传入的参数如果是ANSI字符串,函数首先会把字符串转换为Unicode字符串,再把结果传给操作系统。执行字符串转换,会产生时空上的开销。
- 2.4 C运行库中的Unicode函数和ANSI函数
tchar.h根据是否定义了_UNICODE宏来决定将相应的字符串宏定义扩展为哪个版本。
- 2.5 C运行库中的安全字符串函数
Microsoft提供了一系列的函数来取代C运行库的不安全的字符串处理函数(在StrSafe.h头文件中定义)。
_countof宏定义计算缓冲区的大小(在stdlib.h中定义)。
所有安全(_s后缀)函数的首要任务是验证传给它们的参数值,检查的项目包括指针不为NULL,整数在有效范围内,枚举值是有效的,缓冲区足以容纳结果数据。检查失败,函数会设置局部于线程的C运行时变量errno。
- 2.8 Unicode与ANSI字符串的转换
int WINAPI MultiByteToWideChar(
_In_ UINT CodePage,
_In_ DWORD dwFlags,
_In_NLS_string_(cbMultiByte) LPCCH lpMultiByteStr,
_In_ int cbMultiByte,
_Out_writes_to_opt_(cchWideChar, return) LPWSTR lpWideCharStr,
_In_ int cchWideChar
);
转换步骤:
- 调用MultiByteToWideChar,lpWideCharStr传入NULL,cchWideChar为0,cbMultiByte为-1,返回值即为转换后需要的字符数(不同于字节数);
- 分配Unicode字符串缓冲区,大小为上一步的返回值* sizeof(wchar_t)(以字节计数);
- 调用MultiByteToWideChar执行转换;
宽字符串 --> 多字节字符串 WideCharToMultiByte
int WINAPI WideCharToMultiByte(
_In_ UINT CodePage,
_In_ DWORD dwFlags,
_In_NLS_string_(cchWideChar) LPCWCH lpWideCharStr,
_In_ int cchWideChar,
_Out_writes_bytes_to_opt_(cbMultiByte, return) LPSTR lpMultiByteStr,
_In_ int cbMultiByte,
_In_opt_ LPCCH lpDefaultChar,
_Out_opt_ LPBOOL lpUsedDefaultChar
);
最后,贴上一段Unicode与ANSI互相转换的代码:
#include <Windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
int main()
{
char * str_ansi = "测试test";
// 转换后需要的字符数
int ilen = MultiByteToWideChar(CP_ACP, 0, str_ansi, -1, NULL, 0);
cout << "iLen: " << ilen <<endl;
// 分配转换后的Unicode字符串缓冲区空间
wchar_t* pWideChars = new wchar_t[ilen];
// 执行转换
MultiByteToWideChar(CP_ACP, 0, str_ansi, -1, pWideChars, ilen * sizeof(wchar_t));
// 输出
setlocale(LC_ALL,"chs");
wcout << pWideChars << endl ;
// 释放空间
if(pWideChars != NULL )
{
delete [] pWideChars;
}
//
wchar_t* str_widechar = TEXT("test测试");
int ibytes = WideCharToMultiByte(CP_ACP, 0, str_widechar, -1, NULL, 0, NULL, NULL);
cout << "ibytes: " << ibytes << endl;
char * pMultiBytes = new char[ibytes];
WideCharToMultiByte(CP_ACP, 0, str_widechar, -1, pMultiBytes, ibytes, NULL, NULL );
cout << pMultiBytes << endl;
if(pMultiBytes != NULL)
{
delete [] pMultiBytes;
}
return 0;
}