Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.28;
Скачать: [xml.tar.bz2];




Вниз

Как найти далее при помощи pos? 


Delphimun   (2002-01-07 11:55) [0]

Как найти далее при помощи pos?

Вот способ, который находит только одно искомое слово, а как искать следующее слово(аналог ныйти далее в блокноте windows-а)

if pos(finddialog1.FindText,RichEdit1.Text)<>0 then
begin
RichEdit1.HideSelection := false;
RichEdit1.SelStart := pos(finddialog1.FindText,RichEdit1.Text)-1;
RichEdit1.SelLength := length(finddialog1.findtext);



Delphimun   (2002-01-07 14:26) [1]

Простой же вопрос много раз в форуме был, я просто найти не могу наверняка многие знают



NDeu   (2002-01-07 16:55) [2]

В Help-e TCustomRichEdit.FindText ест Example



Delphimun   (2002-01-07 18:22) [3]

мне нужно искать в файловой переменной, а не в richedit-е, загружать текст в richedit не могу, т.к его модуль много места кушает. Нужно всё сделать при помощи pos



marat_from_tomsk   (2002-01-08 05:16) [4]

работай порциями
после того как нашел первое вхождение
удали обработанную порцию и ищи дальше ...
или поищи требуемую функцию
вот например в FoxPro есть подходящая функция
найти n-ое вхождение



Андрей Сенченко   (2002-01-08 10:23) [5]

a := pos("a",str);
b := pos("b",Copy(str,a,(length(str)-pos("a",str));

Примерно так. Но еще нужно учесть ЧТО возвращает pos() и расставить +-1 во второй строке в нужных местах



Юрий Зотов   (2002-01-08 11:04) [6]

Как легко заметить, помещая код Андрея Сенченко в цикл от 1 до N, находим то самое N-е вхождение. А помещая в цикл while, находим все вхождения. И при этом исходная строка остается неизменной.



Delphimun   (2002-01-08 13:43) [7]

я не совсем понял, напишите пожалуйста пример, с моим кодом(который выше),



Delphimun   (2002-01-08 13:45) [8]

а работать пропорциями для меня не совсем выгодно, т.к нужно
обрабатывать очень большое кол-во текста

Пример мне нужен с кодом Андрея Сенченко.



Romkin   (2002-01-08 13:59) [9]

Если большое количество - пиши ручками, есть много алгоритмов быстрого поиска, надо только реализовать



panov   (2002-01-08 15:04) [10]

Из блестящей идеи Андрей Сенченко © (08.01.02 10:23)
и Юрий Зотов © (08.01.02 11:04)
родилось вот такое творение:

function SearchString( const FindStr, SourceString: String;Num: Integer):Integer;
var
FirstP: PChar;
function MyPos(const FindStr, SourceString: PChar;Num: Integer): PChar;
begin
Result := AnsiStrPos(SourceString,FindStr);
if (Result=nil) then Exit;
Inc(Result);
if Num=1 then Exit;
if num>1 then Result := MyPos(FindStr,Result,num-1);
end;
begin Result := 0;
FirstP := PChar(SourceString);
Result := MyPos(PChar(FindStr),PChar(SourceString),Num) - FirstP;
if Result<0 then Result := 0;
end;



SoftOne   (2002-01-08 15:11) [11]

А можно было и не думать, а использовать готовые функции из модуля StrUtils пакета RXLib.



panov   (2002-01-08 15:12) [12]

А зачем лишние компоненты использовать??



SoftOne   (2002-01-08 15:17) [13]

> panov.
А это не компоненты. Это просто функции.



Song   (2002-01-08 16:35) [14]

а можно присвоить вашу переменную другой, временной и после каждого последующего поиска удалять найденнный текст с начала до найденной позиции вместе с найденным символом и тогда следующий найденный символ, если даже он такой как и предыдущий, найдётся без проблем



panov   (2002-01-08 16:45) [15]

Это нормальное решение в лоб, но поэффективности(скорость работы) самое медленное...



Alx2   (2002-01-08 16:57) [16]

Если при помощи Pos и почти эффективно, то:

function NextSubStr(Const SubStr,Str : String; PrevIdx : Integer):Integer;
begin
if (PrevIdx<Length(Str)) and (PrevIdx>0)
then
Result := pos(SubStr,PChar(@Str[PrevIdx]))+PrevIdx-1
else
Result := 0;
end;
Var k : Integer;
begin
k :=NextSubStr("a","abcabcabc",1);
Label1.Caption:=IntToStr(k); // Выводим позицию первого вхождения строки "a"
k :=NextSubStr("a","abcabcabc",k+1);
Label2.Caption:=IntToStr(k); // Выводим позицию следующего вхождения строки "a"
end;



Alx2   (2002-01-08 16:58) [17]

Ой!
Надо if (PrevIdx<=Length(Str)) and (PrevIdx>0)



Alx2   (2002-01-08 17:00) [18]

Блин, еще проверить не вернет ли pos ноль и если вернет, то Result := 0. Сорри. Тороплюсь :))



