6.3.4 字符串辅助操作
鉴于字符串类型的重要性,我们不难理解,该类型的辅助函数有一个长长操作列表可以执行。鉴于字符串的重要性以及这些操作在大多数应用程序中的通用性,我认为仔细研究一下这个列表是值得的。
Delphi 传统的全局字符串操作函数和字符串辅助函数有一个重要区别:传统的字符串操作假定字符串索引从1开始,而字符串辅助操作逻辑是索引从0开始!
我已经对字符串辅助操作(大多数都有多个重载版本)进行了逻辑分组,考虑到它们的名称通常相当直观,仅简要描述它们的作用:
- 拷贝或部分拷贝操作,如Copy、CopyTo、Join和SubString
- 字符串修改操作,如Insert、Remove和Replace
- 对于从各种数据类型转换为字符串,您可以使用Parse和Format
- 当可能的情况下,使用ToBoolean、ToInteger、ToSingle、ToDouble和ToExtended进行从字符串到各种数据类型的转换,同时您可以使用ToCharArray将字符串转换为字符数组
- 使用 PadLeft、PadRight 和 Create 的重载版本,在字符串中填入空白或特定字符。反之,则可以使用 TrimRight、TrimLeft 和 Trim 删除字符串一端或两端的空白
- 使用Compare、CompareOrdinal、CompareText、CompareTo和Equals进行字符串比较和相等性测试,但请记住您还可以在某种程度上使用等于运算符和比较运算符
- 使用LowerCase和UpperCase、ToLower和ToUpper以及ToUpperInvariant更改大小写
- 使用Contains、StartsWith、EndsWith等操作测试字符串内容。在字符串中进行搜索可以使用IndexOf查找给定字符的位置(从开头或从给定位置开始),类似的IndexOfAny(查找字符数组中的一个元素),从字符串末尾向前搜索的LastIndexOf和LastIndexOfAny操作,以及特殊用途的IsDelimiter和LastDelimiter操作
- 使用 Length(返回字符数)、CountChars(也考虑代理对)、GetHashCode(返回字符串的哈希值)等函数访问字符串的通用信息,以及各种 "空 "测试(包括 IsEmpty、IsNullOrEmpty 和 IsNullOrWhiteSpace)。
- Split等字符串特殊操作,将字符串根据特定字符拆分为多个字符串,并使用QuotedString和DeQuoted在字符串周围添加或删除引号
- 最后,使用 Chars[] 访问单个字符,它在方括号中包含字符串元素的数字索引。它只能用于读取数值(不能用于更改数值),并与所有其他字符串辅助操作一样使用基于零的索引。
实际上,需要注意的是,所有字符串辅助方法都是按照许多其他语言所使用的字符串约定建立的,其中就包括字符串元素从 0 开始,直到字符串长度减 1 的概念。换句话说,正如我前面已经提到但值得再次强调的是,所有字符串辅助操作都使用基于零的索引作为参数和返回值。
注解:Split 操作是 Object Pascal RTL 中相对较新的操作。以前常用的方法是在指定一个特定的行分隔符后,将字符串赋值到一个字符串列表中,然后再访问这个列表中各个字符串或行。但是Split操作的效率和灵活性要高得多。
鉴于您可能需要直接对字符串进行大量操作,我本可以创建多个项目来演示这些功能。然而,我还是坚持只进行一些相对简单的操作演示,尽管这些操作非常常见。
StringHelperTest
示例中有两个按钮。在每个按钮中,代码的第一部分都是构建并显示一个字符串:
varStr1, Str2: string;I, NIndex, NCount: Integer;
beginStr1 := '';// 创建字符串for I := 1 to 10 doStr1 := Str1 + 'Object ';Str2 := string.Copy(Str1);Str1 := Str2 + 'Pascal ' + Str2.SubString(10, 30);Show(Str1);
请注意我是如何使用 Copy 函数来创建字符串数据的唯一副本,而不是别名的,尽管在这个特定的演示中,这并没有什么不同。最后的 SubString 调用用于提取字符串的一部分。结果文本如下:
Object Object Object Object Object Object Object Object Object Object Pascal ect Object Object Object Objec
在初始化后,第一个按钮的代码用于搜索子字符串,并使用用户指定的索引重复搜索,以统计给定字符串(示例中为单字符)的出现次数:
// 查找子字符串
Show('Pascal at: ' +Str1.IndexOf('Pascal').ToString);
// 计算出现次数
I := -1;
NCount := 0;
repeatI := Str1.IndexOf('O', I + 1); // 从下一个元素开始搜索if I >= 0 thenInc(NCount); // 找到一个
until I < 0;
Show('O found: ' +NCount.ToString + ' times');
我知道repeat循环并不是最简单的循环:它可以从负索引开始,因为任何后续搜索都从当前索引之后的索引开始;它计算出现次数;循环的终止是基于元素是否找到,如果没有找到,它会返回-1。代码的输出是:
Pascal at: 70
O found: 14 times
第二个按钮的代码用于对字符串中的一个或多个元素进行搜索和替换。在第一部分,它创建了一个新字符串,复制了首尾部分,并在中间添加了一些新文本。在第二部分中,它使用了 Replace 函数,只需通过适当的标志 (rfReplaceAll) 即可对多个出现的内容进行操作。
// 单一替换
NIndex := Str1.IndexOf('Pascal');
Str1 := Str1.SubString(0, NIndex) + 'Object' +Str1.SubString(NIndex + ('Pascal').Length);
Show(Str1);// 多重替换
Str1 := Str1.Replace('O', 'o', [rfReplaceAll]);
Show(Str1);
由于输出相当长且不容易阅读,我只列出了每个字符串的中间部分:
...Object Pascal ect. Object Object...
...Object Object ect. Object Object...
...object object ect. object object...
同样,这只是一个最小的示例,你可以使用该类型的类型辅助执行丰富的字符串操作。