String 将字符分配给字符串时,如何解决W1047/W1068警告?
我有一个将数字转换为字符串的简单函数(类似于Excel列编号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
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;