Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi [TStringlist/string] Position => Zeile (https://www.delphipraxis.net/128767-%5Btstringlist-string%5D-position-%3D-zeile.html)

_frank_ 5. Feb 2009 18:08


[TStringlist/string] Position => Zeile
 
Moin,
gibt es eine Möglichkeit aus der Zeichen-Position in TStringlist.Text an die Zeilennummer heranzukommen?
klar könnte ich die Zeilenumbruch-Zeichen rückwärts zählen, aber vielleicht gibt es eine einfachere/schnellere Variante.

Gruß Frank

Helmi 5. Feb 2009 18:38

Re: [TStringlist] Position => Zeile
 
Hallo,

meinst du vielleicht:

Delphi-Quellcode:
for i := 0 to Pred(StringList.Count) do
  ShowMessage(StringList.Strings[i]);
also diesen Part:
Delphi-Quellcode:
StringList.Strings[i]

Hawkeye219 5. Feb 2009 18:42

Re: [TStringlist] Position => Zeile
 
Hallo Frank,

du könntest es mit dieser Funktion versuchen:

Delphi-Quellcode:
function LineIndexFromCharIndex (
           const aString   : string;
           const aCharIndex : Integer
         ) : Integer;
begin
  with TMemo.CreateParented(HWND(HWND_MESSAGE)) do
    try
      Text := aString;
      Result := SendMessage(Handle, EM_LINEFROMCHAR, aCharIndex, 0);
    finally
      Free;
    end;
end;
Gruß Hawkeye

_frank_ 5. Feb 2009 19:12

Re: [TStringlist] Position => Zeile
 
@Helmi:
Prinzipiell brauche ich das i aus deinem Beispiel.

Sinn und Zweck des ganzen ist, dass ich nach einer Textsuche die Zeile haben möchte, in der der Teilstring gefunden wurde. ich könnte zwar Zeilenweise suchen, aber wenn der gesuchte Text zeilenübergreifend ist, wird dieser nicht gefunden.

@Hawkeye
daran hatte ich auch schon gedacht, wollte aber ungern die VCL bzw. Windows-Controls dazu misbrauchen.

Gruß Frank

Helmi 5. Feb 2009 19:14

Re: [TStringlist] Position => Zeile
 
und das:

Delphi-Quellcode:
i := StringList.IndexOf(S)
?

_frank_ 5. Feb 2009 19:19

Re: [TStringlist] Position => Zeile
 
schau dir mal Hawkeyes code an...der dürfte das machen...

ich hab ne position, sagen wir 200 (ermittelt mittels pos(ex)&co) in nem string...dieser String hat zeilenumbrüche und ich weise das daher einfach mal einer stringliste zu (evtl. wird das auch nicht benötigt).
wie gesagt, ich könnte mittels

Delphi-Quellcode:
line:=0;
for i:=200 downto 1 do
begin
  if s[i]=#13 then inc(line);
end;
die zeilenende-zeichen zählen, aber vielleicht geht das ja auch eleganter :)

Gruß Frank

Klaus01 5. Feb 2009 19:21

Re: [TStringlist] Position => Zeile
 
Zitat:

Zitat von Helmi
und das:

Delphi-Quellcode:
i := StringList.IndexOf(S)
?

..funktionier nur dann, wenn der gesuchte Text mit der gesammten Zeile übereinstimmt.

Grüße
Klaus

Sereby 6. Feb 2009 09:22

Re: [TStringlist/string] Position => Zeile
 
sowas hab ich mir auch mal programmiert:
Delphi-Quellcode:
function TStringsHelper.GetLineByPos(const MyPosition: Integer): Integer;
var
  I,Line: Integer;
begin
  Result := -1;
  if (MyPosition = -1) then Exit;

  Line := 0;
  I := 1;
  while I < MyPosition do
  begin
    if (Text[I] = #13) then Line := Line + 1;
    I := I + 1;
  end;
  Result := Line;
end;
das ganze habe ich bei delphi 2009 in einen classhelper gepackt aber kannst es ja leicht umschreiben, dass es bei einer per parameter übergebenen stringlist sucht

nahpets 6. Feb 2009 09:55

Re: [TStringlist/string] Position => Zeile
 
Hallo,

versuch' es mal damit:
Delphi-Quellcode:
Function PosToLine(sl : TStrings;
                   sSearchText : String) : Integer;
Var
          iPos  : Integer;
          iStart : Integer;
          iEnde : Integer;
          s     : String;
begin
  // Position des gesuchten Textes ermitteln.
  iPos  := Pos(sSearchText,sl.Text);
  // Von dieser Position rückwärts den vorherigen Zeilenvorschub suchen.
  iStart := iPos;
  Repeat
    Dec(iStart);
  Until sl.Text[iStart] = #10;
  // Wir brauchen die Position hinter dem vorherigen Zeilenvorschub.
  Inc(iStart);
  // Von der Postion der gesuchten Zeichenfolge aus den nächsten Zeilenvorschub suchen.
  iEnde := iPos;
  Repeat
    Inc(iEnde);
  Until sl.Text[iEnde] = #13;
  // Die Zeichenfolge zwischen vorherigem und folgenden Zeilenvorschub holen.
  s     := Copy(sl.Text,iStart,iEnde - iStart);
  // Die Zeile mit der Zeichenfolge suchen und den Index zurückgeben.
  Result := sl.IndexOf(s);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(PosToLine(Memo1.Lines,Edit1.Text)));
end;

_frank_ 6. Feb 2009 15:51

Re: [TStringlist/string] Position => Zeile
 
Liste der Anhänge anzeigen (Anzahl: 1)
nahpets Lösung finde ich schon originell, ist aber um einiges langsamer als die Zählvariante (copy).
sereby's variante ist ähnlich meiner, da kommt mir aber gerade die idee, evtl pos(ex) mit einzuspannen...

so mal die messergebnisse (queryPerformanceCounter, gettickcount hat nicht gereicht):
frankw:34
sereby:34
sereby_pos:52
sereby_var:40
hawkeye:8352
nahpets:37050

wie man erkennt, sind sereby's und meine variante die schnellsten, danach serebys-variante mit var-parameter für s und danach die pos/posex-variante. irgendwann kommen dann die letzten beiden :)

für genauere messinfos hab ich mal das benchmark-programm angehängt.

Danke für die Antworten

//edit
hab das mal noch in µs/ms umgerechnet (mess-programm aktualisiert, gleich noch paar Fehler rausgemacht :) ):
frankw:7µs
sereby:7µs
sereby_pos:12µs
sereby_var:7µs
hawkeye:2,573ms
nahpets:11,478ms

da seh ich gerade, dass hawkeyes Version scheinbar falsch ist (249). die anderen Ergebnisse musste ich nur um 1 inkrementieren (position 5000 wäre zeile 109).

Gruß Frank


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz