Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 将字符分配给字符串时,如何解决W1047/W1068警告?_String_Delphi_Char_Compiler Warnings_Delphi Xe7 - Fatal编程技术网

String 将字符分配给字符串时,如何解决W1047/W1068警告?

String 将字符分配给字符串时,如何解决W1047/W1068警告?,string,delphi,char,compiler-warnings,delphi-xe7,String,Delphi,Char,Compiler Warnings,Delphi Xe7,我有一个将数字转换为字符串的简单函数(类似于Excel列编号1..n如何转换为列名a-ZZZ)。由于我经常使用它,我已经删除了作为速度优化的局部变量,并且只直接处理结果 编译时,我得到以下两个警告: W1047不安全代码“变量参数的字符串索引” W1068将来可能不支持就地修改字符串 以下是缩短的函数: function Idx2Code_(Idx: integer): string; begin SetLength(Result, 3); // init Result size if

我有一个将数字转换为字符串的简单函数(类似于Excel列编号
1..n
如何转换为列名
a-ZZZ
)。由于我经常使用它,我已经删除了作为速度优化的局部变量,并且只直接处理
结果

编译时,我得到以下两个警告:

W1047不安全代码“变量参数的字符串索引”

W1068将来可能不支持就地修改字符串

以下是缩短的函数:

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;
函数Idx2Code_389;(Idx:integer):字符串;
开始
设置长度(结果,3);//初始结果大小

如果在移动开发中使用Idx,Delphi的
string
类型的直接索引默认为0-based(可以通过指令禁用)

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

由于平台之间的这种差异,不鼓励向前直接索引
字符串
,因此警告消息也会随之出现。为了避免这种情况,所有平台上都有一个基于0的属性。但是,此属性是只读的,因此您不能使用它来修改
字符串的内容(Embarcadero曾一度考虑将
字符串
设置为不可变,但后来决定不使用它,但警告仍然存在)

在这种情况下,您必须:

  • 禁用警告,并使用平台适当的索引。您可以使用
    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}
    
    或者,
    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.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;
    
    使用
    System.SysUtils;
    函数Idx2Code_2;(Idx:integer):字符串;
    变量
    SB:TStringBuilder;
    开始
    SB:=TStringBuilder.Create(3);
    尝试
    
    如果Idx在“Result.Chars[0]:=Chr(64+Idx);”行上表示E2129不能分配给只读属性。我确实使用了SystemSysutils。我在这里遗漏了什么?@MikeTorrettinni,使用@LURD:yes,
    TStringBuilder
    是一种选择,但Mike似乎专注于性能,因此分配
    TStringBuilder
    本身并调用方法将数据附加到其中的额外开销可能不符合Mike的喜好。@RemyLebeau,我完全同意。但是总是使用Low()/High()的替代方法实在是太难看了。Emba似乎尽了最大的努力来迷惑德尔福社区。为什么不干脆
    结果:=Chr(…)+Chr(…)+Chr(…)
    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;