首页 > 自考资讯 > 高考百科

1.4 Unicode简介 unicode 13.0

小条 2024-09-23

现代Windows操作系统有不同的语言版本,可以支持所有国家的现有语言。这就涉及到不同字符集的编码规则。

本节需要学习的知识点:

字符集

C语言字符

宽字符和窗口

1.4.1 字符集

ASCII码半角字符集

现代计算机诞生于美国,计算机支持的第一种语言当然是美式英语。为了能够显示美式英语字符,美国人发明了ASCII码编码规则。 ASCII码使用7位二进制数来定义符号,取值范围为0到127,对应128个字符。如图1-6所示。

a4ffc42866a244c599d670bbf4a026cc~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1727668930&x-signature=KrfsBJA0ELtjRNB3XNAQ7QXyJTE%3D ASCII码有特定的书写规则,是一种非常可靠的代码,广泛应用于计算机键盘、显示器、系统硬件、打印机、字体文件、操作系统和互联网。

ASCII码只能满足美国的需要,而不能满足世界其他国家的文字符号。为了满足欧洲国家的需求,IBM创建了扩展的ASCII码表,使用8位二进制数来表示字符,最多支持256个字符。

为了统一标准,美国国家标准协会(ANSI)制定了统一标准ASCII码。这称为单字节字符集。

将计算机应用到中文、韩语、日语等东亚语言,需要编程多达数万个字符。因此,即使是8位二进制数也是不可能的。正因为如此,二进制数扩展为16位,最多允许写入216个字符,基本上满足了你的需求。

Unicode宽字节字符集

Unicode字符集为16位,最多可支持65536个字符。 Unicode 字符串中的所有字符都是16 位(2 个字节)。这样,世界上书面文本中的每个字符都可以被编码,远远超出了单字节字符集的256 个字符。然而,Unicode 并不完美。 Unicode 字符串消耗的内存是ASCII 字符串的两倍。

这65536个字符可以分为不同的区域。表1-1 显示了其中一些区域以及分配给它们的字母。

16位代码

特点

16位代码

特点

0000-007F

ASCII码

0300-036F

通用识别标记

0080-00FF

拉丁字母

0400-04FF

西里尔字母

0100-017F

欧洲拉丁语

0530-058F

亚美尼亚语

0180-01FF

扩展拉丁语

0590-05FF

希伯来语

0250-02AF

标准拼音

0600-06FF

阿拉伯

02B0-02FF

修改字符

0900-097F

梵文

2E80-2EFF

中文、日文和韩文字符的辅助部首

31C0-31EF

中文、日文、韩文笔画

表1-1 区域字符

目前,大约有29,000 个代码点未分配,但保留供将来使用。此外,大约有6,000 个代码点保留供个人使用。

字符代码UTF-8

Unicode是所有字符的统一编码,字符集只给每个字符一个唯一的编号,并没有规定编号为65的字符如何存储。然而,存储数字为40657的字符需要2个字节的空间,而后面的字符可能需要3甚至4个字节的空间。

这时候,知道用什么规则来存储Unicode字符就很重要了。为了覆盖现有Unicode 中的所有字符,您可以指定将字符存储在4 个字节(即32 位)中。 UTF -32(UTF 代表UCS 转换格式)。尽管UTF-32的规则很简单,但也有明显的缺点。仅使用使用UTF-32 和ASCII 的罗马字符需要的空间是后者的四倍(仅对于每个ASCII 字符)。必须保存1 个字节)。

对于存储和网络传输,通常使用更节省空间的变长编码UTF-8,表示使用1到4个字节来表示字符的8位组的格式。

UTF-8的编码规则如下(U+后面的数字代表Unicode字符编码):

U+ 0000 ~ U+ 007F: 0XXXXXXX

U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX

U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX

U+10000 ~ U+1FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX

正如您所看到的,UTF-8 根据前导标志位的数量实现可变长度。单字节字符只占用一个字节,因此可以包含Unicode中的所有字符,类似于UTF-32,有效减少存储和传输时占用的空间。

当前的Windows 操作系统默认使用Unicode 字符集。

1.4.2 C语言宽字符

由于本书使用C语言实现Windows程序,因此有必要介绍C语言的宽字符集函数。我们刚学C语言的时候用的是ANSI C(美国国家标准编程语言——C),它支持7位ASCII码字符。 ANSI C 还支持中文、日文和韩文版本的Windows 支持的多字节字符集。但是,这些多字节字符集被视为单字节值的字符串。多字节字符集主要影响C 语言运行时函数。相反,宽字符比常规字符更宽,这可能会导致编译问题。

