2016-06-07 40 views
3

我有一个简单的功能,可以将数字转换为字符串(类似于Excel列号1..n可以转换为列名称A-ZZZ)。当我使用这个很多时,我已经删除了局部变量作为速度优化,并且只能直接使用Result如何解决分配字符串到字符串W1047/W1068警告?

当我编译,我得到这2个警告:

W1047不安全的代码 '字符串指数为VAR PARAM' 到位可能不是

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; 

我可以使用局部变量,但其速度较慢,我不想。

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

我该如何解决警告,但尽可能保持简单和速度?

回答

5

在移动开发中,德尔福string型的直接索引是0基于默认(这可以用{$ZEROBASEDSTRINGS OFF}指令被禁用)。

在桌面开发,直接索引仍然基于1默认,但可能变为0为基础的未来。

由于平台之间的这种差异,string的直接索引不鼓励向前发展,因此警告消息。为了避免这种情况,在所有平台上都有一个基于0的TStringHelper.Chars[]属性。然而,这个属性是只读,所以你不能用它来修改string的内容(在一点上,Embarcadero正在考虑让string不变,但后来决定反对它,但警告仍然存在)。

在这种情况下,你将不得不采取:

  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的文档n,用于更多信息:

Migrating Delphi Code to Mobile from DesktopUse 0-Based Strings

+1

它说'E2129无法分配给只读property'上线'Result.Chars [0]:= CHR(64 + IDX);”。我确实使用了SystemSysutils。我在这里错过了什么? –

+0

我的不好,我忘了'TStringHelper.Chars []'确实是只读的,你不能用它来修改'string'的内容。我会更新我的答案。 –

+1

@MikeTorrettinni,使用[StringBuilder](http://docwiki.embarcadero.com/Libraries/en/SystemUtils.TStringBuilder.Chars) –

相关问题