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 简介的更多相关文章

  1. Windows程序设计(第五版)学习:第二章 Unicode简介

    第二章 Unicode简介 1,Windows通过双字节技术DBCS解决这个问题,代码页定义不同的字符集,称为ANSI字符集,比如日文为CP932,韩文为CP949,繁体中文为CP950,简体中文为C ...

  2. windows程序设计简介

    大家好,非常高兴和大家一起分享Windows开发心得,Windows已经诞生很多年了,一直因为它的简单易用而深受欢迎,相信很多人在使用Windows的时候,一定有这样一个想法:希望自己将来可以写一个很 ...

  3. Windows 程序设计

    一.Win32 API /******************************************************************** created: 2014/04/1 ...

  4. Windows程序设计:格式化对话框的设计

    刚开始学习Windows程序设计,磕磕碰碰,先做个小笔记缓缓神经,主要是将MessageBox这个Windows API函数的. MessageBox函数是许多人刚开始学习Windows程序设计或者是 ...

  5. windows程序设计.第一个windos程序

    Windows程序设计(第5版) windows程序需要调用API. 第一个Windows程序 /*HelloMsg.c -- Displays "Hello World!" in ...

  6. Windows程序设计(1)——Win32运行原理(一)

    CPU保护模式与Windows系统 1 Windows多任务 2 虚拟内存 3 处理器的特权级别 内核对象 1 内核对象有什么用 2 对象句柄 3 使用计数 1 CPU保护模式与Windows系统 8 ...

  7. windows程序设计01_utf8编码问题

    坚持与妥协 从学程序的第一天老师就给我们说源代码应该使用utf8保存.因为先入为主,"源代码应该使用utf8"的观念已经在"学院派"出身的程序员脑子里根深蒂固. ...

  8. Windows 程序设计(4) MFC 03 -系列学习

    本文整体目录和绝大部门内容来自 [鸡啄米网站]的MFC系列文章,欢迎支持原创 (一)VS2010/MFC编程入门之前言 VC++全称是Visual C++,是由微软提供的C++开发工具,它与C++的根 ...

  9. Windows编程中UNICODE和_UNICODE定义问题

    Windows编程中UNICODE和_UNICODE定义问题 先转一篇文章: 初学Windows SDK编程时碰到过这个问题,相信很多初学Windows编程的人也都碰到过,后来慢慢搞明白些了,但有时别 ...

  10. 关于《Windows程序设计(第五版)》中一个实例程序的疑问

    最近一直在看Charlse Petzold的<Windows程序设计>,作为一个新得不能再新的新手,只能先照着书的抄抄源码了,之前的例子一直都很正常,但昨天遇到一个很诡异的BUG. 先看实 ...

随机推荐

  1. git如何上传大文件,突破大小限制

    Github中单个文件的大小限制是100MB,为了能突破这个限制,我们需要使用Git Large File Storage这个工具, git lfs install git lfs track &qu ...

  2. man fdisk

    FDISK(8)       Linux Programmer?. Manual/Linux程序手册       FDISK(8) NAME/名称       fdisk - Partition ta ...

  3. python线程池示例

    使用with方式创建线程池,任务执行完毕之后,会自动关闭资源 , 否则就需要手动关闭线程池资源  import threading, time from concurrent.futures impo ...

  4. MJ瀑布流学习笔记

    1. 如果系统自带的布局的话,是这样: //系统自带的UICollectionViewFlowLayout 而不是UICollectionViewLayout UICollectionViewFlow ...

  5. mysql版本

    $ mysql Welcome to the MariaDB monitor.  Commands end with ; or \g. Your MySQL connection id is 4791 ...

  6. tensorflow2 矩阵乘法问题

    tensorflow2再做矩阵相乘的时候如果维度有None,则矩阵相乘结果不对. 也不知道为什么,只能用矩阵对应元素相乘在相加的形式来实现矩阵相乘,这个困扰了我好几天,所以记下来. inputs_ti ...

  7. FastDFS整合SpringBoot(五)

    pom.xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId& ...

  8. spring+hibernate单元测试案例

    1,maven创建web工程 2,导入相关依赖 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmln ...

  9. 关闭本机的代理服务(Proxy)

    若您使用了代理服务(Proxy),可能会导致战网游戏发生网络连接.安装或更新方面的问题.请参考以下步骤来关闭您电脑的网络代理服务. Windows 按下 Windows 按鍵 + R . 在运行框中, ...

  10. jQuery入门教程-文档操作方法

    一.append()和appendTo() 1.1 append()方法 <body> <p>好好学习</p> <button>append() 方法& ...