宽字符不一定必须是Unicode。 Unicode 是一种可能的宽字符集。然而,由于本书的重点是Windows而不是抽象的C语言实现,因此本书可以互换使用宽字符和Unicode。

ANSI字符集char数据类型

字符c='A';

变量c需要1个字节来存储表示ASCII字符A的十六进制值0x41。

定义另一个字符串指针。

字符*p;

由于Windows是32位系统,指针变量P需要4个字节的存储空间。

char *p='你好!';

存储字符串需要7个字节的空间,其中之一是字符串末尾的NULL字符。

您还可以定义字符数组。

字符a[10];

编译器为此数组保留10 个字节的空间。 sizeof(a) 表达式返回10。

你也可以写:

char a[]='Hello!';//初始化数组

宽字符集char数据类型

使用Unicode 宽字符不会更改C 语言中的字符数据类型。 char类型仍然代表1个字节的存储,sizeof(char)返回1。理论上,C 中的一个字节可能比8 位长,但对于大多数人来说,一个字节是8 位宽。

C 语言中的宽字符基于wchar_t 数据类型。该数据类型在多个头文件中定义,包括WCHAR.H。

我使用了短typedef wchar_t。

wchar_t 数据类型为16 位宽,类似于无符号短整型。

您可以使用以下语句定义包含单个宽字符的变量:

wchar_t c='A';

变量C 的双字节值是0X0041,它是Unicode 字符A。

当Intel处理器存储多字节值时,它们总是首先存储最低有效字节(小端存储模式),因此这些字节实际上以0x41、0x00的顺序存储在内存中。在检查Unicode 文本的内存存储时,请务必牢记这一点。

wchar_t *p=L'你好!';

大写的L 代表一个长整数,后跟一个左引号。这向编译器表明该字符串是使用宽字符存储的,即每个字符使用2 个字节。指针变量p需要4个字节的存储空间,但是这个字符串需要14个字节的存储空间。

wchar_t a[]=L'你好!';

sizeof(a) 也返回14。

这可能看起来像是一个拼写错误,但引号前的L 非常重要,两个字符之间不应有空格。只有有了这个L,编译器才知道必须使用两个字节来存储字符串中的一个字符。

wchar_t c=L'A';

对于单个字符,可以使用L 前缀来表示宽字符,或者保留默认值,编译器会自动添加0。

C语言标志库函数支持ANSI和宽字符集函数。有关详细信息,请参阅下一节中的表1-2。

1.4.3 Windows宽字符

ANSI 和UNICODE 函数的兼容性

Windows 提供了ANSI 和UNICODE 字符串操作的函数,以及一组与两者兼容的函数。例如:

例子

示例1:

#ifdef 统一码

#define _tcscpy wcscpy

其他的

#define _tcscpy strcpy

#endif

示例2:

#ifdef 统一码

#define 消息框消息框W

其他的

#define 消息框消息框A

#endif //!UNICODE

尖端

1、Windows API函数定义了Unicode函数和相应的ASCII函数,将ASCII字符转换为Unicode字符,并由Unicode函数实现。

2、Windows操作系统中的动态链接库函数名和动态链接库名都是ASCII字符。

Windows头文件的类型

WINDOWS.H 头文件包含许多其他头文件,包括:

WINDEF.H头文件:基本数据类型定义

WINNT.H头文件:负责处理基本的Unicode支持函数。

WINNT.H头文件的开头是一个C头文件CTYPE.H,它定义了wchar_t数据类型。 WINNT.H 头文件定义了两种新的数据类型:CHAR 和WCHAR。

typedef 字符CHAR;

typedef char WCHAR;

CHAR 和WCHAR 是Windows 推荐的数据类型,分别定义8 位和16 位字符。 WCHAR wc 之后的注释建议使用匈牙利表示法来指示这是基于WCHAR 数据类型的变量,即宽字符。

然后,WINNT.H 头文件定义了六种可用作8 位字符串指针的数据类型和四种可用作const 8 位字符串指针的数据类型。

typedef CHAR *PCHAR、*LPCH、*PCH、*NPSTR、*LPSTR、*PSTR;

typedef CONST CHAR *LPCCH、*PCCH、*LPCSTR、*PCSTR;

前缀N 和L 代表近和长,指的是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 和WCHAR 数据类型的不同指针。与TCHAR.H 一样,WINNT.H 将TCHAR 定义为通用字符类型。如果定义了标识符_UNICODE,则指向TCHAR 的指针将定义为WCHAR,而TCAHR 将定义为指向WCHAR 的指针。如果未定义标识符UNICODE,则TCHAR 被定义为char 或指向char 的指针。

#ifdef 统一码

