一组WideChar:集合中最多可以有256个元素。

8

我有这样一行代码:

const
  MY_SET: set of WideChar = [WideChar('A')..WideChar('Z')];

上述代码无法编译,出现以下错误:
[错误] 集合最多只能有256个元素
但是下面这行代码可以成功编译:
var WS: WideString;
if WS[1] in [WideChar('A')..WideChar('Z')] then...

这也可以正常编译:

const
  MY_SET = [WideChar('A')..WideChar('Z'), WideChar('a')..WideChar('z')];
  ...
  if WS[1] in MY_SET then...

为什么会这样呢?

编辑:我的问题是为什么if WS [1] in [WideChar ('A')..WideChar ('Z')]编译通过?而且为什么MY_SET = [WideChar('A')..WideChar('Z'), WideChar('a')..WideChar('z')];也能编译通过?它们不也需要遵循set的规则吗?


第二段代码只有26个元素。在这里使用">="和"<="要简单得多。请注意,您的代码不承认非英文字符。 - David Heffernan
@David,第一个代码也有26个元素吗?请注意,您的代码没有承认非英文字符。我需要检查有效的ISO字符,只有英文字符是有效的。 - zig
1
只要元素本身小于256,第二个表达式就是有效的。第一个表达式声明了一个大于256大小的集合(WideChar集合)。 - LU RD
1
第一个示例中的值有26个元素,但类型更多。不要在这里使用集合。使用不等式运算符。 - David Heffernan
2个回答

12

一个有效的集合必须遵守两个规则:

  1. 集合中的每个元素必须具有小于256的序数值。
  2. 集合中的元素数量不能超过256个。
MY_SET: set of WideChar = [WideChar('A')..WideChar('Z')];
在这里,您声明了一个具有超过256个元素的集合类型Set of WideChar)-> 编译器错误。
if WS[1] in [WideChar('A')..WideChar('Z')]
在这里,编译器将WideChar('A')视为一个序数值。该值和集合中的所有其他值都小于256。这符合规则1。
唯一元素的数量也在限制范围内(Ord('Z')-Ord('A')+1),因此第二个规则通过了。
MY_SET = [WideChar('A')..WideChar('Z'), WideChar('a')..WideChar('z')];
这里声明了一个符合上述要求的集合。请注意,编译器将其视为顺序值的集合,而不是WideChar类型的集合。

1
有趣的是,在第二种情况下(如果WS [1]在,,,中),它如何进行比较? - Tom Brunberg
@TomBrunberg,除了编译器将左参数的大小与字节大小设置元素进行比较外,没有任何区别。 - LU RD
1
@zig 所以错误在 MY_SET: set of WideChar 部分,而不是 [WideChar('A')..WideChar('Z')] 部分。 - Jan Doggen
@JanDoggen,是的。我现在意识到了。 - zig
我一定是误读了你最初的答案,认为任何 WideChar 都会被转换为集合的有效范围,但当然你只是谈到了 WideChar,仅限于 #$00FF。对于噪音感到抱歉。顺便说一句,总结得很好。 - Tom Brunberg

2

一个集合最多只能有256个元素。
即使只有这么少的元素,该集合已经使用了32个字节。

来自文档:

集合是一个比特数组,每个比特表示一个元素是否在集合中。集合中元素的最大数量为256,因此集合永远不会占用超过32个字节。特定集合占用的字节数等于

(Max div 8) - (Min div 8) + 1

因此,只有byte、(ansi)char、boolean和枚举类型的元素少于257个的集合是可能的。
由于widechar使用2个字节,它可以有65536个可能的值。
一个widechar集合将占用8Kb,太大而无法实际使用。

type
  Capitals = 'A'..'Z';

const
  MY_SET: set of Capitals = [WideChar('A')..WideChar('Z')];

编译并且运行的结果是一样的。

如果您的代码不考虑Unicode,那么使用宽字符似乎有点儿可笑。
如代码所写,只能识别英文大写字母,而无法考虑不同区域设置。

在这种情况下,最好使用以下代码:

if (AWideChar >= 'A') and (AWideChar <= 'Z') ....

无论有多少字符落在中间,这都起作用。显然,你可以将其封装在函数中以节省输入。

如果您坚持使用大型集合,请参阅此答案:https://dev59.com/N0zSa4cB1Zd3GeqPjAkl#2281327


2
但是为什么 if WS[1] in [WideChar('A')..WideChar('Z')] 可以编译通过?而且 MY_SET = [WideChar('A')..WideChar('Z'), WideChar('a')..WideChar('z')]; 也可以编译通过?它们不也适用于 set 规则吗?有什么区别呢? - zig
4
编译器将WideChar('A')转换为一个小于256的序数值。如果您输入的值大于此范围,编译器将会报错。现在,编译器具有一个由Ord('Z') - Ord('A') + 1个元素组成的有效集合。 - LU RD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接