我有一个用于Inno Setup的Pascal脚本,但最近我们遇到了Unicode字符的问题。在将Inno设置更改为Unicode版本后,我们在现有脚本中出现了错误。这个错误太笼统了——对于某一行来说,"类型不匹配"。由于我们的主脚本是由包含的许多其他脚本组成的,我不确定这一行是否正确,它指向下面的这个函数,并与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(Script)中,set
只能包含256(2^8)个值。在Unicode Inno设置中,Char
是2字节,因此它可以包含超过256个不同的值。因此,您不能再将其与set
一起使用。
您有以下选项:
-
在您的情况下,由于集合实际上是常量,因此可以在
if
表达式中使用常量集合。有趣的是,这甚至在Unicode版本中也有效(可能内置了一些允许此异常的破解)。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
并在Char
和Byte
之间强制转换,并用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;
还要注意,一个字符接一个字符地附加字符串可能效率很低。将字符替换到位(如上面两个示例所示)。
对于一组字符,最好使用类型化的TSysCharSet或类似StrToCharSet的转换器来避免类型不匹配,例如在maXbox4:中
function IsValidName2(Name: string): string;
var Location: Integer;
begin
Result:= Name;
for Location := 1 to Length(Name) do begin
if not (Name[Location] in StrToCharSet(lowercase(LETTERSET)+
LETTERSET+DIGISET+ '_'+'-')) then begin
Result[Location] := '_';
end;
end;
end;