(delphi11最新学习资料) Object Pascal 学习笔记---第6章第1节(Unicode: 一个适用于整个世界的字母表)

本文主要是介绍(delphi11最新学习资料) Object Pascal 学习笔记---第6章第1节(Unicode: 一个适用于整个世界的字母表),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第6章 字符串

​ 字符串是任何编程语言中都最常用的数据类型之一。在Object Pascal 语言中处理字符串相当简单,速度非常快,而且功能极其强大。尽管字符串的基础知识很容易掌握,而且我在前面的章节中也使用过字符串,但其字符串背后的情况却比乍看起来要复杂一些。文本处理涉及多个密切相关的主题,值得我们深入探讨。要完全理解字符串处理,你需要了解 Unicode 表示法,理解字符串如何映射到字符数组,并学习运行时库中一些最常用的字符串操作,包括把字符串保存文本文件和从文本文件加载字符串。

Object Pascal 有多种字符串操作选项,并提供了不同的数据类型和方法。本章的重点将放在标准字符串数据类型上,但我也会花点时间介绍一些较老的字符串类型,如仍可在 Delphi 编译器中使用的 AnsiString。在此之前,让我Unicode 表示法开始。

6.1 Unicode: 一个适用于整个世界的字母表

Object Pascal 字符串管理的核心是 Unicode 字符集,特别是一种称为 UTF-16 的表示法。在了解字符串的实现技术细节之前,我们值得花几节的篇幅来全面了解 Unicode 标准。

Unicode 背后的理念(这也是它既简单又复杂的原因)是,世界上所有已知字母表中的每一个字符都有相应的描述、图形表示和唯一的数值(称为 Unicode 码点)。

注解:Unicode联盟的参考网站是 http://www.unicode.org,其中有丰富的文档。最终参考是《Unicode标准》书籍,可在 http://www.unicode.org/book/aboutbook.html 找到。

并非所有开发人员都熟悉Unicode,许多人仍然以ASCII和ISO编码等较旧、有限的表示形式来思考字符。通过涵盖这些较旧的标准的简短部分,您将更好地理解Unicode的特殊之处(以及复杂性)。

并非所有开发人员都熟悉 Unicode,许多人仍然认为字符是用 ASCII 等较早的、有限的表示法和 ISO 编码来表示的。通过对这些旧标准的简短介绍,你可以更好地理解 Unicode 的特殊性(和复杂性)。

6.1.1 过去的字符集:从 ASCII 到 ISO 编码

​ 字符表示法始于《美国信息交换标准码》(ASCII),该标准码于 60 年代初制定,是计算机字符的标准编码,包括 26 个小写和大写英文字母、10 个数字、常用标点符号和一些控制字符(至今仍在使用)。

​ ASCII 使用 7 位编码系统来表示 128 个不同的字符。如图 6.1 所示(摘自 Windows 上运行的 Object Pascal 应用程序),只有 #32(空格)到 #126(tilde)之间的字符才有可视化表示。

​ ASCII 固然是一个基础字符集(其 128 个基本字符集至今仍是 Unicode 核心的一部分),但它很快就扩展版本所取代,扩展版本使用第八位添加了另外 128 个字符到字符集中。

​ 现在的问题是,世界上有这么多语言,没有简单的方法来确定字符集(有时表示为ASCII-8)中还包括哪些其他字符。长话短说,Windows 采用了一套不同的字符集,称为编码页,其字符集取决于您的本地配置和 Windows 版本。除了 Windows 编码页之外,还有许多其他类似的标准也基于这种分页方法,这些编码页已成为 ISO 国际标准的一部分。

​ 其中最重要的无疑是 ISO 8859 标准,它定义了多个区域字符集。最常用的一套(准确地说,是大多数西方国家使用的一套)是拉丁字符集,称为 ISO 8859-1。

注解:尽管部分相似,但Windows 1252代码页并不完全符合ISO 8859-1字符集。Windows添加了额外的字符,如€符号、额外的引号等,位于128到150的区域。与拉丁字符集的所有其他值不同,这些Windows扩展与Unicode码点不相符。

6.1.2 Unicode码点和字形

