这是 Andreas answer here的修改版本。
function BytePos(const Pattern: array of byte; const Buffer : array of byte): Integer;
var
PatternLength,BufLength: cardinal;
i,j: cardinal;
OK: boolean;
begin
Result := -1;
PatternLength := Length(Pattern);
BufLength := Length(Buffer);
if (PatternLength > BufLength) then
Exit;
if (PatternLength = 0) then
Exit;
for i := 0 to BufLength - PatternLength do
if Buffer[i] = Pattern[0] then
begin
OK := true;
for j := 1 to PatternLength - 1 do
if Buffer[i + j] <> Pattern[j] then
begin
OK := false;
Break;
end;
if OK then
Exit(i);
end;
end;
begin
WriteLn(BytePos(B,A)); // 3
WriteLn(BytePos(C,A)); // -1
ReadLn;
end.
不过,Bummis 的回答是更喜欢。好多了。
只是评论中提到的一个评论。
对于小型数据集,BytePos
性能优于ByteArrayPos
,而对于大型数据集(10000 个项目),性能则相反。
这适用于 32 位模式,其中汇编程序优化的Pos()
系统功能在大型数据集上发挥最佳效果。
但是在 64 位模式下,没有汇编器优化的 Pos() 函数。在我的基准测试中,对于所有类型的数据集大小,BytePos
比 快 4-6 倍。ByteArrayPos
更新
基准测试是使用 XE3 进行的。
在测试过程中,我purepascal
在 System.pas 函数中发现了一个有缺陷的循环Pos()
。
添加了改进请求QC111103,其中建议的功能快了大约 3 倍。
我还对上述BytePos
内容进行了一些优化,并在下面将其呈现为ByteposEx()
.
function BytePosEx(const Pattern,Buffer : array of byte; offset : Integer = 0): Integer;
var
LoopMax : Integer;
OK : Boolean;
patternP : PByte;
patStart : Byte;
i,j : NativeUInt;
begin
LoopMax := High(Buffer) - High(Pattern);
if (offset <= LoopMax) and
(High(Pattern) >= 0) and
(offset >= 0) then
begin
patternP := @Pattern[0];
patStart := patternP^;
for i := NativeUInt(@Buffer[offset]) to NativeUInt(@Buffer[LoopMax]) do
begin
if (PByte(i)^ = patStart) then
begin
OK := true;
for j := 1 to High(Pattern) do
if (PByte(i+j)^ <> patternP[j]) then
begin
OK := false;
Break;
end;
if OK then
Exit(i-NativeUInt(@Buffer[0]));
end;
end;
end;
Result := -1;
end;