【问题标题】:set of WideChar: Sets may have at most 256 elementsWideChar 集合:集合最多可以有 256 个元素
【发布时间】:2016-06-21 05:31:06
【问题描述】:

我有这行:

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,第一个代码不是也有 26 个元素吗? “请注意,您的代码不承认非英文字符。”我需要检查有效的 ISO 字符。只有英文字符有效。
  • 只要元素本身低于 256,第二个表达式就有效。第一个表达式声明了一个大于 256 的集合(WideChar 集合)。
  • 第一个示例中的值有 26 个元素,但类型有更多。不要在这里使用集合。使用不等式运算符。

标签: delphi delphi-7


【解决方案1】:

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

  1. 集合中的每个元素的序数值必须小于 256。
  2. 集合中的元素不得超过 256 个。
MY_SET: set of WideChar = [WideChar('A')..WideChar('Z')];

在这里你声明了一个 set type (Set of WideChar),它有超过 256 个元素 -> 编译器错误。

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')];

在这里,您声明了一个也满足上述要求的集合。请注意,编译器将此视为一组序数值,而不是 set of WideChar

【讨论】:

  • 有意思,第二种情况(如果WS[1] in ,,,),它是怎么做比较的?
  • @TomBrunberg,除了编译器在与字节大小设置元素的比较中使用左参数的大小之外没有区别。
  • @zig 所以错误在 MY_SET: set of WideChar 部分,而不是在 [WideChar('A')..WideChar('Z' )]
  • @JanDoggen,是的。我现在意识到了。
  • 我一定误读了您的初始答案,即 any WideChar 将被转换 为集合的有效范围,但当然您只谈到了WideChars 到 #$00FF。对不起,噪音。很好的总结,顺便说一句
【解决方案2】:

一个集合不能超过 256 个元素。
即使元素如此之少,该集合也已经使用了 32 个字节。

来自文档:

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

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

因此,只有少于 257 个元素的字节、(ansi)char、布尔值和枚举集是可能的。
因为 Widechar 使用 2 个字节,所以它可以有 65536 个可能的值。
一组widechar会占用8Kb,太大不实用。

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

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

将编译和工作相同。

如果您的代码忽略了 unicode,那么使用 Widechar 似乎有点傻。
由于只识别英文大写字母,因此您不考虑不同的语言环境。

在这种情况下,最好使用类似的代码

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

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

如果您坚持使用大集合,请参阅此答案:https://stackoverflow.com/a/2281327/650492

【讨论】:

  • 但是为什么if WS[1] in [WideChar('A')..WideChar('Z')] 会编译?为什么MY_SET = [WideChar('A')..WideChar('Z'), WideChar('a')..WideChar('z')]; 编译?它们不是也适用于set 规则吗?有什么区别?
  • 编译器将WideChar('A') 转换为小于 256 的序数值。如果您输入的值大于该值,编译器会报错。现在,编译器有一个包含 Ord('Z') - Ord('A') +1 元素的有效集合。
猜你喜欢
  • 2020-11-27
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 2018-03-16
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多