Ecco una versione rielaborata di Andreas risposta 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.
La risposta di Bummis è preferire, comunque. Molto meglio.
Solo un'osservazione come indicato nei commenti.
Per dataset di piccole dimensioni BytePos
supera le prestazioni ByteArrayPos
, mentre per set di dati di grandi dimensioni (10000 articoli) la prestazione viene invertita.
Questo è per la modalità a 32 bit, in cui la funzione di sistema Pos()
ottimizzata per l'assemblatore funziona al meglio per dataset di grandi dimensioni.
Nella modalità 64-bit, tuttavia, non esiste una funzione Pos() ottimizzata per l'assembler. Nel mio test di benchmark, BytePos
è 4-6 volte più veloce di ByteArrayPos
, per tutti i tipi di dimensioni del set di dati.
Aggiornamento
Il test di benchmark è stato fatto con XE3.
Durante il test ho scoperto un loop purepascal
imperfetto nella funzione System.pas Pos()
.
È stata aggiunta una richiesta di miglioramento, QC111103, in cui la funzione proposta è circa 3 volte più veloce.
Ho ottimizzato anche il precedente BytePos
e lo presentiamo qui sotto come 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;
Ecco la risposta, [Esiste una funzione "Pos" per trovare i byte?] (Http://stackoverflow.com/q/4959566/576719). –
Ottima e veloce risposta. (ho passato circa 1h e mezzo a non trovare nulla mentre lo facevi in ..5 '?). Grazie! Devo studiare un po 'di più sui puntatori e simili al fine di utilizzare tali funzioni. –
Pubblicherò una versione rielaborata della risposta di Andreas per voi da studiare. –