Нахождение последнего вхождения подстроки в строку

Нахождение последнего вхождения подстроки в строку

{ **** UBPFD *********** by delphibase.endimus.com ****
>> Нахождение последнего вхождения подстроки в строку
Функция возвращает начало последнего вхождения
подстроки FindS в строку SrcS, т.е. первое с конца.
Если возвращает ноль, то подстрока не найдена.
Можно использовать в текстовых редакторах
при поиске текста вверх от курсора ввода.
Зависимости: System
Автор: Fenik, <a href="mailto:chook_nu@uraltc.ru">chook_nu@uraltc.ru</a>, Новоуральск
Copyright: Автор: Федоровских Николай
Дата: 16 июня 2002 г.
***************************************************** }

function PosR2L(const FindS, SrcS: string): Integer;
{Функция возвращает начало последнего вхождения
 подстроки FindS в строку SrcS, т.е. первое с конца.
 Если возвращает ноль, то подстрока не найдена.
 Можно использовать в текстовых редакторах
 при поиске текста вверх от курсора ввода.}

 function InvertS(const S: string): string;
  {Инверсия строки S}
 var
  i, Len: Integer;
 begin
  Len := Length(S);
  SetLength(Result, Len);
  for i := 1 to Len do
  Result[i] := S[Len - i + 1];
 end;
var
 ps: Integer;
begin
 {Например: нужно найти последнее вхождение
  строки 'ро' в строке 'пирожок в коробке'.
  Инвертируем обе строки и получаем
  'ор' и 'екборок в кожорип',
  а затем ищем первое вхождение с помощью стандартной
  функции Pos(Substr, S: string): string;
  Если подстрока Substr есть в строке S, то
  эта функция возвращает позицию первого вхождения,
  а иначе возвращает ноль.}

 ps := Pos(InvertS(FindS), InvertS(SrcS));
 {Если подстрока найдена определяем её истинное положение
  в строке, иначе возвращаем ноль}

 if ps <> 0 then
  Result := Length(SrcS) - Length(FindS) - ps + 2
 else
  Result := 0;
end;
Пример использования:
p := PosR2L('са', 'Мой сапог догнал самолёт.'); // p:=18;

{
 Letzte Position von SubStr in S ermitteln.
 Returns the last occurence of SubStr in S.
}

 function LastPos(SubStr, S: string): Integer;
 var
  Found, Len, Pos: integer;
 begin
  Pos := Length(S);
  Len := Length(SubStr);
  Found := 0;
  while (Pos > 0) and (Found = 0) do
  begin
  if Copy(S, Pos, Len) = SubStr then
  Found := Pos;
  Dec(Pos);
  end;
  LastPos := Found;
 end;

Взято с сайта: http://www.swissdelphicenter.ch

// by Manuel Wiersch
 function LastPos(const SubStr: AnsiString; const S: AnsiString): LongInt;
 asm
  TEST EAX,EAX // EAX auf 0 prufen (d.h. SubStr = nil)
  JE @@noWork // wenn EAX = 0 dann Sprung zu noWork
  TEST EDX,EDX
  // Test ob S = nil
  JE @@stringEmpty // bei Erfolg -> Sprung zum Label 'stringEmpty'
  PUSH EBX
  PUSH ESI
  PUSH EDI // Register auf dem Stack sichern Grund: OH
  // OH: "In einer asm-Anweisung mu? der Inhalt
  // der Register EDI, ESI, ESP, EBP und EBX
  // erhalten bleiben (dh. vorher auf dem Stack
  // speichern) MOV ESI, EAX
  // ESI = Sourceindex -> Adresse vom SubStr
  MOV EDI, EDX // EDI = Destinationindex -> Adresse von S
  MOV ECX,[EDI-4] // Lange von S ins Zahlregister
  MOV EDX,[ESI-4] // Lange des SubStr in EDX
  DEC EDX // Length(SubStr) - 1
  JS @@fail
  // Vorzeichenbedingter Sprung (JumpIfSign)
  // d.h. (EDX < 0) -> Sprung zu 'fail'
  STD; // SetDirectionFlag -> Stringroutinen von hinten
  // abarbeiten
  ADD ESI, EDX // Pointer auf das letzte Zeichen vom SubStr
  ADD EDI, ECX
  DEC EDI // Pointer auf das letzte Zeichen von S
  MOV AL, [ESI] // letztes Zeichen des SubStr in AL laden
  DEC ESI // Pointer auf das vorletzte Zeichen setzen.
  SUB ECX, EDX // Anzahl der Stringdurchlaufe
  // = Length(s) - Length(substr) + 1
  JLE @@fail // Sprung zu 'fail' wenn ECX <= 0
@@loop:
  REPNE SCASB // Wdh. solange ungleich (repeat while not equal)
  // scan string for byte
  JNE @@fail
  MOV EBX,ECX { Zahleregister, ESI und EDI sichern, da nun der
  Vergleich durchgefuhrt wird ob die nachfolgenden
  Zeichen von SubStr in S vorhanden sind }

  PUSH ESI
  PUSH EDI
  MOV ECX,EDX // Lange des SubStrings in ECX
  REPE CMPSB // Solange (ECX > 0) und (Compare string fo byte)
  // dh. solange S[i] = SubStr[i]
  POP EDI
  POP ESI // alten Source- und Destinationpointer vom Stack holen
  JE @@found // Und schon haben wir den Index da ECX = 0
  // dh. alle Zeichen wurden gefunden
  MOV ECX, EBX // ECX wieder auf alte Anzahl setzen und
  JMP @@loop // Start bei 'loop'
@@fail:
  XOR  EAX,EAX // EAX auf 0 setzen
  JMP @@exit @@stringEmpty:
  XOR  EAX,EAX
  JMP @@noWork @@found:
  MOV EAX, EBX // in EBX steht nun der aktuelle Index
  INC EAX // um 1 erhohen, um die Position des 1. Zeichens zu
  // bekommen
@@exit:
  POP EDI
  POP ESI
  POP EBX
 @@noWork: CLD; // DirectionFlag loschen
end;

Взято с сайта: http://www.swissdelphicenter.ch

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...