Нахождение последнего вхождения подстроки в строку
Falk0ner, вс, 06/07/2008 - 15:34.
Нахождение последнего вхождения подстроки в строку
{ **** 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;
>> Нахождение последнего вхождения подстроки в строку
Функция возвращает начало последнего вхождения
подстроки 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;
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;
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
Отправить комментарий