"Type mismatch" Inno Setup Unicode 版本的 Pascal 脚本中的 "set of char" 错误

"Type mismatch" error on "set of char" in Pascal Script of the Inno Setup Unicode version

我有一个适用于 Inno Setup 的可用 Pascal 脚本,但最近我们 运行 遇到了 Unicode 字符的问题。在将 Inno Setup 更改为 Unicode 版本后,我们在现有脚本中遇到了错误。而且这个错误太笼统了 - "Type mismatch" 对于某些行。由于我们的主脚本由包含的许多其他脚本组成,我不确定该行是否正确,它指向下面的这个函数,并与 Set of Char 行。 在查看 Inno Setup 文档后,我发现 Unicode 版本在某些方面更加严格,并且在 ANSI 字符串处理方面也有一些变化(可能 Char)。

function IsValidName(Name: String):String;
var
  Valid_Ch: Set of Char;
  Location: Integer;
begin
    Valid_Ch := ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '_', '-'];
    Result := '';
    for Location := 1 to Length(Name) do
    begin
        if Name[Location] in Valid_Ch then
        begin
            Result := Result + Name[Location];
        end
        else
        begin
            Result := Result + '_';
        end;
    end;    
end;

我觉得这一切都很好,但这是我第一次接触 Pascal。如果有经验的人可以帮助我解决这个问题,我将不胜感激。 谢谢!

在 Pascal(脚本)中,set 只能包含 256 (2^8) 个值。在 Unicode Inno Setup 中,Char 是 2 字节的,因此它可以包含超过 256 个不同的值。所以你不能再将它与 set 一起使用了。

您有以下选择:

  • 在您的例子中,由于集合实际上是常量,您可以在 if 表达式中使用常量集。有趣的是,这甚至在 Unicode 版本中也有效(可能有一些内置的 hack 允许这个例外)。

    function IsValidName(Name: string): string;
    var
      Location: Integer;
    begin
      Result := Name;
      for Location := 1 to Length(Name) do
      begin
        if not (Name[Location] in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '_', '-']) then
        begin
          Result[Location] := '_';
        end;
      end;    
    end;
    

如果您需要集合可变(不是您的情况):

  • 使用 Byte 并在 CharByte 之间进行转换,并将所有字符显式替换为 Ord() > 255
  • 或使用 string 而不是 set。有关示例,请参见下文。

    function IsValidName(Name: string): string;
    var
      Valid_Ch: string;
      Location: Integer;
    begin
      Valid_Ch := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-';
      Result := Name;
      for Location := 1 to Length(Result) do
      begin
        if Pos(Result[Location], Valid_Ch) = 0 then
        begin
          Result[Location] := '_';
        end;
      end;    
    end;
    

另请注意,逐个字符地附加字符串可能效率很低。就地替换字符(如上面两个示例所示)。