在Delphi中快速填充字符串

Sve*_*sli 11 delphi string algorithm optimization

我试图加速应用程序中的某个例程,我的剖析器AQTime确定了一种方法,特别是作为瓶颈.这种方法已经存在多年了,并且是"misc"单元的一部分:

function cwLeftPad(aString:string; aCharCount:integer; aChar:char): string;
var
  i,vLength:integer;
begin
  Result := aString;
  vLength := Length(aString);
  for I := (vLength + 1) to aCharCount do    
    Result := aChar + Result;
end;
Run Code Online (Sandbox Code Playgroud)

在我正在优化的程序部分中,该方法被称为~35k次,并且它花费了惊人的56%的执行时间!

很容易看出它是一种可怕的方式来左键填充字符串,所以我用它替换它

function cwLeftPad(const aString:string; aCharCount:integer; aChar:char): string; 
begin
  Result := StringOfChar(aChar, aCharCount-length(aString))+aString;
end;
Run Code Online (Sandbox Code Playgroud)

这显着提升了.总运行时间从10,2秒增加到5.4秒.真棒!但是,cwLeftPad仍然占总运行时间的13%左右.有没有一种简单的方法可以进一步优化这种方法?

Rob*_*edy 12

您的新函数包含三个字符串,输入,结果StringOfChar和函数结果.当函数返回时,其中一个会被破坏.你可以用两个来做,没有任何东西被破坏或重新分配.

  1. 分配所需总长度的字符串.
  2. 用填充字符填充它的第一部分.
  3. 用输入字符串填充其余部分.

这是一个例子:

function cwLeftPad(const aString: AnsiString; aCharCount: Integer; aChar: AnsiChar): AnsiString;
var
  PadCount: Integer;
begin
  PadCount := ACharCount - Length(AString);
  if PadCount > 0 then begin
    SetLength(Result, ACharCount);
    FillChar(Result[1], PadCount, AChar);
    Move(AString[1], Result[PadCount + 1], Length(AString));
  end else
    Result := AString;
end;
Run Code Online (Sandbox Code Playgroud)

我不知道Delphi 2009及更高版本是否提供了基于Char的双字节FillChar,如果有的话,我不知道它叫什么,所以我改变了函数的签名来显式使用AnsiString.如果需要WideString或UnicodeString,则必须找到处理双字节字符的FillChar替换.(截至Delphi 2009,FillChar有一个令人困惑的名字,因为它不处理全尺寸的Char值.)

另一件需要考虑的事情是,你是否真的需要首先调用该函数.最快的代码是永不运行的代码.


gab*_*abr 6

另一个想法 - 如果这是Delphi 2009或2010,禁用Project,Options,Delphi Compiler,Compiling,Code Generation中的"字符串格式检查".