Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Zeichen bzw Zeilen zählen in Richedit bzw String


Wolff68 - Di 06.08.02 21:38
Titel: Zeichen bzw Zeilen zählen in Richedit bzw String
Hi!
Folgendes Problem:
Wenn man in einem Richedit etwas selektiert gibt es ja netterweise die Parameter SelStart und SelLength.
In SelStart steht dann drin ab welchem Zeichen die Selektion beginnt.
Schön.
Nur bräuchte ich die entsprechende Zeilen-Nummer und das Zeichen in der Zeile. Also im Format L: xxx Z:xxx
Auf die Schnelle hab ich das mal so gelöst, was zwar funktioniert aber natürlich nicht so richtig toll ist:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function TForm2.LineNr(Start: Integer): String;
var i, LineCount, LastRet: Integer;
begin
 LineCount := 0;
 For i := 1 to Start Do
  IF RichEdit1.Text[i] = #13 then begin
   INC(LineCount);
   LastRet := i;
  end;
 Result := 'L:'+IntToStr(LineCount)+'Z:'+IntToStr(Start-LastRet);
end;

Der Funktion übergeb ich also das Ergebnis von RichEdit1.SelStart und schau dann nach, wieviele #13 davorliegen.
Voll stümperhaft, deshalb such ich ja was besseres.
Gibt es in Delphi eine Funktion, die mir die Anzahl eines Bestimmten Zeichens in einem String liefert?
Oder gibt es bei Richedit was anderes als dieses SelStart?
Hab grad nichts gefunden. :-(
Oder gibt es andere brauchbare Wege um zum gewünschten Ergebnis zu kommen?

Danke Euch!


Christian S. - Di 06.08.02 22:21

Hi!


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure LZ (RichEdit1 : TRichEdit; VAR L,Z : INTEGER);
VAR backup : STRING;
    i : INTEGER;
begin
  backup:=RichEdit1.Text;
  RichEdit1.Text:=Copy(RichEdit1.Text,1,RichEdit1.SelStart)+'%%'+
                  Copy(RichEdit1.Text,RichEdit1.SelStart,Length(RichEdit1.Text)-RichEdit1.SelStart);

  for i:=0 TO RichEdit1.Lines.Count-1 DO
  if pos('%%',RichEdit1.Lines[i]) > 0 then break;

  L:=i;
  Z:=pos('%%',RichEdit1.Lines[i]);
  RichEdit1.Text:=backup;
end;


Wenn wir annehmen, dass "%%" im RichEdit1 nicht vorkommt, wäre das auch eine Lösung. Ob sie besser ist, wage ich zu bezweifeln ...

MfG,
Peter


Wolff68 - Mi 07.08.02 21:30

Danke für die Mühe, Peter.
Wie Du schon sagtest, viel besser ist Deine Variante nicht. Immerhin zählt sie aber bereits die Zeilen, und vergleicht nicht Zeichen für Zeichen!

Daß Du den Text bis zur Selektion kopiert hast brachte ich aber auf folgende Idee:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
function TForm2.LineNr(Start: Integer): String;
begin
  RichEdit2.Text := Copy(RichEdit1.Text,0,Start);
  Result := 'L'
            +IntToStr(RichEdit2.Lines.Count-1)
            +'Z'
            +IntToStr(Length(RichEdit2.Lines[RichEdit2.Lines.Count-1])+1);
end;

Denn nachdem ich alles bis zur Selection in ein neues Richedit kopiert habe bekomme ich ja mit Lines.Count-1 die Nummer der letzten Zeile, und mit der Länge der letzten Zeile auch die Position des Zeichens raus :-)

Ob ich mit dem zweiten Richedit nun mit Kanonen auf Spatzen schieße kann natürlich sein....
Aber wenn ich den Text des sichtbaren RichEdit komplett neu setze verliere ich die Cursorposition, bzw die Selektion.
Der User müsste also immerwieder von oben anfangen zu scrollen usw.


Da ich hier im Moment #13 suche kann ich auch die Lines.Count verwenden. Gut soweit. Was aber wenn ich was anderes suchen müsste?
Gibt es wirklich nichts anderes als Char für Char zu vergleichen?

Mein Problem ist zwar gelöst, aber die Frage ob es für das Zählen etwas anderes gibt eigentlich noch nicht!


Christian S. - Mi 07.08.02 22:06

Hi!

Ich bin mir nicht sicher, ob ich Deine Frage richtig verstanden habe. Aber um die Anzahl von einem bestimmten Zeichen in einem String zu finden, habe ich mir folgende Methode ausgedacht:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function anzahl_zeichen (zeichen: Char; text: STRING) : Integer;
VAR position : Integer;
    neu_text : STRING;
begin
  position:=Pos(zeichen,text);
  if position=0 then result:=0
  else begin
    neu_text:=Copy(text,position+1,Length(text)-position);
    result:=1+anzahl_zeichen(zeichen,neu_text);
  end;
end;


Wahrscheinlich ist es gar nicht das was du wolltest, oder?

MfG,
Peter


wwerner - Do 08.08.02 07:21

Suchst du das?

http://www.swissdelphicenter.ch/de/showcode.php?id=165


Wolff68 - Sa 10.08.02 23:18

Hey wwerner!
Super! Genau sowas hab ich gesucht.
Hatte mir dieses SendMessage noch nie so genau angesehen und werds wohl erst umsetzen wenn ich es kapiert hab. :-) Aber Danke für den Link. Genau sowas hab ich gesucht.

An Peter: Wow, Also ich schrecke immer ein wenig zurück Funktionen rekursiv zu machen und dabei auch noch Variablen zu definieren. Die können sich nämlich ganz schön summieren...
Den Ansatz find ich gut. Ich würde das aber eher in eine Schleife packen und per Delete von vorne weglöschen. Also eher so:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
function AnzahlZeichen(Zeichen:Char; Text: String): Integer;
begin
 result := 0;
 while Pos(Zeichen, Text) > 0 Do Begin
  Inc(result);
  Delete(Text, 1, Pos(Zeichen, Text));
 end;
end;

Meine Frage war eigentlich eher, ob es nicht bereits eine Funktion für sowas innerhalb des RichEdits gibt. Aber anscheinend ja nicht....

Oder gibts da auch was via SendMessage? Muss mir das mal genauer anschauen. Hab überhaupt nicht an das SendMesage gedacht, scheint aber Potential zu bieten :-)


Gruß, Wolff


MathiasH - So 11.08.02 10:46

das es einen Einzeilen Trick gibt weis ich, ab wie ging der nochmal.........

Wo ist dieses dumme Buch, wenn man's mal braucht? mal suchen vielleicht find ich's noch :wink:

MathiasH


CenBells - Di 17.09.02 12:26

weiß jemand, welche unit ich für den tip aus dem swissdelphicenter einbinden muss?
Delphi findet die Bezeichner EM_LINEFROMCHAR und oder EM_LINEFROM INDEX nicht.
gruß
Ken


Tino - Di 17.09.02 12:43

Binde mal die Unit Messages ein!


CenBells - Di 17.09.02 13:42

hat nicht geklappt, aber egal. ich mache es nun mit
Richedit.CaretPos.Y für die zeile und
Richedit.CaretPos.X für die Spalte.

Danke trotzdem
Ken