【发布时间】:2016-02-29 09:59:47
【问题描述】:
我有一个难以理解的令人费解的结果。
我一直在尝试提高这个例程的速度
function TStringRecord.GetWord: String;
begin
// return the next word in Input
Result := '';
while (PC^ <> #$00) and not PC^.IsLetter do begin
inc(FPC);
end;
while (PC^ <> #$00) and PC^.IsLetter do begin
Result := Result + PC^;
inc(FPC);
end;
end;
将Result := Result + PC^ 替换为基于指针的操作。这
是我的尝试:
function TStringRecord.GetWord2: String;
var
Len : Integer;
StartPC,
DestPC : PChar;
begin
// return the next word in Input
Result := '';
while (PC^ <> #$00) and not PC^.IsLetter do begin
inc(FPC);
end;
Len := Length(Input);
SetLength(Result, Len);
StartPC := PChar(Result);
DestPC := PChar(Result);
while (PC^ <> #$00) and PC^.IsLetter do begin
WStrPLCopy(DestPC, PC, 1);
inc(FPC);
inc(DestPC);
end;
SetLength(Result, DestPC - StartPC);
end;
根据我的线路分析器,WStrPLCopy(DestPC, PC, 1) 需要 50 倍的时间
比Result := Result + PC^。据我所知,这是因为在进入
对 WStrPLCopy 有一个对 _WStrFromPWChar 的调用,这似乎复制了更多
字符比必要的字符。我怎样才能避免这种情况,或者有人可以建议
另一种基于 PChar 的方法?
我的代码的其余部分如下:
TStringRecord = record
private
FPC: PChar;
FInput: String;
procedure SetInput(const Value: String);
public
function NextWord : String;
function NextWord2 : String;
property Input : String read FInput write SetInput;
property PC : PChar read FPC;
end;
procedure TStringRecord.SetInput(const Value: String);
begin
FInput := Value;
FPC := PChar(Input);
end;
【问题讨论】:
-
如果没有您向我们展示有意义的代码,就很难提供帮助。您省略了对输入字符串的任何引用。当一个就足够时,您正在执行两个堆分配。你在抄袭。当然你需要找到开始和结束索引,并使用
Copy。我向你保证,如果你展示你的代码,你会得到更好的答案。 -
我无意隐瞒任何事情,只是想省略不相关的细节。输入通常可以是几个 k 个字符。正如您所说,我在复制什么“零碎”,您对两个堆分配有什么想法?
-
您执行了两次堆分配。它们在代码中尽可能简单。你只需要做一个。而不是一个字符一个字符地复制,我会在最后复制一次。我不会在这里使用
PChar,而是使用索引。我会非常警惕线轮廓仪。使用秒表计时。 -
无论如何,我都不愿意写任何代码,因为仍然有很多缺失的信息。我们不知道典型的输入数据,代码如何与您的程序的其余部分相适应,等等。
-
"代码如何适应" 哦,这只是一个自学练习,典型的输入是任何东西,真的。无论如何,我不打算要求任何代码。我更改了我的代码以大致按照您的建议进行(仅在找到结尾后复制)并且它工作正常并且在速度方面与 GetWord 方法相当,所以谢谢。不确定我的 q 应该得到 -1 的结果,但我猜这就是 SO 的乐趣所在。我仍然对调用
_WStrFromPWChar的内容感到好奇,但我想我会单独询问这个问题,以免因我的代码不赞成而陷入困境。