| Autor |
Beitrag |
galagher
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 07.01.09 20:58
Hallo!
Das geht doch auch anders, ich glaube, schneller:
Delphi-Quelltext
Aber ich komm' nicht drauf, wie. Ich wüsste auch nicht, wonach ich da suchen sollte. Ich glaube nur, dass es da auch noch eine andere Art gibt, an s anzuhängen. Hat jemand eine Idee?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 07.01.09 21:16
Grundsätzlich nicht, in speziellen Fällen gibts da auch Tricks. Nämlich dann, wenn du in einer Schleife jeweils einen Buchstaben anhängst, der String also immer weiter wächst.
In dem Fall kannst du einfach vorher die Länge hochsetzen und danach auf die tatsächliche Länge kürzen.
Und für das Setzen der einzelnen Buchstaben gibts auch noch Tricks um die Performance zu erhöhen. Ich bin so auf ca. 150.000.000 verarbeitete Buchstaben pro Sekunde gekommen bei einer Entschlüsselung.
// EDIT:
Ach ja: Und wenn Text die Eigenschaft eines Memos ist: Lies das vorher in einen String statt immer wieder auf den Memoinhalt zuzugreifen.
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 07.01.09 22:01
jaenicke hat folgendes geschrieben : | Nämlich dann, wenn du in einer Schleife jeweils einen Buchstaben anhängst, der String also immer weiter wächst.
In dem Fall kannst du einfach vorher die Länge hochsetzen und danach auf die tatsächliche Länge kürzen. |
Kannst du mir ein einfaches Beispiel geben?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 07.01.09 22:34
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 07.01.09 22:46
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 07.01.09 22:58
Wenn du genauer zeigst was du da optimieren willst, dann lässt sich da auch mehr dazu sagen. 
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 07.01.09 23:28
jaenicke hat folgendes geschrieben : | Wenn du genauer zeigst was du da optimieren willst, dann lässt sich da auch mehr dazu sagen.  |
Ich dachte einfach, bei zB. nur 10 Schleifendurchläufen spielt das ja keine Rolle, aber bei einigen tausend könnte es ja etwas bringen, wenn man da optimiert. Vor allem, wenn diese Schleifendurchläufe immer wieder ausgeführt werden.
Ich weiss, dass es anders als s := s+Text[i] auch geht, es ist auch nicht aufwändig. Steht sogar im Delphi-Forum irgendwo, aber ich weiss absolut keinen Zusammenhang mehr oder auch nur ein Stichwort, wonach ich suchen könnte. Ich erinnere mich nur, dass es irgendwann irgendjemand in irgendeinem Thread irgendwo beiläufig erwähnt hat!
Nicht, dass der Code so langsam wäre, aber einfach aus Interesse:
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:
| function WordatCaret: String; var i, n: Integer; s: String; begin s := '';
with RichEdit1 do begin n := SelStart+1;
for i := SelStart downto 0 do begin if Text[i] = ' ' then break; Dec(n); end;
for i := n to Length(Text) do begin if (Text[i] = ' ') or (Text[i] = #13) then break; s := s+Text[i]; end; end;
Result := s; end; |
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 07.01.09 23:47
Hier ist das Vorgehen das langsamste. Du kopierst die Zeichen einzeln. Stattdessen solltest du Anfang und Ende des Wortes suchen und danach das ganze Wort in einem Rutsch kopieren. Das kannst du auch mit CopyMemory machen, das wäre wohl am schnellsten. 
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Do 08.01.09 09:17
Du greifst für jedes Zeichen auf die Text-Eigenschaft des TRichedit-Controls zu. Die wiederum wird jedesmal aus den einzelnen Zeilen gebildet. Und das dürfte schonmal sehr langsam sein: Erstelle also zunächst eine Kopie des RichEdit-Textes in einer lokalen Variablen und arbeite mit dieser.
@jaenike: Wenn ich erst die Position des Wortes suche, und dann mit copyMemory arbeite, dann durchlaufe ich diese Stelle im String 2x (einmal zum Suchen und dann nochmals zum Kopieren). Das ist nach meiner Erfahrung langsamer, als das das stetige Kopieren eines Zeichens. Eventuell könnten CopyMemory-Spezialversionen von FastCode.org diesen Nachteil zunichte machen, es bliebe aber trotzdem beim zweimaligen Durchlaufen.
Selbst Konstrukte wie: s:=s+Text[i] sind nicht mehr böse Performancebremsen, da Delphi seit Version 2005(?) durch die Verwendung des optimierten Speichermanagers hier nicht jedesmal neuen Speicher zuweist. Es wäre trotzdem zu überlegen, ob man nicht 's' zunächst auf -sagen wir- 2000 Zeichen festsetzt und einmalig zum Schluss die konkrete Wortlänge festsetzt.
Abschließend wäre es hilfreich, die Funktion unabhängig vom TRichEdit zu machen:
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:
| Function WordAtCaret (Const sText : String; aCaretPos : Integer) : String; Var iCaret, ResultPos : Integer;
Begin SetLength (Result, ciMaxWordLength); iCaret := aCaretPos + 1; While (iCaret>1) And (sText[iCaret])=' ' Do Dec(iCaret); ResultPos := 0; while (iCaret <= Length (sText)) And Not (sText[iCaret] in [' ', #13]) Do Begin Inc (ResultPos);
Result[ResultPos] := sText[iCaret]; inc (iCaret); End; SetLength (Result, ResultPos); End; ... TheWord := WordAtCaret (RichEdit.Text, RichEdit.SelStart); |
Setze die Konstante ciMaxWordLength auf soetwas wie 1000 (oder z.B. 200, wenn keine Zeile länger als 200 Zeichen ist)
_________________ Na denn, dann. Bis dann, denn.
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Do 08.01.09 18:39
alzaimar hat folgendes geschrieben : | | Selbst Konstrukte wie: s:=s+Text[i] sind nicht mehr böse Performancebremsen, da Delphi seit Version 2005(?) durch die Verwendung des optimierten Speichermanagers hier nicht jedesmal neuen Speicher zuweist. Es wäre trotzdem zu überlegen, ob man nicht 's' zunächst auf -sagen wir- 2000 Zeichen festsetzt und einmalig zum Schluss die konkrete Wortlänge festsetzt. |
Ich benutze Delphi 6.
Leider klappt dein Code nicht. Statt des Aufrufes
Delphi-Quelltext 1:
| TheWord := WordAtCaret (RichEdit.Text, RichEdit.SelStart); |
müsste man
Delphi-Quelltext 1:
| TheWord := WordAtCaret (RichEdit.Text, RichEdit.SelStart - Länge_des_Wortes); |
angeben, aber die Länge des Wortes ist ja zunächst noch unbekannt, da das Wort ja erst ermittelt werden soll!
Es soll eine Rechtschreibkorrektur als Teil eines Programms werden. Jedesmal, wenn der Benutzer die Leertaste oder Enter drückt, soll das letzte Wort korrigiert werden.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Do 08.01.09 19:12
Geht natürlich, aber was mir nicht gefällt, ist, dass ich eine globale Variable verwenden muss, die mir die Länge des Wortes angibt. Ich möchte nämlich das Wort im RichEdit selektieren und, falls nötig, korrigieren.
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:
| function WordAtCaret(const sText: String; aCaretPos: Integer): String; var iCaret, ResultPos, i: Integer; begin SetLength (Result, 1000); for iCaret := aCaretPos downto 0 do if (sText[iCaret] in [' ', #10]) then break;
iCaret := iCaret+1;
while (iCaret > 1) and (sText[iCaret] = ' ') do Dec(iCaret);
ResultPos := 0;
while (iCaret <= Length (sText)) and not (sText[iCaret] in [' ', #13]) do begin Inc (ResultPos); Result[ResultPos] := sText[iCaret]; Inc(iCaret); end;
SetLength(Result, ResultPos);
iWortLength := Length(Result); end; |
Für die Wortkorrektur gibt es eine Liste EingabeKorrL, die Items haben jeweils das Format wort|Wort - links = falsch, rechts = korrekt.
Der Aufruf:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| for i := 0 to EingabeKorrL.Count-1 do begin if WordAtCaret(RichEdit1.Text, RichEdit1.SelStart) = GetShortHint(EingabeKorrL[i]) then begin with RichEdit1 do begin Lines.BeginUpdate; SelStart := SelStart-iWortLength; SelLength := iWortLength; SelText := GetLongHint(EingabeKorrL[i]); Lines.EndUpdate; end; break; end; end; |
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Do 08.01.09 20:14
Ich würde die Funktion so verändern, das sie den Wortanfang zurückliefert (iCaretPos).
_________________ Na denn, dann. Bis dann, denn.
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 09.01.09 16:43
alzaimar hat folgendes geschrieben : | | Ich würde die Funktion so verändern, das sie den Wortanfang zurückliefert (iCaretPos). |
Einfacher ist, zuerst an eine Variable zuzuweisen: s := WordAtCaret(RichEdit1.Text, RichEdit1.SelStart); , dann kan man einfach mit Length(s) arbeiten.
Danke euch für die Hilfe!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 09.01.09 19:49
Hier der komplette Code, getestet mit TMemo und TRichEdit. Wortkorrektur ist inkludiert!
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:
|
function WordCorrection(const CustomMemo: TCustomMemo; aCaretPos, iMaxWordLen: Integer; const WordCorrList: TStringList): String; var iCaret, ResultPos, iPos: Integer; sText: String; begin SetLength(Result, iMaxWordLen);
sText := CustomMemo.Text;
iCaret := aCaretPos;
if aCaretPos > 1 then for iCaret := aCaretPos downto 0 do if (sText[iCaret] in [' ', #0, #10]) then break;
Inc(iCaret); while (iCaret > 1) and (sText[iCaret] = ' ') do Dec(iCaret);
ResultPos := 0;
while (iCaret <= Length(sText)) and not (sText[iCaret] in [' ', #13]) do begin Inc (ResultPos);
if ResultPos > Length(Result) then SetLength(Result, Length(Result)+iMaxWordLen);
Result[ResultPos] := sText[iCaret]; Inc(iCaret); end;
SetLength(Result, ResultPos); if (Result = '') or (Pos(#10, Result) > 0) or (Pos(#13, Result) > 0) or (Pos(' ', Result) > 0) then exit;
for iCaret := 0 to WordCorrList.Count-1 do begin if Result = GetShortHint(WordCorrList[iCaret]) then begin with CustomMemo do begin iPos := SelStart; Lines.BeginUpdate; SelStart := SelStart-Length(Result); SelLength := Length(Result); if (Pos(' ', SelText) > 0) or (Pos(#10, SelText) > 0) or (Pos(#13, SelText) > 0) then begin SelStart := iPos; Sellength := 0; Lines.EndUpdate; break; end;
SelText := GetLongHint(WordCorrList[iCaret]); Lines.EndUpdate; end; break; end; end; end; |
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
|