typedef WCHAR TCHAR, *PTCHAR;

typedef LPWSTR LPTCH、PTCH、PTSTR、LPTSTR;

typedef LPCWSTR LPCTSTR;

其他的

typedef char TCHAR, *PTCHAR;

typedef LPSTR LPTCH、PTCH、PTSTR、LPTSTR;

typedef LPCSTR LPCTSTR ;

#endif

当在头文件中定义TCHAR 时,WINNT.H 和WCHAR.H 头文件都会防止重复定义TCHAR 数据类型。 WINNT.H 头文件还定义了一个宏,该宏将L 添加到字符串的第一个引号中。

#define __TEXT(quote) L##quote //UNICODE 已定义

#define __TEXT(quote) quote //UNICODE未定义

无论如何,TEXT宏定义如下:

#define __TEXT(引用) __TEXT(引用)

这些定义允许您在同一程序中混合ASCII 和Unicode 字符串。

Windows NT 从一开始就支持Unicode。这意味着Windows NT 在内部使用16 位字符串。由于世界上许多地方尚未使用16 位字符串,因此Windows NT 操作系统必须频繁地在内部转换字符串。 Windows NT 可以运行专门为ASCII 和UNICODE 编写的程序,或者为ASCII 和Unicode 混合编写的程序。实际上是通过相关的API函数来实现的。

Windows 字符串函数

Microsoft C 包括需要字符串参数的C 语言运行时函数的宽字符和通用版本。然而,Windows 复制了其中一些C 函数。

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 标识符,这些函数支持宽字符串。否则,仅接受常规字符串。

如何在Windows上使用printf

不幸的是,Windows没有标准输入和标准输出的概念,因此不能在Windows程序中使用printf函数。然而,fprintf 和sprintf 函数可以在Windows 程序中使用。

函数原型:

int printf (const char * szFormat,);

int sprintf (char * szBuffer, const char * szFormat,);

sprintf 函数不会将格式化结果写入标准输出,而是将它们存储在szBuffer 缓冲区中。

printf('%i 和%i 之和为%i', 5, 3, 5+3);

功能上相当于:

char szBuffer[100];

sprintf(szBuffer, '%i 和%i 之和为%i', 5, 3, 5+3);

put(szBuffer);

【注意】缓冲区必须足够大。

sprintf 函数还有一个变体函数,即vsprintf 函数。

int sprintf (char * szBuffer, const char * szFormat,)

{

int iReturn;

va_list pArgs;

va_start(pArgs, szFormat);

iReturn=vsprintf(szBuffer, szFormat, pArgs);

va_end(pArgs);

返回iReturn。

}

指C语言变量参数的内容。

由于许多早期的Windows 程序都使用sprintf 和vsprintf 函数,因此Windows API 中添加了两个类似的函数:wsprint 和wvsprintf。

随着宽字符的引入,添加了许多sprintf 函数,如下表所示。

ASCII码

宽字符

普遍的

可变数量的参数

普通版

短跑

swprintf

_stprintf

最大长度版本

_sprintf

_snwprintf

_sntprintf

Windows版本

wsprintf

wsprintfW

wsprintf

指向参数数组的指针

普通版

VSprintf

打印输出

_vstprintf

最大长度版本

_vsnprintf

_vsnwprintf

_vsntprintf

Windows版本

wvsprintfA

wvsprintfW

wvsprintf

表1-2 printf函数

在sprintf 函数的宽字符版本中,字符串缓冲区被定义为宽字符串。该函数的所有宽字符版本都要求格式字符串是宽字符字符串。但是,您有责任确保传递给这些函数的其他字符串也是宽字符串。

常用字符串处理函数对照表

美国国家标准协会

统一码

普遍的

解释

数据类型

(字符.h)

(wchar.h)

(tchar.h)

特点

wchar_t

查尔

特点*

wchar_t*

查尔*

LPSTR

LPWSTR

LPTSTR

线性PCSTR

LPCWSTR

LPCTSTR

字符串转换

阿托伊

_wtoi

_土井

将字符串转换为整数(int)

阿瑟尔

_wtol

_ttol

将字符串转换为长整型。

阿托夫

_wtof

_tstof

将字符串转换为浮点数(双精度)。

伊托亚

_itow

_伊托

将任何类型的数字转换为字符串

字符串操作

斯特伦

惠斯伦

_tcslen

获取字符串数量

结构体

wcscpy

_tcscpy

复制字符串

结构体

wcsncpy

_tcsncpy

与strcpy/wcscpy类似,但指定副本数。

STRCMP

西西康普

_tcscmp

比较两个字符串

STRNCMP

西西尼康普

_tcsncmp

