Windows程序设计--(二)Unicode 简介
2.2 宽字符和C语言
2.2.2 更宽的字符
在C语言中的宽字符正是基于short型数据的, 这一数据类型在头文件WCHAR.H中的定义为:
typedef unsigned short wchar_t ;
所以C语言中的宽字符wchar_t数据类型与一个无符号短整形unsigned short一样, 都是16位宽。
例如:
wchar_t c = 'A' ;
在计算机中保存为0x0041,显示为0x41 0x00
2.2.3 宽字符库函数
在使用strlen计算宽字符长度时:
#include <stdio.h>
#include <string.h> int main()
{
wchar_t *p = L"Hello" ;
printf( "%d\n", strlen(p) ) ; return ;
}
运行后显示的结果为1, 很显然, 它没有求出正确的长度, 这是因为, 宽字符字符串"Hello"在一段内存中存储的值如下:
48 00 65 00 6C 00 6C 00 6F 00 21 00
这是因为当strlen找到该字符串的第一个0时就认为该字符串已经结束了, 所以得到的长度为1, strlen统计到的这一个字符即为0x48表示的'H'。
我们使用wcslen函数计算宽字符长度。同样的还有
函数名 |
函数原型 |
函数功能 |
返回值 |
wcscat |
wchar_t *wcscat(wchar_t *s1, const wchar_t *s2); |
将s2所指的字符串连接到s1后面 |
s1所指字符串的首地址 |
wcschr |
wchar_t *wcschr(const wchar_t *s, wchar_t c); |
在s字符串中找到c字符第一次出现的位置 |
若找到, 则返回该字符的地址, 否则返回NULL |
wcscmp |
int wcscmp(const wchar_t *s1, const wchar_t *s2); |
让字符串s1与字符串s2进行比较 |
s1 < s2, 返回负数; s1 == s2, 返回0;s1 > s2, 返回正数 |
wcscpy |
wchar_t *wcscpy(wchar_t *s1, const wchar_t *s2); |
将s2所指字符串覆盖方式复制到s1中 |
s1所指的字符串的首地址 |
wcslen |
size_t wcslen(const wchar_t *s); |
求s所指字符串的长度 |
返回有效字符的个数 |
wcsstr |
wchar_t * wcsstr(const wchar_t *s1, const wchar_t *s2); |
找出字符串s2在字符串s1中第一次出现的位置 |
若找到, 则返回该位置的地址, 否则返回NULL |
2.2.4 维护一个源代码文件
使用TEXT可以避免使用 L"hello"直接使用TEXT("hello")
追溯定义TEXT的地方发现已经加了L
#define TEXT(quote) __TEXT(quote) // r_winnt #define __TEXT(quote) L##quote // r_winnt
因此使用TEXT或者_TEXT都可以不用谢L了
2.3 宽字符和Windows
2.3.1 Windows头文件的类型
一个Windows程序包括表头文件WINDOWS.H。该文件包括许多其它表头文件,包括WINDEF.H,该文件中有许多在Windows中使用的基本型态定义,而且它本身也包括WINNT.H。WINNT.H处理基本的Unicode支持。
WINNT.H的前面包含C的表头文件CTYPE.H,这是C的众多表头文件之一,包括wchar_t的定义。WINNT.H定义了新的数据型态,称作CHAR和WCHAR:
typedef char CHAR ;
typedef wchar_t WCHAR ; // wc
当您需要定义8位字符或者16位字符时,推荐您在Windows程序中使用的数据型态是CHAR和WCHAR。WCHAR定义后面的注释是匈牙利标记法的建议:一个基于WCHAR数据型态的变量可在前面附加上字母wc以说明一个宽字符。
WINNT.H表头文件进而定义了可用做8位字符串指针的六种数据型态和四个可用做const 8位字符串指针的数据型态。这里精选了表头文件中一些实用的说明数据型态语句:
typedef CHAR * PCHAR, * LPCH, * PCH, * NPSTR, * LPSTR, * PSTR ;
typedef CONST CHAR * LPCCH, * PCCH, * LPCSTR, * PCSTR ;
前缀N和L表示「near」和「long」,指的是16位Windows中两种大小不同的指标。在Win32中near和long指标没有区别。
类似地,WINNT.H定义了六种可作为16位字符串指针的数据型态和四种可作为const 16位字符串指针的数据型态:
typedef WCHAR * PWCHAR, * LPWCH, * PWCH, * NWPSTR, * LPWSTR, * PWSTR ;
typedef CONST WCHAR * LPCWCH, * PCWCH, * LPCWSTR, * PCWSTR ;
至此,我们有了数据型态CHAR(一个8位的char)和WCHAR(一个16位的wchar_t),以及指向CHAR和WCHAR的指标。与TCHAR.H一样,WINNT.H将TCHAR定义为一般的字符类型。如果定义了标识符UNICODE(没有底线),则TCHAR和指向TCHAR的指标就分别定义为WCHAR和指向WCHAR的指标;如果没有定义标识符UNICODE,则TCHAR和指向TCHAR的指标就分别定义为char和指向char的指标:
#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
如果已经在某个表头文件或者其它表头文件中定义了TCHAR数据型态,那么WINNT.H和WCHAR.H表头文件都能防止其重复定义。不过,无论何时在程序中使用其它表头文件时,都应在所有其它表头文件之前包含WINDOWS.H。
WINNT.H表头文件还定义了一个宏,该宏将L添加到字符串的第一个引号前。如果定义了UNICODE标识符,则一个称作 __TEXT的宏定义如下:
#define __TEXT(quote) L##quote
如果没有定义标识符UNICODE,则像这样定义__TEXT宏:
#define __TEXT(quote) quote
此外, TEXT宏可这样定义:
#define TEXT(quote) __TEXT(quote)
这与TCHAR.H中定义_TEXT宏的方法一样,只是不必操心底线。我将在本书中使用这个宏的TEXT版本。
这些定义可使您在同一程序中混合使用ASCII和Unicode字符串,或者编写一个可被ASCII或Unicode编译的程序。如果您希望明确定义8位字符变量和字符串,请使用CHAR、PCHAR(或者其它),以及带引号的字符串。为明确地使用16位字符变量和字符串,请使用WCHAR、PWCHAR,并将L添加到引号前面。对于是8位还是16位取决于UNICODE标识符的定义的变量或字符串,要使用TCHAR、PTCHAR和TEXT宏。
2.3.2 Windows函数调用
MessageBoxA:
WINUSERAPI int WINAPI MessageBoxA (HWND hWnd, LPCSTR lpText,
LPCSTR lpCaption, UINT uType) ;
下面是MessageBoxW:
WINUSERAPI int WINAPI MessageBoxW (HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) ;
他们的第2,3个参数都是字符串常量指针
MessageBox会根据参数类型来调用:
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
2.3.3 Windows的字符串函数
下面是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) ;
这些函数与C链接库中对应的函数功能相同。如果定义了UNICODE标识符,那么这些函数将接受宽字符串,否则只接受常规字符串。宽字符串版的lstrlenW函数可在Windows 98中执行。
2.3.4 在Windows中使用printf
在Windows程序中不能使用printf函数,而是使用其他的函数:
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
char szBuffer[];
sprintf(szBuffer, "The Sum of %i and %i is %i\n", , , + );
MessageBox(NULL, szBuffer, TEXT("Hk_Mayfly"), 0x4L | 0x40L); return ;
}
表列出了Microsoft的C执行时期链接库和Windows支持的所有sprintf函数。
ASCII |
宽字符 |
常规 |
|
参数的变数个数 |
|||
标准版 |
sprintf |
swprintf |
_stprintf |
最大长度版 |
_snprintf |
_snwprintf |
_sntprintf |
Windows版 |
wsprintfA |
wsprintfW |
wsprintf |
参数数组的指针 |
|||
标准版 |
vsprintf |
vswprintf |
_vstprintf |
最大长度版 |
_vsnprintf |
_vsnwprintf |
_vsntprintf |
Windows版 |
wvsprintfA |
wvsprintfW |
wvsprintf |
2.3.5 格式化的消息框
#include <windows.h>
#include <tchar.h>
#include <stdio.h> int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...) { TCHAR szBuffer [] ; 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, ) ; } 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 ; }
Windows程序设计--(二)Unicode 简介的更多相关文章
- Windows程序设计(第五版)学习:第二章 Unicode简介
第二章 Unicode简介 1,Windows通过双字节技术DBCS解决这个问题,代码页定义不同的字符集,称为ANSI字符集,比如日文为CP932,韩文为CP949,繁体中文为CP950,简体中文为C ...
- windows程序设计简介
大家好,非常高兴和大家一起分享Windows开发心得,Windows已经诞生很多年了,一直因为它的简单易用而深受欢迎,相信很多人在使用Windows的时候,一定有这样一个想法:希望自己将来可以写一个很 ...
- Windows 程序设计
一.Win32 API /******************************************************************** created: 2014/04/1 ...
- Windows程序设计:格式化对话框的设计
刚开始学习Windows程序设计,磕磕碰碰,先做个小笔记缓缓神经,主要是将MessageBox这个Windows API函数的. MessageBox函数是许多人刚开始学习Windows程序设计或者是 ...
- windows程序设计.第一个windos程序
Windows程序设计(第5版) windows程序需要调用API. 第一个Windows程序 /*HelloMsg.c -- Displays "Hello World!" in ...
- Windows程序设计(1)——Win32运行原理(一)
CPU保护模式与Windows系统 1 Windows多任务 2 虚拟内存 3 处理器的特权级别 内核对象 1 内核对象有什么用 2 对象句柄 3 使用计数 1 CPU保护模式与Windows系统 8 ...
- windows程序设计01_utf8编码问题
坚持与妥协 从学程序的第一天老师就给我们说源代码应该使用utf8保存.因为先入为主,"源代码应该使用utf8"的观念已经在"学院派"出身的程序员脑子里根深蒂固. ...
- Windows 程序设计(4) MFC 03 -系列学习
本文整体目录和绝大部门内容来自 [鸡啄米网站]的MFC系列文章,欢迎支持原创 (一)VS2010/MFC编程入门之前言 VC++全称是Visual C++,是由微软提供的C++开发工具,它与C++的根 ...
- Windows编程中UNICODE和_UNICODE定义问题
Windows编程中UNICODE和_UNICODE定义问题 先转一篇文章: 初学Windows SDK编程时碰到过这个问题,相信很多初学Windows编程的人也都碰到过,后来慢慢搞明白些了,但有时别 ...
- 关于《Windows程序设计(第五版)》中一个实例程序的疑问
最近一直在看Charlse Petzold的<Windows程序设计>,作为一个新得不能再新的新手,只能先照着书的抄抄源码了,之前的例子一直都很正常,但昨天遇到一个很诡异的BUG. 先看实 ...
随机推荐
- 读书笔记二、pandas之DataFrame
注:DataFrame的构造方法与Series类似,只不过同时接受一条一维数据源,每一条都会成为单独的一列. 注意,返回的Series拥有原DataFrame 相同的索引,且其name属性也已经被相应 ...
- 使用GDB调试时attach ID不被允许
在进入gdb后,直接使用attach ID,出现下面的情况: Could not attach to process. If your uid matches the uid of the targ ...
- CSS3选择器 ::selection选择器
“::selection”伪元素是用来匹配突出显示的文本(用鼠标选择文本时的文本).浏览器默认情况下,用鼠标选择网页文本是以“深蓝的背景,白色的字体”显示的,效果如下图所示: 从上图中可以看出,用鼠标 ...
- TreeMap和Comparable接口
备注:HashMap线程不安全,效率高,允许key.value为空 HasTable线程安全.效率低.不允许key或value为空 TreeMap在存储时会自动调用comparable方法进行排序,当 ...
- 载]mysqlhotcopy 热备工具体验与总结
载]mysqlhotcopy 热备工具体验与总结 今天有空尝试了一下MYSQLHOTCOPY这个快速热备MYISAM引擎的工具.(本文是针对单个服务器的情况,以后将会加入多服务器相关操作)他和MYSQ ...
- Zabbix分布式监控系统实践
https://www.zabbix.com/wiki/howto/install/Ubuntu/ubuntuinstall 环境介绍OS: Ubuntu 10.10 Server 64-bitSer ...
- ELK Stack
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11488404.html ELK workflow log -> filebeat -> l ...
- Oracle12c创建及删除PDB
在12C R1版本中只支持Global Shared Undo模式,所有container共享一个UNDO表空间:在12C R2引入了PDB Local Undo模式,每个container都有自己的 ...
- Jenkins slave-agent.jnlp 无法安装为服务(install as a service)
问题: 在部署持续集成环境,配置slave节点时遇到一个问题,slave-agent.jnlp可以正常启动运行(不能正常启动的点这里) 但是在保存为系统服务时,slave-agent.jnlp点击[i ...
- 6 October
P1514 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 \(N\) 行 \(\times M\) 列的矩形,如上图所示, ...