Ошибка "несоответствие типов" для "набора символов" в Pascal Script версии Inno Setup для Unicode
У меня есть рабочие скрипты Pascal для Inno Setup, но недавно мы столкнулись с проблемой символов Unicode. И после изменения Inno Setup на версию 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;
Все это выглядит хорошо для меня, но это мой первый контакт с Паскалем. Я был бы благодарен, если бы кто-то более опытный мог помочь мне в этом. Спасибо!
2 ответа
В Паскале (Сценарий) set
может содержать только 256 (2^8) значений. В Unicode Inno Setup 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;
Также обратите внимание, что добавление строки char-by-char может быть довольно неэффективным. Вместо этого замените символы на месте (как показано в обоих примерах выше).
С набором символов лучше использовать типизированный 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;