Unicode 是ASICII字符集的一个扩展,用16bit来表示所有字符集,windows NT从底层上支持Unicode。而win9X只部分支持unicode.
2.1 字符集简史
ASCII 7位 只能表示标准的美国常用字符
扩展ASCII 8位ASCII码,
2.1.4 双字节字符集
DBCS 前128个代码是ASCII, 较高的128代码中还跟随第二个字节。这两个字节在一起代表一个单独的字符。
代码页 932 日文, 936 简体中文, 949 韩文, 950 繁体中文
为了解析双字节字符串中实际字符的数量,需要从字符串开始一直解析到指针需要的位置。
2.1.5 Unicode的解救方案
通过双字节16bit来表示所有字符集,不再需要代码页。
2.2 宽字节和C语言
宽字符不一定是unicode,unicode只是宽字符编码的一种实现。
2.2.1 char数据类型
2.2.2 wchar_t 宽字符数据类型
2.2.3 宽字符库函数
wcslen strlen
wprintf printf
2.2.4 维护一个源代码文件
TCHAR.h 头文件
_tprintf printfwprintf
_tcslen strlenwcslen
TCHAR char wchar_t
_T(""); __T() _TEXT()
2.3 宽字符和windows
在WINNT.h中包含了CTYPE.h 定义了众多类型
typedef char CHAR;
typedef wchar_t WCHAR; //wc
可用做8位字符串指针的6种数据类型和可用做const8位字符串指针的4种数据类型
typedef CHAR* PCHAR, * LPCH, * PCH, * NPSTR, * LPSTR, * PSTR;
typedef CONST CHAR * LPCCH, *PCCH, * LPCSTR, * PCSTR;
N和L在16位系统中代表近和远,但是在32位系统中没有任何区别
可用作16位字符串指针的6种数据类型和可用作const 16位字符串指针的4种数据类型
typedef WCHAR* PWCHAR, * LPWCH, *PWCH, *NWSTR, *LPWSTR, *PWSTR;
typedef CONST WCHAR* LPCWCH, *PCWCH, *LPCWSTR, *PCWSTR;
#ifdef UNICODE
typedef WCHAR TCHAR , * PTCHAR;
typedef LPWSTR LPTCH, PTCH, PTSTR, LPTSTR;
typedef LPCWSTR LPCTSTR;
#else
typedef char TCHAR, * PTCHAR;
typedef LPSTR LPTCH, PTCH, PTSTR, LPTSTR;
typedef LPCSTR LPCTSTR;
#endif
#define TEXT(x) __TEXT(x)
至于如何选择8位还是16位变量及字符串,则取决于UNICODE标示符是否已被定义以及是否使用TCHAR, PTCHAR和TEXT宏
2.3.2 Windows函数的使用
例如MessageBox 有两个原形
WINUSERAPI int WINAPI MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UNIT uType);
WINUSERAPI int WINAPI MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
除非要明确使用ASCII或者UNICODE否则可以继续使用MessageBox根据是否定义UNICODE标识符来自动选择
2.3.4 在windows中使用printf
windows程序中不存在标准输入和标准输出的概念。所以可以在windows程序使用fprintf,但不能使用printf
sprintf可以继续使用
可以用sprintf 格式化字符串以后再传递给MessageBox
Microsoft 引入了_snprintf 需要制定缓冲区大小
还有一个变形vsprintf
参考书上的表格
一个例子
#include <windows.h> #include <tchar.h> #include <stdio.h> int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, ...) { TCHAR szBuffer[1024]; va_list pArgList; // The va_start macro (defined in STDARG.h) is usually equivalent to: //pArgList = (char *) &szFormat + sizeof(szFormat); va_start(pArgList, szFormat); // The last argument to wvsprintf points to the arguments _vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szFormat, pArgList); // The va_end macro just zeroes out pArgList for no good reason va_end(pArgList); return MessageBox(NULL, szBuffer, szCaption, 0); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int CmdShow) { int cxScreen, cyScreen; cxScreen = GetSystemMetrics(SM_CXSCREEN); cyScreen = GetSystemMetrics(SM_CYSCREEN); MessageBoxPrintf(TEXT("ScrnSize"), TEXT("The screen is %i pixels wide by %i pixels high."), cxScreen, cyScreen); return 0; }执行结果如下:
2.3.6 国际化之于本书
可以参考书籍 Developing International Software for Windows 95 and Windows NT(Microsoft Press, 1995)
使用TCHAR 定义字符串,对字符串文本使用TEXT宏,不要混淆字节和字符。