Einzelnen Beitrag anzeigen

Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: München
11.412 Beiträge
 
Delphi 11 Alexandria
 
#1

Suchen von Strings im String (incl. Startposition)

  Alt 12. Jun 2002, 11:50
Hi DPler,

dieser Beitrag habe ich zum ersten Mal am 31.10.2000 bei Delphi3000.com veröffentlicht. Nach und nach werde ich verschiedene meiner Beiträge hier einbringen.

Die Lösung wurde in Borland Delphi 5 SP 1 entwickelt, sollte aber auch auf den anderen 32-bit Versionen funktionieren. Der Algorithmus basiert auf dem Original von Borlands Pos Funktion aus der Systems unit.

function NextPos(Substr: string; S: string; LastPos: DWORD = 0): DWORD

Die ersten beiden Parameter sind identisch mit der Funktion Pos von Borland. Der dritte Parameter gibt die Position an, nach welcher die Suche fortgesetzt werden soll (meistens die des letzten Treffers). 0 für von Anfang an, 1 suche ab der 2. Stelle, ..., 9 suche ab der 10. Stelle usw. usf.

Damit kann man recht schnell nach allen Vorkommen eines String in einem weiteren Suchen. Der Code ist komplett in Assembler und liesse sich weiter optimieren (siehe Delphi3000.com), aber er funktioniert.

Delphi-Quellcode:
function NextPos(SubStr: AnsiString; Str: AnsiString; LastPos: DWORD
  = 0): DWORD;
type
  StrRec = packed record
    allocSiz: Longint;
    refCnt: Longint;
    length: Longint;
  end;

const
  skew = sizeof(StrRec);

asm
  // Search-String passed?
  TEST EAX,EAX
  JE @@noWork

  // Sub-String passed?
  TEST EDX,EDX
  JE @@stringEmpty

  // Save registers affected
  PUSH ECX
  PUSH EBX
  PUSH ESI
  PUSH EDI

  // Load Sub-String pointer
  MOV ESI,EAX
  // Load Search-String pointer
  MOV EDI,EDX
  // Save Last Position in EBX
  MOV EBX,ECX

  // Get Search-String Length
  MOV ECX,[EDI-skew].StrRec.length
  // subtract Start Position
  SUB ECX,EBX
  // Save Start Position of Search String to return
  PUSH EDI
  // Adjust Start Position of Search String
  ADD EDI,EBX

  // Get Sub-String Length
  MOV EDX,[ESI-skew].StrRec.length
  // Adjust
  DEC EDX
  // Failed if Sub-String Length was zero
  JS @@fail
  // Pull first character of Sub-String for SCASB function
  MOV AL,[ESI]
  // Point to second character for CMPSB function
  INC ESI

  // Load character count to be scanned
  SUB ECX,EDX
  // Failed if Sub-String was equal or longer than Search-String
  JLE @@fail
@@loop:
  // Scan for first matching character
  REPNE SCASB
  // Failed, if none are matching
  JNE @@fail
  // Save counter
  MOV EBX,ECX
  PUSH ESI
  PUSH EDI
  // load Sub-String length
  MOV ECX,EDX
  // compare all bytes until one is not equal
  REPE CMPSB
  // restore counter
  POP EDI
  POP ESI
  // all byte were equal, search is completed
  JE @@found
  // restore counter
  MOV ECX,EBX
  // continue search
  JMP @@loop
@@fail:
  // saved pointer is not needed
  POP EDX
  XOR EAX,EAX
  JMP @@exit
@@stringEmpty:
  // return zero - no match
  XOR EAX,EAX
  JMP @@noWork
@@found:
  // restore pointer to start position of Search-String
  POP EDX
  // load position of match
  MOV EAX,EDI
  // difference between position and start in memory is
  // position of Sub
  SUB EAX,EDX
@@exit:
  // restore registers
  POP EDI
  POP ESI
  POP EBX
  POP ECX
@@noWork:
end;
Also, viel Spass beim Suchen...
Daniel W.
  Mit Zitat antworten Zitat