Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Teilstring suchen (https://www.delphipraxis.net/112263-teilstring-suchen.html)

Hugo Hasi 17. Apr 2008 19:17


Teilstring suchen
 
Hallo Leute... ich will lieber nicht wissen der wievielte Thread das zu diesem Thema ist :oops: , und ich hab mir auch einige dazu durchgelesen, aber trotzdem tut das Programm nicht das, was es eigentlich soll.
Also es geht um ein TList, die Autoren und die Bücher, die diese geschrieben haben, verwalten soll. Man gibt sozusagen Autor und Titel in zwei Felder ein und dann erscheinen die in der Liste.
Nun will ich aber den Autor suchen können... es erscheint auch keine Fehlemeldung aber, wenn ich einen Autor suche, erscheint gleich die Nachricht'Der Autor konnte nicht gefunden werden.', obwohl der Autor in der Liste steht. Vielleicht ist ja jemand so nett und kann sich mal anschauen, was ich da so (alles) falsch gemacht habe. Hoffe ich hab alle nötigen Infos da unten stehen... wäre echt hilfreich!!!
thx


Delphi-Quellcode:
procedure TForm1.SuchenButtonClick(Sender: Tobject);
var gefunden,j,n,suchbegriff,zeile:string;
i,max,separator:integer;
begin
 autorfeld.Text:=suchbegriff;
 i:=0;
 gefunden:=n;
 max:=Listenfenster.Items.Count-1;
 repeat
  Listenfenster.Items.Strings[i];
  zeile:=Listenfenster.Items.Strings[i];
  separator:=pos(#45,zeile);
  autorfeld.text:=copy(zeile,1,separator-1);
  if(autorfeld.text=suchbegriff) then begin
   i:=Listenfenster.ItemIndex;
   gefunden:=j;
  end else begin
  i:=+1;
  end;
 until (gefunden=j)or (i>max);
  if (gefunden=n) then begin
  ShowMessage('Der Autor konnte nicht gefunden werden.');
 end;
end;

DeddyH 17. Apr 2008 19:22

Re: Teilstring suchen
 
Hallo und Willkommen in der DP :dp:

wie sieht Dein Autorfeld denn aus? Ist das ein Record oder nur ein String? Außerdem hast Du einige Fehler im Code (i := +1 z.B.).

Die Muhkuh 17. Apr 2008 19:31

Re: Teilstring suchen
 
Um noch ein paar Fehler mehr aufzulisten:

Delphi-Quellcode:
autorfeld.Text:=suchbegriff;
Ist wohl andersrum gemeint.

Delphi-Quellcode:
gefunden:=n;
Du hast n nichts zugewiesen, was soll das bringen?

Delphi-Quellcode:
Listenfenster.Items.Strings[i];
Da steht einzeln in Zeile 10, was soll das bringen?

Delphi-Quellcode:
i:=+1;
Sollte wohl:

Delphi-Quellcode:
i := i + 1;
// oder
Inc(i);
heißen.

Hier mal ein kleiner Vorschlag:

Delphi-Quellcode:
var
  Search, Author, ItemStr: String;
  I: Integer;
  Found: Boolean;
begin
  Search := Edit1.Text;
  Found := false;

  for I := 0 to ListBox1.Count - 1 do
  begin
    ItemStr := ListBox1.Items[I];
    Author := Copy(ItemStr, 1, Pos(#45, ItemStr));
    if Pos(Search, Author) > 0 then
    begin
      ShowMessage('Autor: "' + Author + '" gefunden' + #13#10 + 'Index: ' +
        IntToStr(I));
      Found := true;
    end;
  end;

  if (not (Found)) then
    ShowMessage('Sorry, kein Autor gefunden');
end;

mkinzler 17. Apr 2008 19:32

Re: Teilstring suchen
 
Für gefunden würde sich eher eine Booleanvariable eignen.

Delphi-Quellcode:
procedure TForm1.SuchenButtonClick(Sender: Tobject);
var
    suchbegriff,zeile: string;
    i,max,separator:integer;
    gefunden: Boolean;
    sl: TStrings;
begin
  sl := TStringList.Create;
  sl.Delimiter = #45;
  suchbegriff := autorfeld.Text;
  i:=0;
  gefunden:=False;
  max:=Listenfenster.Items.Count-1;
  while (i < max) and not gefunden do
  begin
    sl.DelimitedText := Listenfenster.Items.Strings[i];
    autorfeld.text:= sl.Strings[1];
    if(autorfeld.text=suchbegriff) then gefunden:= True else i:=+1;
  end;
  if not gefunden) then
  begin
      ShowMessage('Der Autor konnte nicht gefunden werden.');
  end;
end;

dominikkv 17. Apr 2008 19:33

Re: Teilstring suchen
 
öhm... weißt du überhaupt was du da machst ?! :zwinker:
versuchs mal so:
Delphi-Quellcode:
procedure TForm1.SuchenButtonClick(Sender: Tobject);
var
  I, Index: Integer;
begin
  Index := -1;
  if Listenfenster.Items.Count > 0 then
    for I := 0 to Pred(Listenfenster.Items.Count) do
      If Pos(autorfeld.text, Listenfenster.Items[i]) > 0 then
        begin
          Index := I;
          Break;
        end;
  if Index < 0 then
    ShowMessage('Der Autor konnte nicht gefunden werden.');
end;

Die Muhkuh 17. Apr 2008 19:37

Re: Teilstring suchen
 
Das mit dem Break finde ich nicht so ideal. Was machst Du, wenn der in der Liste ein Autor mehrmals vertreten ist?

DeddyH 17. Apr 2008 19:40

Re: Teilstring suchen
 
Noch ein Vorschlag:
Delphi-Quellcode:
function SearchSubString(const s,             //gesuchter String
                         Sep: string;         //Trennstring
                         const sList: TStrings //Liste
                         ): integer;          //gefundene Position in der Liste
var found: Boolean;
    i: integer;
begin
  found := false;
  Result := -1;
  i := 0;
  while (i < sList.Count) and not found do
    begin
      if Copy(sList[i],1,Pos(Sep,sList[i]) - 1) = s then
        begin
          Result := i;
          found := true;
        end
      else
        inc(i);
    end;
end;

Die Muhkuh 17. Apr 2008 19:48

Re: Teilstring suchen
 
Du hast das gleiche Problem, wenn sich mehrere Autoren finden. Das ganze ein bisschen erweitert:

Delphi-Quellcode:
function SearchSubString(const s,             //gesuchter String
                         Sep: string;         //Trennstring
                         const sList: TStrings //Liste
                         ): String;          //Kommatext mit den gefundenen Items
var
  i, max: integer;
  ResTmp, ItemStr: String;
begin
  i := 0;
  ResTmp := '';
  max := sList.Count;
  while (i < max) do
  begin
    ItemStr := sList[I];
    ItemStr := Copy(ItemStr, 1, Pos(Sep, ItemStr));
    if Pos(s, ItemStr) > 0 then
    begin
      ResTmp := ResTmp + IntToStr(I) + ',';
    end;

    inc(i);
  end;

  Result := Copy(ResTmp, 1, Length(ResTmp) - 1);
end;

DeddyH 17. Apr 2008 19:58

Re: Teilstring suchen
 
Dann eben so:
Delphi-Quellcode:
type DynArr = array of integer;

procedure SearchSubString(const s,               //gesuchter String
                          Sep: string;           //Trennstring
                          const sList: TStrings; //Liste
                          var ResultArr: DynArr); //dynamisches Array nimmt Trefferpositionen auf
var i: integer;
begin
  SetLength(ResultArr,0);
  i := 0;
  while (i < sList.Count) do
    begin
      if Copy(sList[i],1,Pos(Sep,sList[i]) - 1) = s then
        begin
          SetLength(ResultArr,Length(ResultArr) + 1);
          ResultArr[High(ResultArr)] := i;
        end;
      inc(i);
    end;
end;
[edit] Achja:
Delphi-Quellcode:
if Pos(s, ItemStr) > 0 then
findet den Suchstring auch mittendrin, ob das so gewollt ist? :zwinker: [/edit]

Die Muhkuh 17. Apr 2008 20:04

Re: Teilstring suchen
 
Und das ganze noch ein bisschen verbessert, da bei Detlefs Lösung nur exakte Strings gefunden werden:

Delphi-Quellcode:
type TDynIntArray = array of Integer;

procedure SearchSubString(const s,            //gesuchter String
                         Sep: string;         //Trennstring
                         const sList: TStrings; //Liste
                         var ResultArr: TDynIntArray); // Trefferpositionen
var
  i, max: integer;
  ItemStr: String;
begin
  i := 0;
  max := sList.Count;
  SetLength(ResultArr, 0);
  while (i < max) do
  begin
    ItemStr := sList[I];
    ItemStr := Copy(ItemStr, 1, Pos(Sep, ItemStr));

    if Pos(s, ItemStr) > 0 then
    begin
      SetLength(ResultArr, Length(ResultArr) + 1);
      Resultarr[High(ResultArr)] := I;
    end;

    inc(i);
  end;
end;

DeddyH 17. Apr 2008 20:09

Re: Teilstring suchen
 
So, vielleicht warten mir erstmal ab, was der T.E. dazu sagt :mrgreen:

Die Muhkuh 17. Apr 2008 20:11

Re: Teilstring suchen
 
Gerade jetzt, wo es lustig ist. :cry:

:tongue:

DeddyH 17. Apr 2008 20:47

Re: Teilstring suchen
 
Na gut, einen hab ich noch:
Delphi-Quellcode:
type TDynIntArr = array of integer;
     TMySearchOption = (soIgnoreCase,  //Groß-/Kleinschreibung ignorieren
                        soSomewhere,   //Suchstring kann irgendwo enthalten sein
                        soIsBeginning); //Suchstring steht am Anfang, weitere Zeichen können folgen
     TMySearchOptions = set of TMySearchOption;

procedure SearchSubString(const s,                  //gesuchter String
                          Sep: string;              //Trennstring
                          const sList: TStrings;    //Liste
                          var ResultArr: TDynIntArr; //dynamisches Array nimmt Trefferpositionen auf
                          const Options: TMySearchOptions);
var i: integer;
    found: Boolean;
    sSearch: string;
begin
  SetLength(ResultArr,0);
  i := 0;
  while (i < sList.Count) do
    begin
      sSearch := Copy(sList[i],1,Pos(Sep,sList[i]) - 1);

      if soIgnoreCase in Options then
        begin
          if soSomewhere in Options then
            found := Pos(AnsiLowerCase(s),AnsiLowerCase(sSearch)) > 0
          else if soIsBeginning in Options then
            found := Pos(AnsiLowerCase(s),AnsiLowerCase(sSearch)) = 1
          else
            found := AnsiSameText(s,sSearch);
        end
      else if soSomewhere in Options then
        found := Pos(s,sSearch) > 0
      else if soIsBeginning in Options then
        found := Pos(s,sSearch) = 1
      else
        found := AnsiCompareStr(s,sSearch) = 0;

      if found then
        begin
          SetLength(ResultArr,Length(ResultArr) + 1);
          ResultArr[High(ResultArr)] := i;
        end;
      inc(i);
    end;
end;

Hugo Hasi 18. Apr 2008 17:59

Re: Teilstring suchen
 
:shock:
verdammt man kommt sich ja manchmal echt dämlich vor :duck: . Aber ein fettes Dank an euch... hab es sogar wirklich hinbekommen. Ihr habt da zwischendurch mal was wirklich interessantes angesprochen... das mit den mehreren Autoren. Um jetzt aber die Suche weiterlaufen zu lassen, müsste ich doch theoretisch eine ganz neuen Button mit einer ganz neuen Funktion erstellen, oder? Kann ich das denn so machen, dass ich den Index(weil wenn er was gefunden hat, wird es ja markiert) einfach um einen erhöhe und er dann wieder die "normale" Suchfunktion durchführt?
Sehr wahrscheinlich kommt jetzt wieder"Weißt du überhaupt was du da machst?" :tongue:

DeddyH 18. Apr 2008 18:11

Re: Teilstring suchen
 
Wenn Du die Funktion aus meinem letzten Posting nimmst (die ist noch nicht optimal, funktioniert aber), könntest Du das z.B. so machen:
Delphi-Quellcode:
procedure TForm5.Button1Click(Sender: TObject);
var Results: TDynIntArr;
    i: integer;
begin
  ListBox1.ClearSelection;
  SearchSubString(Edit1.Text,'#',ListBox1.Items,Results,[]);
  for i := 0 to High(Results) do
    ListBox1.Selected[Results[i]] := true;
  SetLength(Results,0);
end;

Hugo Hasi 18. Apr 2008 18:18

Re: Teilstring suchen
 
der meckert immer rum, dass TdynIntArr ein undefinierter Bezeichner ist...

DeddyH 18. Apr 2008 18:25

Re: Teilstring suchen
 
Hast Du den Code aus #13 denn auch komplett kopiert und bei Dir eingefügt (am Besten direkt unter "implementation")?

dominikkv 18. Apr 2008 18:28

Re: Teilstring suchen
 
Ok, dann will ich hier mal meine Lösung Vorstellen xD

Delphi-Quellcode:
const
  Delimiters = [#1..#47, #58..#64, #91..#96, #123..#191, #215, #216, #247, #248];
  Delimiters_0 = [#0] + Delimiters;

procedure GetWords(s: string; woerter: TStrings);
var
  p, r: pchar;
  Token: string;
begin
  woerter.Clear;
  p := pchar(s);
  repeat
    r := p;
    while not (p^ in Delimiters_0) do inc(p);
    SetString(Token, r, p - r);
    if Token <> '' then woerter.Add(Token);
    while p^ in Delimiters do inc(p);
  until p^ = #0;
end;

function Such(Txt, Pattern: string): boolean;
var
  slP: TStringlist;
  x: integer;
  pt: PChar;
  p: array of PChar;
  i: array of integer;
  b: array of boolean;
begin
  if (Txt = '') or (Pattern = '') then begin
    result := false;
    exit;
  end;
  Txt := ansiuppercase(Txt);
  Pattern := ansiuppercase(Pattern);
  slP := TStringlist.Create;
  GetWords(Pattern, slP);
  setlength(p, slP.count);
  setlength(i, slP.count);
  setlength(b, slP.count);
  for x := 0 to slP.count - 1 do begin
    p[x] := @slP[x][1];
    i[x] := length(slP[x]);
    b[x] := false;
  end;
  pt := @Txt[1];
  while pt^ <> #0 do begin
    for x := 0 to high(p) do
      if comparemem(pt, p[x], i[x]) then b[x] := true;
    inc(pt);
    result := true;
    for x := 0 to high(b) do
      result := result and b[x];
    if result then break;
  end;
  b := nil;
  i := nil;
  p := nil;
  slP.free;
end;


procedure TForm1.SuchenButtonClick(Sender: Tobject);
var
  I: Integer;
  Ergebnis: Array of Integer;
  AutorenListe: TStringList;
begin
  SetLength(Ergebnis, 0);
  AutorenListe := TStringList.Create;
  if Listenfenster.Items.Count > 0 do
    for I := 0 to Pred(Listenfenster.Items.Count) do
      if Such(Listenfenster.Items[i], Autorfeld.Text) then
        begin
          SetLength(Ergebis, Succ(Length(Ergebnis)));
          Ergebnis[high(Ergebnis)] := I;
          AutorenListe.Add(Listenfenster.Items[i]);
        end;

  if length(Ergebnis) > 0 then // gefunden?
//  if AutorenListe.Count > 0 then // alternativ
    begin
//     jetzt steht in Ergebnis der Index zu den Einträgen in Listenfenster
//     zB den ersten Index kannst du mit Ergebnis[0] abrufen
//     oder du nimmst die AutorenListe: showmessage(AutorenListe[0]);
    end;
  AutorenListe.Free;
end;
Diese Methode hat den Vorteil das sie erstens schnell ist, zweitens kannst du auch nach nach mehreren Wörtern suchen.
Beispiel: Du suchst "Friedrich Schiller"
Der Suchalgorythmus (schreibt man das so!?) würde auch "Friedrich von Schiller" oder "Schiller, Friedrich" finden.

Hugo Hasi 18. Apr 2008 18:31

Re: Teilstring suchen
 
jetzt ja :oops: aber wo genau schreib ich denn das mit dem SearchSubString hin?

DeddyH 18. Apr 2008 18:34

Re: Teilstring suchen
 
Was meinst Du jetzt?

djpaull 5. Jun 2008 16:36

Re: Teilstring suchen
 
Hallo allerseits!

Wollte zuerst einen neuen Thread aufmachen, aber es erschien mir sinnvoll hier weiter zu machen. Habe änliches Problem.
Mein Prog soll einen text nach 0 (null bzw. mehreren nullen) durchsuchen. der Hacken dabei ist - sobald er eine null (oder mehrere direkt nacheinander) findet, soll er aufhören zu suchen und die Stelle und Anzahl der gefundenen Nullen ausgeben.

Bsp.:
Text lautet : Delphi-000123-Forum
AusgabeText1 : 8
AusgabeText2 : 3

8 steht für die Stelle, 3 für Anzahl der Nullen.
Kling banal, aber ich komme irgendwie nicht weiter.

DeddyH 5. Jun 2008 16:48

Re: Teilstring suchen
 
Nur die Anzahl der direkt aufeinander folgenden Nullen?

djpaull 5. Jun 2008 16:54

Re: Teilstring suchen
 
Und die Stelle, wo man sie zum ersten mal gefunden hat. Weitere Nullen sind unwichtig.

Edit1

Ich dachte an sowas wie:
Delphi-Quellcode:
Procedure TForm1.SucheNull;
 var Text,SuchText, Test:string;
     Suchindex: Integer;
begin
  Text:=TextFeld.Text;
  Suchtext := '0';

  begin
    // Find the position of the last 0
    Suchindex := LastDelimiter(Suchtext, Text);
    //ShowMessage('The last 0 is at '+IntToStr(Suchindex));
  end;

  if Suchindex = 0 then
  Ausgabe.Text:= '';
  if Suchindex = 1 then
  Ausgabe.Text:= '0';
  if Suchindex = 2 then
  Ausgabe.Text:= '00';
end;
ist nur so Gedankenansatz...

Die Muhkuh 5. Jun 2008 17:01

Re: Teilstring suchen
 
Mit Delphi-Referenz durchsuchenPos ist das zu ermöglichen.

djpaull 5. Jun 2008 17:06

Re: Teilstring suchen
 
Ja schon. Aber ob Pos oder LastDelimiter, wie mache ich, dass er, nach dem er die ersten nullen gefunden hat, aufhört zu suchen?

EDIT1

Wenn ich ihm sage, er soll nach dem Fund aufhören, dann findet er auch nur eine einzige Null. Wenn ich sage, er soll nach den ganzen Text nach Nullen durchsuchen, dann spuckt er ALLE Nullen aus. Ich Brauche aber nur die erste Null oder die erte Null-Folge.

Die Muhkuh 5. Jun 2008 17:08

Re: Teilstring suchen
 
Delphi-Quellcode:
i := Pos('0', str);

if i > 0 then
  MachWas;
Damit findest Du einmal die erste Null, weiter wird nicht gesucht.

Mit einer While-Schleife kannst Du dann noch solange von i + 1 weiterlaufen, bis das gefundene Zeichen <> 0 ist.

DeddyH 5. Jun 2008 17:20

Re: Teilstring suchen
 
Oder vielleicht etwas in der Art:
Delphi-Quellcode:
type TStellen = record
  First,
  Count: integer;
end;

function GetPosAndCount(const s: string; const c: Char): TStellen;
var i: integer;
begin
  Result.First := 0;
  Result.Count := 0;
  for i := 1 to Length(s) do
    if s[i] = c then
      begin
        if Result.First < 1 then
          Result.First := i;
        inc(Result.Count);
      end
    else
      if Result.First > 0 then break;
end;

djpaull 5. Jun 2008 17:29

Re: Teilstring suchen
 
Sorry, bin in Records noch nicht fit.
Zitat:

function GetPosAndCount(const s: string; const c: Char): TStellen;
Was ist in diesem Fall "const s: string" und "const c: Char". s ist mein Text und c der Suchstring, oder hab ich das falsch verstanden? :oops:

Die Muhkuh 5. Jun 2008 17:32

Re: Teilstring suchen
 
s ist da, worin gesucht werden soll, c ist ein Buchstabe, nach dem gesucht werden soll.

djpaull 5. Jun 2008 17:56

Re: Teilstring suchen
 
OK. Ich rufe die Funktion jetzt so auf:
Delphi-Quellcode:
GetPosAndCount(MeinText.text,'0');
Aber wo sehe ich die Ergebnise? Ich wollte sie z.B. im EditFeld1 haben.

DeddyH 5. Jun 2008 17:59

Re: Teilstring suchen
 
Du hast den Rückgabewert ja nicht ausgewertet.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var bla: TStellen;
begin
  bla := GetPosAndCount('abcdddef','d');
  ShowMessage(Format('Position %d, Anzahl %d',[bla.First,bla.Count]));
end;

djpaull 5. Jun 2008 18:59

Re: Teilstring suchen
 
Aja! Danke! Es funzt :thumb: Ist bei mir Seltenheit. :wink:

marabu 6. Jun 2008 09:46

Re: Teilstring suchen
 
Moin,

hier noch eine kleine Detail-Studie:

Delphi-Quellcode:
function PosChars(c: Char; const s: string; var count: Integer): Integer;
begin
  Result := Pos(c, s);
  count := Result div 1;
  while (count > 0) and (count <= Length(s)) and (s[count] = c) do
    Inc(count);
  Dec(count, Result);
end;
Freundliche Grüße

p80286 6. Jun 2008 10:08

Re: Teilstring suchen
 
@Marabu

warum
Zitat:

count := Result div 1;
?

Hat
Delphi-Quellcode:
count := Result;
nicht den gleichen Effekt?

Gruß
K-H

marabu 6. Jun 2008 19:05

Re: Teilstring suchen
 
Wer von euch hat das DIV da hingeschrieben?

Wenn ich den erwische ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:28 Uhr.

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