Entwickler-Ecke
Algorithmen, Optimierung und Assembler - FindText für Memo
starsurfer - So 12.02.06 22:02
Titel: FindText für Memo
Ich schreib garde an nem aufgemotzten Windows Editor.
Und dazu muss ich ja auch in dem Memo nach Wörtern suchen.
Nun bietet ja Richedit eine kleine Funktion die Findtext heist, aber wie ich feststellen musste besitzt Memo die Funktion nicht.
Also hab ich das Internet angeschmissen und hier im Forum gesucht und wieder Erwarten nichts passendes gefunden(Hinweise auf pos() zählen da mit drunter).
Ihr könnt mich natürlich eines Besseren belehren :o
Lange Rede kurzer Unsinn.... hab ich mir die Funktion halt selber geschreiben:
AMemo: Memo in dem gesucht wird
Search_Text:zu suchender Text
Direction: Suchrichtung (true=vorwärts,false=rückwärts)
Case_Sensitiv: Groß und Kleinschreibung beachten/missachten
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
| function MemoFindText(AMemo:TMemo;Search_Text:string;Direction,Case_Sensitiv:bool):integer; var sstart,slength,sendpos,i:integer; cut:string; c:char; begin sstart:=AMemo.SelStart; slength:=AMemo.SelLength; sendpos:=length(AMemo.lines.text); if Case_sensitiv=false then ansilowercase(Search_Text); if direction=true then begin for i:=sstart+slength to sendpos do begin c:=AMemo.lines.text[i]; if Case_sensitiv=false then c:=ansilowercase(c)[1]; if c=Search_Text[1] then begin cut:=copy(AMemo.lines.text,i,length(Search_text)); if Case_sensitiv=false then cut:=ansilowercase(cut); if cut=Search_text then begin result:=i-1; exit; end; end; end; end else begin for i:=sstart-slength downto 0 do begin c:=AMemo.lines.text[i]; if Case_sensitiv=false then c:=ansilowercase(c)[1]; if c=Search_Text[1] then begin cut:=copy(AMemo.lines.text,i,length(Search_text)); if Case_sensitiv=false then cut:=ansilowercase(cut); if cut=Search_text then begin result:=i-1; exit; end; end; end; end; result:=-1;end; |
Die Funktion läuft ganz gut. Sie liefert die Anfangsposition des gesuchen Wortes wieder.
ABER bei großen Datei wird sie leider sehr langsam :?
Habt ihr irgendwelche Ideen wie man diese Funktion optimieren kann ?
Blackheart666 - So 12.02.06 22:15
Was spricht denn gegen RichEdit wenns ein aufgemotzter Editor sein soll.
starsurfer - So 12.02.06 22:31
Ich hab nicht geplant das der Text formatiert werden kann. Er soll weder bunt noch kursiv, fett usw... dargestellt werden.
Und diese Formatierung is ja der große Unterschied zwischen Memo und Richedit...
(ok am Ende is das Ergebnis das Gleiche...also aus Prinzip:Memo :D )
Gausi - Mo 13.02.06 10:26
Titel: Re: FindText für Memo
starsurfer hat folgendes geschrieben: |
Habt ihr irgendwelche Ideen wie man diese Funktion optimieren kann ? |
Wenn du wirklich nicht Pos etc. nehmen willst, dann musst du dir einen vernünftigen Stringsuch-Algorithmus schreiben. Beispiele dafür wären
KNUTH-MORRIS-PRATT-ALGORITHMUS oder
BOYER-MOORE-ALGORITHMUS. Die sind etwas komplizierter zu durchblicken, sind aber wesentlich schneller als dein (naiver) Algorithmus.
starsurfer - Di 14.02.06 17:12
thx gausi für dein Rat :)
ich hab meine Funktion jetzt ma auf
BOYER-MOORE-ALGORITHMUS umgestellt...
das is bei raus gekommen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85:
| function memofindtext(AMemo:TMemo;Search_Text:string;Direction,Case_Sensitiv:bool):integer; var switch_list:array[32..255] of integer; j,i,sstart,sendpos,searchpos,jumpvalve:integer; ordvalve:byte; cut:string; begin sstart:=AMemo.SelStart; sendpos:=length(AMemo.lines.text); if Case_sensitiv=false then Search_text:=ansilowercase(Search_Text); if Direction = True then begin for j:=32 to 255 do begin switch_list[j]:=length(Search_Text); for i:=length(Search_Text) downto 1 do begin if chr(j)=Search_Text[i] then begin switch_list[j]:=length(Search_Text)-i; break; end; end; end; searchpos:=sstart+1; jumpvalve:=0; repeat searchpos:=searchpos+jumpvalve; if Case_sensitiv=false then ordvalve:= ord(ansilowercase(AMemo.lines.text[searchpos+1])[1]) else ordvalve:= ord(AMemo.lines.text[searchpos+1]); if ordvalve<32 then jumpvalve:=length(Search_text) else jumpvalve:=switch_list[ordvalve]; if jumpvalve=0 then begin result:=searchpos-length(search_text)+1; cut:=copy(AMemo.lines.text,searchpos-length(Search_Text)+2,length(search_text)); if case_sensitiv=false then cut:=ansilowercase(cut); if (searchpos-sstart>=length(Search_Text)) and (cut=Search_text) then exit else inc(searchpos); end; until (searchpos>=sendpos); end else begin for j:=32 to 255 do begin switch_list[j]:=length(Search_Text); for i:=1 to length(Search_Text) do begin if chr(j)=Search_Text[i] then begin switch_list[j]:=i-1; break; end; end; end; searchpos:=sstart-1; jumpvalve:=0; repeat searchpos:=searchpos-jumpvalve; if Case_sensitiv=false then ordvalve:= ord(ansilowercase(AMemo.lines.text[searchpos+1])[1]) else ordvalve:= ord(AMemo.lines.text[searchpos+1]); if ordvalve<32 then jumpvalve:=length(Search_text) else jumpvalve:=switch_list[ordvalve]; if jumpvalve=0 then begin result:=searchpos; cut:=copy(AMemo.lines.text,searchpos+1,length(search_text)); if case_sensitiv=false then cut:=ansilowercase(cut); if (sstart-searchpos>=length(Search_Text)) and (cut=search_text) then exit else dec(searchpos); end; until (searchpos<=0); end; result:=-1; end; |
er ist schon wesentlich schneller als mein "alter" algorithums...
Aber kann man den noch irgendwo optimieren?
Horst_H - Di 14.02.06 17:30
Hallo,
fuer die Vorwaertssuche ist es wohl einfacher so
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| function MemoFindText(AMemo:TMemo;Search_Text:string;Case_Sensitiv:bool):integer; var sstart,slength:integer; cut:string; begin sstart:=AMemo.SelStart; slength:=AMemo.SelLength; cut := copy(AMemo.lines.text,sStart,sLength); IF Not(Case_Sensitiv) then begin cut := lowercase(cut); Search_Text := lowercase(Search_Text); end; Result := Pos(Search_Text,cut); If Result > 0 then Result := Pos +sStart; end; |
Gruss Horst
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!