gpt4 book ai didi

string - 将 char 分配给 string 时如何解决 W1047/W1068 警告?

转载 作者:行者123 更新时间:2023-12-03 15:49:48 31 4
gpt4 key购买 nike

我有一个简单的函数,可以将数字转换为字符串(类似于 Excel 列号 1..n 可以转换为列名称 A-ZZZ) 。由于我经常使用它,因此我删除了局部变量作为速度优化,并且仅直接使用 Result

当我编译时,我收到这两个警告:

W1047 Unsafe code 'String index to var param'

W1068 Modifying strings in place may not be supported in the future

这是缩短的函数:

function Idx2Code_(Idx: integer): string;
begin
SetLength(Result, 3); // init Result size
if Idx <= 26 then
begin
// single char: A-Z
Result := Chr(64 + Idx);
SetLength(Result, 1);
end
else if Idx <= 676 then
begin
// 2 chars codes: BA-ZZ
Result[1] := Chr((Idx div 26) + 64 + 1); // <- warnings for this line
Result[2] := Chr((Idx mod 26) + 64); // <- warnings for this line
SetLength(Result, 2);
end
else
begin
// 3 chars codes: BAA-ZZZ
Result[1] := Chr((Idx div 676) + 64 + 1); // <- warnings for this line
Result[2] := Chr(((Idx mod 676) div 26) + 64 + 26); // <- warnings for this line
Result[3] := Chr((Idx mod 26) + 64 + 26); // <- warnings for this line
end;
end;

我可以使用局部变量,但速度较慢,这是我不想要的。

我不想使用在未来的 Delphi 版本中可能会“过时”的代码。

如何解决警告,同时尽可能保持简单性和速度?

最佳答案

在移动开发中,Delphi 的 string 类型的直接索引默认是基于 0(可以使用 {$ZEROBASEDSTRINGS OFF} 指令禁用此功能)。

在桌面开发中,默认情况下直接索引仍然是基于1,但将来可能变为基于0。

由于平台之间存在这种差异,不鼓励继续对字符串进行直接索引,因此会出现警告消息。为了避免这种情况,有一个基于 0 的 TStringHelper.Chars[]所有平台上均可使用的属性。但是,此属性是只读,因此您不能使用它来修改字符串的内容(在某一时刻,Embarcadero 正在考虑将字符串 code> 不可变,但后来决定不这样做,但警告仍然存在)。

在这种情况下,您必须:

  1. 禁用警告,并使用适合平台的索引。您可以使用 Low(string) 来帮助您:

    {$WARN UNSAFE_CODE OFF}
    {$WARN IMMUTABLE_STRINGS OFF}
    function Idx2Code_(Idx: integer): string;
    begin
    if Idx <= 26 then
    begin
    // single char: A-Z
    SetLength(Result, 1);
    Result[Low(string)] := Chr(64 + Idx);
    end
    else if Idx <= 676 then
    begin
    // 2 chars codes: BA-ZZ
    SetLength(Result, 2);
    Result[Low(string)] := Chr((Idx div 26) + 64 + 1);
    Result[Low(string)+1] := Chr((Idx mod 26) + 64);
    end
    else
    begin
    // 3 chars codes: BAA-ZZZ
    SetLength(Result, 3);
    Result[Low(string)] := Chr((Idx div 676) + 64 + 1);
    Result[Low(string)+1] := Chr(((Idx mod 676) div 26) + 64 + 26);
    Result[Low(string)+2] := Chr((Idx mod 26) + 64 + 26);
    end;
    end;
    {$WARN IMMUTABLE_STRINGS DEFAULT}
    {$WARN UNSAFE_CODE DEFAULT}
  2. 使用TStringBuilder :

    uses
    System.SysUtils;

    function Idx2Code_(Idx: integer): string;
    var
    SB: TStringBuilder;
    begin
    SB := TStringBuilder.Create(3);
    try
    if Idx <= 26 then
    begin
    // single char: A-Z
    SB.Append(Chr(64 + Idx));
    end
    else if Idx <= 676 then
    begin
    // 2 chars codes: BA-ZZ
    SB.Append(Chr((Idx div 26) + 64 + 1));
    SB.Append(Chr((Idx mod 26) + 64));
    end
    else
    begin
    // 3 chars codes: BAA-ZZZ
    SB.Append(Chr((Idx div 676) + 64 + 1));
    SB.Append(Chr(((Idx mod 676) div 26) + 64 + 26));
    SB.Append(Chr((Idx mod 26) + 64 + 26));
    end;
    Result := SB.ToString;
    finally
    SB.Free;
    end;
    end;

    或者,TStringbuilder 确实有自己的 Chars[]可写属性:

    uses
    System.SysUtils;

    function Idx2Code_(Idx: integer): string;
    var
    SB: TStringBuilder;
    begin
    SB := TStringBuilder.Create(3);
    try
    if Idx <= 26 then
    begin
    // single char: A-Z
    SB.Length := 1;
    SB[0] := Chr(64 + Idx);
    end
    else if Idx <= 676 then
    begin
    // 2 chars codes: BA-ZZ
    SB.Length := 2;
    SB[0] := Chr((Idx div 26) + 64 + 1);
    SB[1] := Chr((Idx mod 26) + 64);
    end
    else
    begin
    // 3 chars codes: BAA-ZZZ
    SB.Length := 3;
    SB[0] := Chr((Idx div 676) + 64 + 1);
    SB[1] := Chr(((Idx mod 676) div 26) + 64 + 26);
    SB[2] := Chr((Idx mod 26) + 64 + 26);
    end;
    Result := SB.ToString;
    finally
    SB.Free;
    end;
    end;

有关详细信息,请参阅 Embarcadero 文档:

Migrating Delphi Code to Mobile from Desktop : Use 0-Based Strings

关于string - 将 char 分配给 string 时如何解决 W1047/W1068 警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37688491/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com