​ 如果我真的想要表述地更准确一点,除了码点的概念之外,我还应该再引入一个概念。实际上,有时多个码点可以用于表示一个字形(视觉字符)。这通常不是一个字母,而是一个字母或字母和符号的组合。例如,如果有一个表示拉丁字母a的码点序列(#$0061)后跟一个表示重音符号的码点(#$0300),则应将其显示为一个重音字符。

​ 在Object Pascal编码术语中,如果您写出以下内容(CodePoints 示例的一部分),信息将有一个单重音字符,如图 6.2 所示。

varStr: String;
beginStr := #$0061 + #$0300;ShowMessage(Str);

图 6.2:一个字形可以是多个码点的结果

​ 在这种情况下,我们有两个字符,代表两个码点,但只有一个字形(或视觉元素)。事实上,在拉丁字母中,您可以使用一个特定的 Unicode 码点来表示给定的字形(带重音的字母 a 的码点是 $00E0),但在其他字母表中,组合Unicode代码点是获得给定图形元素(和正确的输出)的唯一方法。

即使显示的是重音字符,也不会对数值进行自动规范化或转换(只是正确显示),因此字符串的内部结构仍与使用单字符 à 的字符串不同。

注解:用多个代码点呈现字形可能取决于操作系统的具体支持以及正在使用的文本呈现技术,因此您会发现,对于一些字形元素,不是所有操作系统都提供正确的输出。

6.1.3 从码点到字节(UTF)

​ 虽然ASCII对字符到字符的数值表示使用了一种直接且简单的映射,但Unicode使用了一种更复杂的方法。正如我所提到的,Unicode字母表的每个元素都有一个关联的代码点,但到实际表示的映射通常更为复杂。

​ Unicode 背后令人困惑的一点是,在实际存储、物理字节、内存或文件中,有多种方法来表示同一个码点(或 Unicode 字符对应的数值)。

​ 这个问题源于这样一个事实,即以简单和统一的方式表示所有Unicode代码点的唯一方法是为每个代码点使用四个字节。这说明了需要一个固定长度的表示(每个字符总是需要相同数量的字节),但大多数开发人员会认为这在内存占用和处理时间方面太昂贵了。

注解:在Object Pascal中,通过使用UCS4Char数据类型可以实现4字节的Unicode码点表示。

​ 这就是为什么Unicode标准还定义了其他表示法的原因,这些表示法通常需要的内存更少,但每个符号的字节数不同,具体取决于所需的码点。其思想是对于最常见的元素使用较小的表示,对于不经常遇到的元素使用较长的表示。

​ Unicode码点的不同物理表示称为Unicode变换格式(UTF)。它们是算法的映射,是 Unicode 标准的一部分,可将每个码点(字符的绝对数字表示)映射为表示给定字符的独特字节序列。请注意,这些映射可以双向使用,在不同表示法之间来回转换。

​ Unicode标准定义了三种编码格式,具体取决于用于表示字符集的初始部分(前 128 个字符)的比特数:8、16或32。值得注意的是这三种编码格式每个代码点最多需要4个字节的数据。

  • UTF-8将字符转换为1到4字节的可变长度编码。UTF-8在HTML和类似协议中很受欢迎,因为当大多数字符(如HTML中的标记)都属于ASCII子集时,UTF-8就显得相当紧凑。
  • UTF-16 在许多操作系统(包括 Windows 和 macOS)中都很流行。UTF-16非常方便,因为大多数字符都可以用两个字节来表示,这使得它相当紧凑,处理速度也很快。
  • UTF-32在字符处理上非常合理(所有码位长度相同),但它太占用内存,实际使用有限。

​ 有一个常见的误解是,UTF-16可以直接用两个字节映射所有码点,但由于Unicode定义了100,000多个码点,您很容易发现它们无法容纳在64K个元素中。然而,确实存在开发人员仅使用Unicode的子集的情况,以使其适应固定长度的2字节每字符表示形式。在早期,Unicode的这个子集称为UCS-2,现在您经常看到它被引用为基本多语言平面(BMP)。但是,这只是Unicode的一个子集,是众多平面的一个。

注意:与多字节表示形式(UTF-16 和 UTF-32)相关的一个问题是确定哪个字节在前。根据该标准,所有形式都是允许的,因此您可以拥有 UTF-16 BE(大端)或 LE(小端),UTF-32 也是如此。big-endian 字节序列化是最高有效字节在前,little-endian 字节序列化是最低有效字节在前。字节序列化通常与带有称为字节顺序标记 (BOM) 的标头的 UTF 表示形式一起标记在文件中。

6.1.4 字节顺序标记

​ 在以 Unicode 字符存储的文本文件中,有一种方法可以显示码点所使用的 UTF 格式。这些信息存储在文件开头的标头或标记中,称为字节序标记(BOM)。这是一个签名,表示所使用的 Unicode 格式和字节序形式(小端或大端—LE 或 BE)。下表提供了各种 BOM 的汇总,其长度可以是 2、3 或 4 字节:

  • 00 00 FE FF UTF-32,big-endian
  • FF FE 00 00 UTF-32,little-endian
  • FE FF UTF-16,big-endian
  • FF FE UTF-16,little-endian
  • EF BB BF UTF-8

​ 在本章后面,我们将看到 Object Pascal 如何管理流中 BOM。BOM 出现在文件的开头,实际的 Unicode 数据紧随其后。因此,一个内容为 AB 的 UTF-8 文件包含五个十六进制值(3 个 值是BOM,2 个值是字母):

EF BB BF 41 42

​ 如果文本文件没有这些签名中的任何一个,通常将其视为ASCII文本文件,但它也可能包含任何编码的文本。

注解:另一方面,当您从网络请求或通过其他互联网协议接收数据时,可能会有一个特定的标头(协议的一部分)来指示编码,而不是依赖于 BOM。

6.1.5 观察Unicode

​ 如何创建一个 Unicode 字符表,就像我之前展示的 ASCII 字符表一样?首先,我们可以在基本多语言平面(BMP)中显示码点,但不包括所谓的代理对。

注解: 并非所有数值都是真正的 UTF-16 码点,因为有些字符(称为代用字符)的数值是无效的,它们被用来组成码点对并代表 65535 以上的码点。乐谱中用于 F(或低音)谱号的符号𝄢就是一个很好的代理对的例子。它的 3 字节码点 1D122 在 UTF-16 中用两个值(D834 和 DD22)的 4 字节来表示。

​ 要显示 BMP 的所有元素,需要一个 256 * 256 的网格,这很难在屏幕上显示。因此,ShowUnicode 示例中有一个包含两个页面的选项卡: 第一个标签页是包含 256 个区块的主选择器,而第二个页面则显示包含实际 Unicode 元素的网格,每次显示一个部分。与书中的其他程序相比,该程序的用户界面更简洁一些,如果你只对程序的输出结果感兴趣,而对程序的内部结构不感兴趣,你可以简单地浏览一下程序代码。

​ 程序启动时,会在 TabControl 第一页的 ListView 控件中填入 256 个条目,每个条目表示一组 256 个字符中的第一个和最后一个字符。以下是窗体的 OnCreate 事件处理器的实际代码,以及用于显示每个元素的简单函数,产生了图 6.3 的输出结果:

// 辅助函数
function GetCharDescr(NChar: Integer): string;
beginif Char(NChar).IsControl thenResult := 'Char #' + IntToStr(NChar) + ' [  ]'elseResult := 'Char #' + IntToStr(NChar) + ' [' + Char(NChar) + ']';
end;procedure TForm2.FormCreate(Sender: TObject);
varI: Integer;ListItem: TListViewItem;
beginfor I := 0 to 255 do // 256个页面 * 每个页面256个字符beginListItem := ListView1.Items.Add;ListItem.Tag := I;if (I < 216) or (I > 223) thenListItem.Text := GetCharDescr(I * 256) + '/' + GetCharDescr(I * 256 + 255)elseListItem.Text := 'Surrogate Code Points';end;
end;

图6.3:ShowUnicode示例的第一页有一个长列表,显示Unicode字符的各个部分

​ 请注意代码是如何在 ListView 项目的 Tag 属性中保存 "页面 "编号的,这些信息随后将用于填充页面。当用户选择其中一个条目时,应用程序将跳转到 Tab控件的第二页,并用该部分的 256 个字符填充其字符串网格:

procedure TForm2.ListView1ItemClick(const Sender: TObject; const AItem: TListViewItem);
varI, NStart: Integer;
beginNStart := AItem.Tag * 256;for I := 0 to 255 dobeginStringGrid1.Cells[I mod 16, I div 16] :=IfThen(not Char(I + NStart).IsControl, Char(I + NStart), '');end;TabControl1.ActiveTab := TabItem2;
end;

​ 上述代码中使用的 IfThen 函数是一个双向测试:如果第一个参数传递的条件为真,函数返回第二个参数的值;如果不为真,则返回第三个参数的值。对第一个参数进行的测试使用了 Char 类型助手的 IsControl 方法来过滤不可打印的控制字符。

注解:IfThen 函数的操作与大多数基于 C 语法的编程语言中的 ? :运算符类似。它有一个用于字符串的版本和一个用于整数的单独版本。对于字符串版本,必须包含 System.StrUtils 单元,而对于整数版本的 IfThen,则必须包含 System.SysUtils 单元。

​ 应用程序生成的 Unicode 字符网格如图 6.4 所示。请注意,输出结果因所选字体和具体操作系统显示特定 Unicode 字符的能力而异。

图 6.4: ShowUnicode 示例的第二页显示了一些的 Unicode 字符

这篇关于(delphi11最新学习资料) Object Pascal 学习笔记---第6章第1节(Unicode: 一个适用于整个世界的字母表)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/751956

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

揭秘世界上那些同时横跨两大洲的国家

我们在《世界人口过亿的一级行政区分布》盘点全球是那些人口过亿的一级行政区。 现在我们介绍五个横跨两州的国家,并整理七大洲和这些国家的KML矢量数据分析分享给大家,如果你需要这些数据,请在文末查看领取方式。 世界上横跨两大洲的国家 地球被分为七个大洲分别是亚洲、欧洲、北美洲、南美洲、非洲、大洋洲和南极洲。 七大洲示意图 其中,南极洲是无人居住的大陆,而其他六个大洲则孕育了众多国家和

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学