Unicode简介
Unicode是为了解决ASCII编码紧缺,为了解决ANSI编码分页不一致等问题而产生的编码格式,属于宽字符编码,可以表示65536个字符。
C中的宽字符(Unicode)
c定义并初始化普通字符
char c = 'A';
char * p = "Hello!"
char a[] = "Hello!"; // 全局变量使用
static char a[] = "Hello!"; // 局部变量使用
宽字符
C中的宽字符基于wchar_t数据型态,它在几个表头文件包括WCHAR.H中都有定义,像这样:
typedef unsigned short wchar_t ; // 无符号整形,16位宽
wchar_t c = 'A'; // 以0x41、0x00的顺序保存在内存中
wchar_t * p = L"Hello!" ; // 14字节
static wchar_t a[] = L"Hello!" ;
宽字符链接库函数
char * pc = "Hello!" ;
int iLength = strlen (pc) ; // ASCII 6
wchar_t * pw = L"Hello!";
int iLength = wcslen(pw); // 宽字符 6
维护单一原始码
#define _tcslen wcslen // 定义了_UNICODE,并包含 使用宽字符函数
#define _tcslen strlen // 未定义_UNICODE
typedef wchar_t TCHAR; // 定义了_UNICODE,TCHAR使用宽字符类型
typedef char TCHAR ; // 未定义_UNICODE
#define __T(x) L##x // 定义了_UNICODE,粘贴符号(token paste)
#define __T(x) x // 未定义_UNICODE
#define _T(x)__T(x) // 相同定义宏_T
#define _TEXT(x)__T(x) // 相同定义宏_TEXT
宽字符和 Windows
Windows表头文件类型
在Windows.h里包含Winnt.h, WINNT.H处理基本的Unicode支持。
typedef char CHAR ;
typedef wchar_t WCHAR ; // wc匈牙利标记法
// 8位的char
typedef CHAR * PCHAR, * LPCH, * PCH, * NPSTR, * LPSTR, * PSTR ;
typedef CONST CHAR * LPCCH, * PCCH, * LPCSTR, * PCSTR ;
// 16位的wchar_t
typedef WCHAR * PWCHAR, * LPWCH, * PWCH, * NWPSTR, * LPWSTR, * PWSTR ;
typedef CONST WCHAR * LPCWCH, * PCWCH, * LPCWSTR, * PCWSTR ;
#ifdef UNICODE // 标记是否为UNICODE,将TCHAR定义为一般字符类型
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(quote) L##quote // 定义了UNICODE
#define __TEXT(quote) quote // 未定义UNICODE
#define TEXT(quote) __TEXT(quote)
Windows函数呼叫
#ifdef UNICODE
#define MessageBox MessageBoxW // 宽字符函数
#else
#define MessageBox MessageBoxA // ASCII函数
#endif
Windows的字符串函数
ILength = lstrlen (pString) ;
pString = lstrcpy (pString1, pString2) ;
pString = lstrcpyn (pString1, pString2, iCount) ;
pString = lstrcat (pString1, pString2) ;
iComp = lstrcmp (pString1, pString2) ;
iComp = lstrcmpi (pString1, pString2) ;
以上函数兼容Unicode宽字符
在Windows中使用printf
ASCII | 宽字符 | 常规 | |
---|---|---|---|
参数的变数个数 | |||
标准版 | sprintf | swprintf | _stprintf |
最大长度版 | _snprintf | _snwprintf | _sntprintf |
Windows版 | wsprintfA | wsprintfW | wsprintf |
参数数组的指针 | |||
标准版 | vsprintf | vswprintf | _vstprintf |
最大长度版 | _vsnprintf | _vsnwprintf | _vsntprintf |
Windows版 | wvsprintfA | wvsprintfW | wvsprintf |
格式化消息框
#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
_vsnprintf_s(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 iCmdShow)
{
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;
}