Romkin   (2002-01-08 17:18) [19]

Попробовал, вот что получилось - функция не оптимальна, но вроде работает, эвристика по стоп-символу и суффиксу, дает значительный выигрыш на больших кусках текста и при длинных образцах (при коротких тоже неплохо)
Прибраться только надо, чтобы побыстрее работала... но влом

function fStrPos(const Line, Sample: string; FromPos, ToPos: integer): integer;
var
stLen, samLen: integer;
StopIndex: integer;
StopChar, ch: char;
SuffixStr, RevertSample: string;
SuffixLen: integer;
i, incr: integer;
begin
Result := 0;
//checks
SamLen := length(Sample);
if SamLen = 0 then exit;
if FromPos <= 0 then FromPos := 1;
stLen := length(Line);
if (ToPos < stLen) and (toPos >= FromPos) then
stLen := toPos;
//Переворачиваем Sample - удобно для Pos
SetLength(RevertSample, SamLen);
for i := 1 to SamLen do
RevertSample[SamLen - i + 1] := Sample[i];
//Пока не дошли до конца участка минус длина образца...
while FromPos <= (stLen - samLen + 1) do
begin
//сравниваем образец СПРАВА НАЛЕВО
StopIndex := 0;
for i := samLen downTo 1 do
if Sample[i] <> Line[i + FromPos - 1] then
begin
//На чем запнулись
StopIndex := i;
StopChar := Line[i + FromPos - 1];
SuffixStr := copy(Sample, i+1, samLen - i);
SuffixLen := length(SuffixStr);
Break;
end;
//Проверка совпадения
if StopIndex = 0 then
begin
Result := FromPos;
Exit;
end;
//Переворачиваем суффикс
for i := 1 to (SuffixLen div 2) do
begin
ch := suffixstr[SuffixLen - i + 1];
suffixstr[SuffixLen - i + 1] := suffixStr[i];
suffixstr[i] := ch;
end;
//Приращение по суффиксу - следующее вхождение
incr := Pos(SuffixStr, copy(RevertSample,SuffixLen + 1,SamLen));
//Приращение по стоп-символу:
for i := StopIndex - 1 downTo 1 do
if Sample[i] = StopChar then
begin
if incr < (SamLen - i) then
incr := SamLen - i;
break;
end;
if incr = 0 then incr := samLen;
inc(FromPos, incr);
end;
end;



Yaro   (2002-01-08 18:08) [20]

Люди, я чот не пойму, нафиг вам POS??? Прекрасно и без него обойтись можно...
Просто делайте по такому принципу:
Пусть текст, в котором надо осуществить поиск будет Text, а искомый кусок будет, скажем, F_text...
Производим сканирование посимвольно, ищем все вхождения (назовем это Text[i]) f_text[1], после того как нашли сравниваем Text[i+1] и f_text[2] и так далее... Если не подходит хотяб один знак в цикле проверки символов, идем дальше...
В принципе способ эффективный, так как не "жрет" сильно много "больших" сравнений, как было бы, если сранивать таким образом - if copy(Text, i, length(Text)) = f_text...



