2016-06-07 43 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) –

相關問題