与strcmp/wcscmp 类似,但指定要比较的字符串数量。

斯特拉卡特

世界猫

_tcscat

将一个字符串附加到另一个字符串的末尾

字符串猫

网络猫

_tcsnccat

与strcat/wcscat 类似,但指定粘合字符串的粘合长度。

拉紧

西西

_tcshr

查找子串的第一个位置

延长

WCSRCR

_tcsrchr

查找子字符串末尾的第一个匹配项。

斯特普布克

西斯普布鲁克

_tcspbrk

查找一个字符串中的任何字符在另一个字符串中第一次出现的位置。

斯特斯特

wcsstr/wcswcs

_tcsstr

查找字符串中另一个字符串的第一次出现

字符串

西西斯普恩

_tcscspn

返回不包含第二个字符串的第一个数字。

字符串

华西斯普恩

_tcsspn

返回包含第二个字符串的第一个数字。

斯特拉谈话

灯芯库存

_tcstok

根据标识符将字符串拆分为一系列字符串。

西坐标宽度

获取宽字符串的宽度

厕所宽度

获取宽字符宽度

字符串测试

伊萨斯基

伊斯瓦西人

_istacii

测试字符是否为ASCII 字符。即判断c是否在0~127范围内。

伊萨努姆

伊斯瓦南

_istalnum

测试一个字符是数字还是字母

阿尔法

伊斯瓦尔法

_伊斯塔法

测试一个字符是否是一个字符

iscntrl

是wcntrl

_istcntrl

测试一个字符是否是控制字符

这是一个数字

这是一个数字

_istdigit

测试一个字符是否是数字

伊斯格拉夫

冰图

_istgraph

测试字符是否为可显示字符

低的

爱笑的人

_伊斯特鲁

测试字符是否为小写

印刷

打印

_istprint

测试字符是否可打印

被打断

我有一只轮胎瘪了

_istpunct

测试一个字符是否是标点符号

空间

空间空间

_istspace

测试字符是否为空白字符

上面是

伊斯瓦珀

_istupper

测试字符是否为大写

是x数字

是wx数字

_istxdigital

测试字符是否为十六进制数字

大小写转换

底部

塔塔

_ 及以下

将字母转换为小写

塔珀

脚趾上部

_totupper

将字母转换为大写

人物比较

斯特拉科莱

瓦斯科科尔

_tcscoll

比较字符串

日期和时间转换

填充时间

时间

_tcsftime

根据指定的字符串格式和区域设置设置日期和时间的格式

时间

根据指定格式将字符串转换为时间值。这是strftime的逆过程。

打印和扫描字符串

打印

打印函数

_tprintf

使用可变长度参数格式化输出到标准输出

打印函数

打印输出

_ftprintf

具有可变参数的格式化输出

扫描仪

扫描仪

_tscanf

从标准输入格式化读取

扫描仪

扫描仪

_ftscanf

格式化读取

短跑

swprintf

_stprintf

根据vararg参数表将其格式化为字符串。

扫描仪

扫描仪

_stscanf

读取格式化字符串

打印函数

打印输出

_vftprintf

使用stdarg 参数表将输出格式化为文件

打印函数

使用stdarg 参数表将输出格式化为标准输出

VSprintf

打印输出

_vstprintf

格式化stdarg 参数表并写入字符串

sprintf_s

swprintf_s

_stprintf_s

格式字符串

数字化转型

支撑

沃斯托德

_tcstod

将字符串的第一部分转换为双精度浮点数。

斯特拉特尔

维克斯塔尔

_tcstol

将字符串的第一部分转换为长整数

斯特拉图尔

惠斯托尔

_tcstoul

将字符串的第一部分转换为无符号长整数。

_strtoi64

_wcstoi64

_tcstoi64

输入/输出

弗吉特

fgetwc

_fgettc

从流中读取字符并将其转换为宽字符

弗格茨

弗吉特斯

_fgetts

从流中读取字符串并将其转换为宽字符串。

弗普特克

fputwc

_fputtc

将宽字符转换为多字节字符并输出到标准输出

输出量

弗普特斯

_fputts

将宽字符串转换为多字节字符并将其打印到标准输出字符串。

得到

上厕所

_gettc

从标准输入读取字符并将其转换为宽字符。

明白了

获得

_getchar

从标准输入读取字符

普奇

放厕所

_puttc

标准输出

投手

普查尔

_puttchar

标准输出

ETC。

无法获得

_ungettc

返回字符到输入流

表1-3 常用字符串处理函数对比表

版权声明:本文转载于网络,版权归作者所有。如有侵权,请联系本站编辑删除。

猜你喜欢