Romkin   (2002-01-08 18:27) [21]

Не смотрите на Romkin © (08.01.02 17:18),
я в смещениях запутался!!! и голова не работает, завтра, завтра...



panov   (2002-01-08 20:28) [22]

>Romkin © (08.01.02 18:27)
Ну вот, а если завтра этот вопрос в FAQ попадет?



Romkin   (2002-01-09 11:46) [23]

Вариант - системный поиск
Нагло вырезана AnsiPos и переиначена на поиск с позиции

uses SysUtils;

function fAnsiPos(const Substr, S: string; FromPos: integer): Integer;
var
P: PChar;
begin
Result := 0;
P := AnsiStrPos(PChar(S) + fromPos - 1, PChar(SubStr));
if P <> nil then
Result := Integer(P) - Integer(PChar(S)) + 1;
end;

AnsiStrPos - можно просто вырезать из SysUtils



Romkin   (2002-01-09 14:50) [24]

Второй вариант:

function TailPos(const S, SubStr: string; fromPos: integer): integer;
asm
PUSH EDI
PUSH ESI
PUSH EBX
PUSH EAX
OR EAX,EAX
JE @@2
OR EDX,EDX
JE @@2
DEC ECX
JS @@2

MOV EBX,[EAX-4]
SUB EBX,ECX
JLE @@2
SUB EBX,[EDX-4]
JL @@2
INC EBX

ADD EAX,ECX
MOV ECX,EBX
MOV EBX,[EDX-4]
DEC EBX
MOV EDI,EAX
@@1: MOV ESI,EDX
LODSB
REPNE SCASB
JNE @@2
MOV EAX,ECX
PUSH EDI
MOV ECX,EBX
REPE CMPSB
POP EDI
MOV ECX,EAX
JNE @@1
LEA EAX,[EDI-1]
POP EDX
SUB EAX,EDX
INC EAX
JMP @@3
@@2: POP EAX
XOR EAX,EAX
@@3: POP EBX
POP ESI
POP EDI
end;



Song   (2002-01-09 15:14) [25]

Даааа, ребят, такоооое развернули из обычной несложной задачи... :)))



Андрей Сенченко   (2002-01-09 17:01) [26]

Не помню где, по-моему у Экслера была такая прибаутка:
Начинающий программист пишет
10 BEGIN
20 PRINT "HELLO WORLD"
...
далее опускаю
...
Супер крутой системщик пишет : ... и далее следовал код по-моему строк на 500 с такими изворотами, что просто мама дорогоая.



Romkin   (2002-01-09 17:32) [27]

2Андрей Сенченко:
Это уже цикл...
На самом деле, задача поиска подстроки довольно сложная, особенно это заметно при длинных строках - элементарный алгоритм работает долго, умный - летает... Все примерно как с сортировкой - пузырьком - не больше десятка чисел, quicksort - для больших массивов в виртуальной памяти, и тд



Anatoly Podgoretsky   (2002-01-09 20:51) [28]

Romkin © (09.01.02 11:46)
Result := P - PChar(S) + 1;

Romkin © (09.01.02 14:50)
Насчет ассеблерного алгоритма, комментировать особо не буду, только скажу что очень неэффективный алгоритм, используются аггрегатные команды, на современных процессорах большое пенальти.

Romkin © (09.01.02 17:32)
Насчет ума это верно. Если я тебе скажу, что при определенных условиях пузырьковый алгоритм бует быстрее быстрой сортировки - ты мне поверишь?




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.28;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.78 MB
Время: 0.03 c
3-90232           Стас                  2001-12-24 11:19  2002.01.28  
DBLookupBox


3-90188           Andrey_ask            2001-12-21 19:50  2002.01.28  
Потеря записей


1-90265           panov                 2002-01-09 08:46  2002.01.28  
QReport.Preview Как это работает?


1-90317           Val                   2002-01-11 17:28  2002.01.28  
видимость в секции private


1-90275           Mr. API               2001-12-27 19:31  2002.01.28  
работа с архивами