gpt4 book ai didi

delphi - 在 Delphi 中查找流中字符串的有效方法

转载 作者:行者123 更新时间:2023-12-03 18:18:03 42 4
gpt4 key购买 nike

我想出了这个函数来返回字符串在 Delphi 流中出现的次数。但是,我怀疑有更有效的方法来实现这一点,因为我使用的是“更高级别”的结构 (char),而不是在较低的字节/指针级别(我不太熟悉)

function ReadStream(const S: AnsiString; Stream: TMemoryStream): Integer;
var
Arr: Array of AnsiChar;
Buf: AnsiChar;
ReadCount: Integer;

procedure AddChar(const C: AnsiChar);
var
I: Integer;
begin
for I := 1 to Length(S) - 1 do
Arr[I] := Arr[I+1];
Arr[Length(S)] := C;
end;

function IsEqual: Boolean;
var
I: Integer;
begin
Result := True;
for I := 1 to Length(S) do
if S[I] <> Arr[I] then
begin
Result := False;
Break;;
end;
end;

begin
Stream.Position := 0;
SetLength(Arr, Length(S));
Result := 0;
repeat
ReadCount := Stream.Read(Buf, 1);
AddChar(Buf);
if IsEqual then
Inc(Result);
until ReadCount = 0;
end;

有人可以提供更有效的程序吗?

最佳答案

Stream 有一个方法可以让你进入内部缓冲区。

您可以使用 Memory property 获取指向内部缓冲区的指针.

如果您使用 32 位并且您愿意放弃已弃用的 TMemoryStream并使用 TBytesStream相反,您可以使用滥用动态数组和 AnsiString 在 32 位中共享相同结构的事实。
不幸的是,Emba 破坏了 X64 中的兼容性,这意味着无论出于何种原因,您都不能在 X64 中拥有大于 2GB 的字符串。

请注意,此技巧将在 64 位中失效! (参见下面的修复)

您可以使用 Boyer-Moore string searching .

这允许您编写如下代码:

function CountOccurrances(const Needle: AnsiString; const Haystack: TBytesStream): integer;
var
Start: cardinal;
Count: integer;
begin
Start:= 1;
Count:= 0;
repeat
{$ifdef CPUx86}
Start:= _FindStringBoyerAnsiString(string(HayStack.Memory), Needle, false, Start);
{$else}
Start:= __FindStringBoyerAnsiStringIn64BitTArrayByte(TArray<Byte>(HaySAtack.Memory), Needle, false, Start);
{$endif}
if Start >= 1 then begin
Inc(Start, Length(Needle));
Inc(Count);
end;
until Start <= 0;
Result:= Count;
end;

对于 32 位,你必须重写 BoyerMoore code使用 AnsiString ;一个微不足道的重写。
对于 64 位,您必须重写 BoyerMoore 代码才能使用 TArray<byte>作为第一个参数;一个相对简单的任务。

如果您追求效率,请尽量避免使用 pchars 的 WinAPI 调用。 C 风格的字符串是一个可怕的想法,因为它们没有长度前缀。

关于delphi - 在 Delphi 中查找流中字符串的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44220926/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com