Страницы

Поиск по вопросам

вторник, 12 февраля 2019 г.

Как исправить код, чтобы не было 'String index to var param'?

Function exchange(input: String): String; Var I: Integer; Begin Result:=input; I:=Length(Result); For I:=1 To I Do Begin If Result[I]='a' Then Result[I]:='b'; //[DCC Error] test.pas(13): E1047 Unsafe code 'String index to var param' If Result[I]='c' Then Result[I]:='d'; //[DCC Error] test.pas(14): E1047 Unsafe code 'String index to var param' If Result[I]='e' Then Result[I]:='f'; //[DCC Error] test.pas(15): E1047 Unsafe code 'String index to var param' End; End;
Именно изменить, что можно отключить предупреждения я знаю, мне интересно как же пишется этот "надёжный" код и что именно ему тут не нравится?


Ответ

Вот такой код будет корректным и безошибочным:
Function exchange(input: String): String; Var I: Integer; sb: TStringBuilder; Begin sb := TStringBuilder.Create(input); try For I := 0 To sb.Length - 1 Do Begin if sb.Chars[I] = 'a' Then sb.Chars[I] := 'b'; if sb.Chars[I] = 'c' Then sb.Chars[I] := 'd'; if sb.Chars[I] = 'e' Then sb.Chars[I] := 'f'; End; Result := sb.ToString; finally sb.Free; end; End;
А теперь объяснение:
В современных версиях Делфы, при внедрении поддержки новых платформ (iOS, Android, x64 и т.п.) было принято решение уходить от строк индексируемых 1 .. N в пользу стандартных с индексацией 0 .. N-1. Данное изменение ломает практически весь существующий код. Поэтому его внедрение идет очень медленно и постепенно. В какой-то версии добавили предупреждения, в какой-то {$IFDEF ZEROBASEDSTRINGS}. Где-то эта директива включена по умолчанию, но в основном нет.
О чем говорит данное предупреждение - о том, что обращаться к строкам по индексу небезопасно, т.к. индексация может быть заранее неизвестна (в зависимости от директивы и целевой платформы).
Как быть?
Самое простое решение, если вам нужна только Win32 - отключить предупреждения и спокойно жить дальше. Самое правильное, если вам нужны новые платформы - переписать код с использованием построителя строк (TStringBuilder), который сам разберется как именно строка индексируется, и предоставляет к ней единый интерфейс через свои методы.
P.S. Как ни странно, For I:=1 To I Do является вполне корректным кодом, т.к. цикл сохраняет максимальное значение до начала итерирования.

Комментариев нет:

Отправить комментарий