类型的一种命名约定。为了与C语言和旧代码兼容,在C++标准中保留该类型名。
wchar_t数据类型的具体实现与各个C/C++编译器有关,在Win32和VC中定义为: typedef unsigned short wchar_t; (16位的双字节无符号短整数) 为了实现跨平台(如Win16/32/64),在Windows API中重新定义了多种数据类型。下面是在Win32 API中定义的与(宽)字符有关的部分常用typedef类型:
typedef char CHAR; // 普通字符类型 typedef CHAR *PCHAR, *LPCH, *PCH; typedef CONST CHAR *LPCCH, *PCCH; typedef CHAR *NPSTR, *LPSTR, *PSTR; typedef CONST CHAR *LPCSTR, *PCSTR;
typedef wchar_t WCHAR; // 宽字符类型 typedef WCHAR *PWCHAR, *LPWCH, *PWCH; typedef CONST WCHAR *LPCWCH, *PCWCH; typedef WCHAR *NWPSTR, *LPWSTR, *PWSTR; typedef CONST WCHAR *LPCWSTR, *PCWSTR;
#ifdef UNICODE // 使用Unicode字符 typedef WCHAR TCHAR, *PTCHAR; typedef LPWCH LPTCH, PTCH; typedef LPWSTR PTSTR, LPTSTR; typedef LPCWSTR PCTSTR, LPCTSTR; typedef LPWSTR LP;
#else // 不使用Unicode字符 typedef char TCHAR, *PTCHAR; typedef LPCH LPTCH, PTCH; typedef LPSTR PTSTR, LPTSTR; typedef LPCSTR PCTSTR, LPCTSTR; #endif /* UNICODE */
可见,在Win32 API中,普通字符类型char被重新定义为CHAR、宽字符类型wchar_t
11
被重新定义为WCHAR、当前字符类型被定义为TCHAR。至于TCHAR,到底是普通字符类型还是宽字符类型,则由应用程序项目的字符集属性来决定。当字符集属性取值为“使用Unicode字符集”(ASCII字符和汉字都用两个字节表示)时,TCHAR就是宽字符类型;当字符集属性取值为“使用多字节字符集”(ASCII字符用一个字节表示,而汉字则用三个字节表示)时,TCHAR就是普通字符类型。
字符集属性可以在创建项目时的“MFC应用程序向导”对话框的“应用程序类型”页中,通过选中或去选“使用Unicode库”复选框来设置,参见图2-4。
图2-4 MFC应用程序向导对话框中的使用Unicode库复选框
也可以在创建项目后,通过选中“项目”菜单的“*属性”(其中*为具体的项目名,下同)菜单项,打开“*属性页”对话框,然后在“配置属性”的“常规”属性选卡中的“字符集”选项中进行选择来确定,参见图2-5。
12
图2-5 项目属性页中的字符集选项
2.L转换符和打印格式符
为了将普通字符(串)转换成宽字符(串),可在常数字符(串)前添加了L转换运算符。例如:
wchar_t wch = L'C', *wstr = L\普通字符串转换为宽字符串\MessageBox(L\内存分配出错!\错误\
在诸打印函数中,字符(串)变量所对应的字符和串格式符也从普通字符的%c和%s改为宽字符的%lc和%ls。例如:
wchar_t buf[80];
swprintf_s(buf, 80, L\字符串为:“%ls”,字符为‘%lc’\wstr, wch); MessageBox(buf);
3.宽字符函数
下面是若干常用的宽字符函数(包含在ISO C99 / ISO C++的标准库中,其中的errno_t和size_t被分别定义成int和unsigned int类型): #include
size_t wcslen(const wchar_t *s); // 获取宽字符数组中的字符个数
13
int wprintf(const wchar_t * format, ...); // 格式化打印(显示)输出 int wscanf(const wchar_t * format, ...); // 格式化键盘输入 //格式化串输出和输入:
int swprintf(wchar_t * s, size_t n, const wchar_t * format, ...); int swscanf(const wchar_t * s, const wchar_t * format, ...); // 宽字符串转换为长整数、浮点数和双精度数:
long int wcstol(const wchar_t * nptr, wchar_t ** endptr, int base); float wcstof(const wchar_t * nptr, wchar_t ** endptr); double wcstod(const wchar_t * nptr, wchar_t ** endptr);
#include
2.安全CRT函数
安全CRT函数是微软公司对C/C++语言的扩展。它在原来函数名后添加了“_s”后缀;一般返回出错代码;并将原来的函数返回值,作为一个参数,添加到函数输入参数列表的最后;对带缓冲区参数的函数,还添加了表示缓冲区大小的输入参数,以防止内存溢出。
在VC08中,如果不使用这些安全性函数,编译器会报告警告性错误。 下面是若干常用的安全CRT函数(位于头文件stdio.h、stdlib.h或wchar.h中): // 从标准输入设备(键盘)获取(宽)字符串行:
char *gets_s( char *buffer, size_t sizeInCharacters);
wchar_t *_getws_s( wchar_t *buffer, size_t sizeInCharacters); // (无符号)整数转换为(宽)字符串:
errno_t _itoa_s( int value, char *buffer, size_t sizeInCharacters,
int radix );
errno_t _itow_s( int value, wchar_t *buffer, size_t sizeInCharacters,
int radix );
errno_t _ultoa_s( unsigned long value, char *str, size_t sizeOfstr,
int radix );
14
errno_t _ultow_s( unsigned long value, wchar_t *str, size_t sizeOfstr,
int radix );
// 格式化(串)输入/输出:
int printf_s( const char *format [, argument]... ); int wprintf_s( const wchar_t *format [, argument]... ); int scanf_s( const char *format [, argument]... ); int wscanf_s( const wchar_t *format [, argument]... );
int sprintf_s( char *buffer, size_t sizeOfBuffer, const char *format
[, argument] ... );
int swprintf_s( wchar_t *buffer, size_t sizeOfBuffer, const wchar_t
*format [, argument]...);
int sscanf_s( const char *buffer, const char *format [, argument ] ...); int swscanf_s( const wchar_t *buffer, const wchar_t *format [,
argument ] ...);
int fprintf_s( FILE *stream, const char *format [, argument ]...); int fwscanf_s( FILE *stream, const wchar_t *format [, argument ]... ); int fscanf_s( FILE *stream, const char *format [, argument ]... ); int fwscanf_s( FILE *stream, const wchar_t *format [, argument ]... ); // 串复制:
errno_t strcpy_s( char *strDestination, size_t sizeInBytes, const
char *strSource );
errno_t wcscpy_s( wchar_t *strDestination, size_t sizeInWords, const
wchar_t *strSource ); // 打开文件:
errno_t fopen_s( FILE** pFile, const char *filename, const char
*mode );
errno_t _wfopen_s( FILE** pFile, const wchar_t *filename, const
wchar_t *mode ); // 串转换:
errno_t mbstowcs_s( size_t *pConvertedChars, wchar_t *wcstr, size_t
15