第2章,[标签 Win32] :宽字符库函数

专栏导航

上一篇:第2章,[标签 Win32] :char 数据类型与 Unicode 字符

回到目录

下一篇:第2章 :编写兼容多字节字符集和 Unicode 字符集的 Windows 程序

本节前言

早在预备章节里面,我花费了几篇文章的篇幅,讲解了几个字符串函数。包括 strcmp,strcat,strlen 等等的字符串操作函数。

这些个字符串操作函数,在编程之中,去使用它们,可以为我们带来很大的方便。在 Windows 程序设计里面,如果可以的话,我们也希望使用它们,为我们的编程,提供许多的便利。

然而呢,strlen 等等的字符串函数,它们所操作的字符串,都是说,每一个字符,都是一个单字节的 char 型数据,而不是 2 字节的 Unicode 字符。而在 Windows 程序设计里面,相当多的时候,我们很可能会需要去使用,能够操作 Unicode 字符的宽字符串函数。

本节呢,我们要讲解的,是与操作 char 型字符的字符串函数相对应的,能够操作 Unicode 字符的字符串函数。以 strlen 为例,我们希望,有这样的一个函数,它呢,能够计算 Unicode 字符串的有效字符长度。

想要学习本节,你首先需要理解 Unicode 字符。如果还不理解 Unicode 字符的基本概念,请先学习下面的两个链接所示的文章。

参考课节:第2章 :Unicode 由来简述

参考课节:第2章 :char 数据类型与 Unicode 字符

在你理解了上述两篇文章的基础上,我们接着往下学习。

一.    计算字符串长度

在下面的文章链接里面,我们讲解 strlen 函数。

编程技能:字符串函数05,strlen

使用 strlen 函数,可以计算一个,由 char 型字符组成的字符串的有效字符长度,这个长度不包含末尾的 NUL 字符。

请看代码。

char ch[] = "Hello";
int len = strlen(ch);

在上面的代码块里面,首先呢,我们定义了未指定长度的 ch 字符数组,每一个元素都是 char 型的。

然后呢,通过调用 strlen,我们可以计算出 ch 字符串的有效字符长度,这个长度被保存在 int 型变量 len 之中。

我们可以看出来,len 的结果,会是 5 。因为字符串 "Hello" 里面包含着 5 个有效 char 型字符。

现在呢,我们来尝试着改动一下上面的代码块。

wchar_t wch[] = L"Hello";
int len = strlen(wch);

在这个代码块里面,我们将原本的 char 型字符数组,改为了 Unicode 字符数组。

然后呢,我们尝试着用 strlen 函数来计算 Unicode 字符串 wch 的有效字符长度。

这个代码,在 VS2019 里面,它是会报错的。

报错的信息大概如下。

【wchar_t *】类型的实参与【const char *】类型的实参不兼容,

在 strlen 函数里面,参数部分,需要的是一个【const char *】类型的字符指针。也就是说,它需要的是一个字符串指针,这个字符串里面的字符,是 char 型字符。

而 wch 字符串,它里面的每一个字符,都是 wchar_t 类型的字符,是 Unicode 字符。结果呢,将一个 Unicode 字符串指针传递给 strlen 函数的【const char *】实参,类型不兼容,无法通过编译。

为了通过编译,我们可以这样子来修改着代码。

wchar_t wch[] = L"Hello";
int len = strlen((char *)wch);

这回呢,就可以在 VS2019 里面通过编译了。

然而,在执行的时候,len 变量的值,并不是 5,而是 1 。

为啥呢?

我们在上一节里面,讲解了英特尔的小端字节序。如果你此刻不清楚英特尔小端字节序,请参考下述文章的第一分节,来学习这个知识。

 参考课节:第2章 :Unicode 由来简述

wch 字符串里面的各个字符,包括结尾的 NUL 字符在内,它们的 Unicode 编码分别如下。

0x0048  0x0065  0x006C  0x006C 0x006F 0x0000

由于英特尔是小端字节序,所以呢,这些个数,在内存里面,是这样子来排布的。

0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x00, 0x00

当我们使用 strlen 函数来计算字符串的长度的时候,它遇到了第一个 0 就会停下来了。在上面的排布里面,第一个 0,是在 0x48 的右边,此时呢,在 0 之前,仅有 0x48 一个有效的非零 ASCII 码,所以呢,strlen 会返回 1 值。

从 strlen 函数的例子,我们大概可以看出。很多的处理 char 型字符的字符串函数,不能够直接用来处理,由 Unicode 字符组成的 Unicode 字符串。

所以呢,我们需要去想办法,去找到那个,能够直接处理 Unicode 字符的字符串函数。

这种字符串函数,要么是我们自己去写,要么呢,就是别人已经写好了,我们拿过来直接用。

微软已经为我们考虑好了这个问题。也就是,在 Windows SDK 里面,已经有了直接可以处理 Unicode 字符串的函数,我们可以直接用。

宽字符版本的 strlen,叫做 wcslen。我们可以分解一下 wcslen 这个函数名。它的英文分解为:wide charity string length 。strlen 定义在 string.h 中,wcslen 定义在 Wchar.h 中。在使用 C++ 的时候,如果你需要使用 strlen,你也可以不包含 string.h,而是包含 cstring,并且使用 std 命名空间。

strlen 函数的声明如下。

size_t __cdecl strlen(const char *);

wcslen 函数的声明如下。

size_t __cdecl wcslen(const wchar_t *);

在上面的两个声明里面,size_t 就是 unsigned int 。 __cdecl 标识的,是一种调用约定。一般地,Windows API 函数,用的多是标准调用,标识符为 __stdcall 。而普通的函数,用的调用约定,多是 CDECL 调用约定,标识符为 __cdecl 。

不同的调用约定的具体内容,我们此刻先不用管。因为,你想要深入地去理解的话,你至少需要了解汇编语言的知识。甚至,有可能还需要去了解编译器的原理。

在当前阶段,编译器的代码,我还没有去研究过。汇编语言我虽然会,但是呢,我假定你还没有学习过汇编语言。我假定,你是在学习过了 C/C++ 基础知识以后,来学习的本专栏的内容。在这样的假定之下,对应调用约定这样的东西,你有一个初步的了解,知道有这个东西就可以了,暂时不需要去深究。

所以呢,上述的两个计算字符串函数的声明,你可以大致地将其理解为下面的声明方式。

unsigned int strlen(const char *);

unsigned int wcslen(const wchar_t *);

能理解上面的这俩简化了的声明代码,就可以算作是合格了。

我相信你能够做得到。

使用 wcslen 的代码如下所示。

wchar_t wch[] = L"Hello";
int len = wcslen(wch);

这回呢,wcslen 可以返回 Unicode 字符串的正确的有效长度,5 。并且呢,这个有效长度会被赋值给 int 型变量 len 。

有的同学呢,可能会对这个返回值有疑问,为啥不是返回 10,而是返回 5 。这个是因为,wcslen 也好,strlen 也好,它们所返回的,是有效字符的个数,而不是有效字符的字节数。

以 wcslen 为例,它返回的是字符串中包含的有效的 Unicode 字符的个数,不包含结尾的 NUL 字符。

在以后的 Windows 程序设计的学习中,你都需要注意看一看,某一个 Windows API,它的某一个参数或者返回值,所需要的是字节数,还是字符个数。字节数与字符个数,在处理 char 型字符的普通 C 字符串的时候,它俩是一样的。而在处理 Unicode 字符的 Unicode 版本的函数中,字节数就不等于字符个数了,而是等于字符个数乘以 2 。

遇到有不懂的,随时去查阅吧。

在浏览器里面搜索,最好是在微软的必应搜索引擎里面去搜索。因为,对于 Windows 程序设计,里面的相应的问题,你在必应搜索引擎里面去查阅信息的时候,浏览器给出的词条,默认地,以微软的 MSDN 为优先,其次是 优快云 。而 MSDN 与 优快云 的反馈词条,一般地,都是我们所需要的东西。

二.    其它的宽字符串函数

字符串函数,不止是 strlen,还有 strcmp,strcat 等等。那么,它们是不是也会有对应的 Unicode 版本呢?

是的。

一般地,处理 char 型字符的字符串函数,都是以 str 为前缀。比如 strlen,strcat,strcpy,等等。

而相对应地,处理 Unicode 字符的字符串函数,都是以 wcs 为前缀。比如,wcslen,wcscat,wcscpy,等等。

总之呢,某一个处理 char 型字符的字符串函数,所对应的 Unicode 版本,只是将 str 前缀,换成 wcs 前缀。并且呢,你需要将 string.h 头文件,换成是 Wchar.h 头文件。

所有 C 语言中的那些,使用字符串参数的运行库函数,都有对应的 Unicode 版本。例如,我们比较常用的 printf 函数,也有对应的 Unicode 版本,它是 wprintf 函数。只是在使用 Unicode 字符串函数的时候,别忘了将 str 前缀 换成 wcs 前缀,并且要包含有 Wchar.h 头文件。

而处理 char 型字符的字符串函数,它们是包含在 string.h 头文件里面的。

结束语

在写作本节之前,我还在犯愁呢,不知道要咋去写。

好在,真的去写的时候,感觉还好。

本节的写作,我觉得很满意,很开心。

当然了,我也希望,你学习本节的时候,也觉得学得很顺利,很开心。

专栏导航

上一篇:第2章,[标签 Win32] :char 数据类型与 Unicode 字符

回到目录

下一篇:第2章 :编写兼容多字节字符集和 Unicode 字符集的 Windows 程序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值