Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fehler in einer while Schleife (https://www.delphipraxis.net/91264-fehler-einer-while-schleife.html)

moperswings 2. Mai 2007 15:53


Fehler in einer while Schleife
 
Hallo,

ich möchte eine *.html-Datei nach Bildern durchsuchen und die gefundenen Bilder sollen in einer Listbox angezeigt werden. Ich weiss aber nicht, wie ich mit einer while-Schleife eine TStringliste durchlaufen lasse. Ohne while wird mir nur das erste Bild angezeigt.
Hoffe, Ihr könnt mir helfen!
Viele Grüsse, moperswings
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
        dateiname: string;
        inhalt: TStringlist;
        pic_start: string;
        i: integer;
        temp: String;
begin
        pic_start := '<img src';
        dateiname := 'd:\image14\daten.html';
        Memo1.Lines.LoadFromFile(dateiname);
        inhalt := TStringlist.Create;
        inhalt.LoadFromFile(dateiname);

        while not EOF({inhalt läuft nicht}) do begin
          for i := 0 to inhalt.Count - 1 do
          if pos(pic_start, inhalt[i]) <> 0 then begin
          temp := inhalt[i];
          Listbox1.Items.Add(temp);
          inhalt.free;
          exit;
          end;
        end;
end;

BenjaminH 2. Mai 2007 15:56

Re: Fehler in einer while Schleife
 
Mit Delphi-Referenz durchsuchenPosEx kannst du ab einer bestimmten Stelle suchen.
Das heißt du suchst erst nach dem ersten vorkommen und dann nimmst du den Wert, den PosEx zurückliefert um ab da weiter zu suchen.

stifflersmom 2. Mai 2007 16:05

Re: Fehler in einer while Schleife
 
Zitat:

Zitat von moperswings
Hallo,

ich möchte eine *.html-Datei nach Bildern durchsuchen und die gefundenen Bilder sollen in einer Listbox angezeigt werden. Ich weiss aber nicht, wie ich mit einer while-Schleife eine TStringliste durchlaufen lasse. Ohne while wird mir nur das erste Bild angezeigt.
Hoffe, Ihr könnt mir helfen!
Viele Grüsse, moperswings
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
        dateiname: string;
        inhalt: TStringlist;
        pic_start: string;
        i: integer;
        temp: String;
begin
        pic_start := '<img src';
        dateiname := 'd:\image14\daten.html';
        Memo1.Lines.LoadFromFile(dateiname);
        inhalt := TStringlist.Create;
        inhalt.LoadFromFile(dateiname);

        while not EOF({inhalt läuft nicht}) do begin
          for i := 0 to inhalt.Count - 1 do
          if pos(pic_start, inhalt[i]) <> 0 then begin
          temp := inhalt[i];
          Listbox1.Items.Add(temp);
          inhalt.free;
          exit;
          end;
        end;
end;

'ne StringList hat kein EOF also, wieso willst Du das (mit while) nutzen?
Du solltest einfach so Deine StringLsit durchgehen:
Delphi-Quellcode:
For I:= 0 to Inhalt.Count -1 do
...
Moin

BenjaminH 2. Mai 2007 16:16

Re: Fehler in einer while Schleife
 
Ich würde das so machen, ich denke das ist das einfachste.
Delphi-Quellcode:
p:Integer;
pic_start := '<img src="';
p:=pos(pic_start, Memo1.Text);
[etc]
while p<>0 do
Begin
  Listbox1.Items.Add(substr(Memo1.Text,Copy(Memo1.Text,p+Length(pic_start),PosEx('"',Memo1.Text,p+Length(pic_start)));
  p:=posex(pic_start, Memo1.Text,p);
End;

Matze 2. Mai 2007 16:17

Re: Fehler in einer while Schleife
 
Du solltest die StringList auch nicht versuchen, in einer Schleife freizugeben, selbst wenn es EOF gäbe. Mach sowas generell so, damit die StringList auch sicher wieder freigegeben wird:

Delphi-Quellcode:
inhalt := TStringlist.Create;
try
  while (...)
  begin
    ...
  end;
finally
  FreeAndNil(inhalt);
end;

Christian Seehase 2. Mai 2007 16:59

Re: Fehler in einer while Schleife
 
Moin Benjamin,

Du solltest aber niemals TStrings.Text (z.B. bei Memo) in einer Schleife verwenden, sondern immer eine String-Variable für so etwas nehmen, da die Eigenschaft Text bei jedem Lesezugriff aus den Zeilen zusammengesetzt wird (gilt analog auch für das Schreiben).
Immer Text zu verwenden ist eine der "besten" Performancebremsen.

moperswings 4. Mai 2007 09:03

Re: Fehler in einer while Schleife
 
Hallo,

hier ist meine - nach langem Leiden - vorläufige Lösung:
Wer eine Idee hat, wie man das optimieren oder wie es ganz anders laufen könnte, dann her damit!
Ich hätte es vor allem noch gerne in einer Stringliste, damit ich mir das Memo sparen kann, was ich eigentlich für mich nur zur Kontrolle eingebaut habe, um zu sehen, ob auch alle Bilder gefunden werden.
Ich würd mich freuen!

Ich hoffe auch, hiermit eine allgemeine Lösung zu liefern, wie man einen Textteil filtern kann und so anderen auch mal helfen könnte!

Viele Grüsse, moperswings
Delphi-Quellcode:
procedure TForm1.Button14Click(Sender: TObject);
var
        i, p: integer;
        s: string;
        bild: string;
        dateiname: string;
begin
        dateiname := 'd:\image14\daten.html';
        Memo1.Lines.LoadFromFile(dateiname);

        bild := '<img';

        for i := 0 to Memo1.Lines.Count - 1 do
        begin
        if pos(bild, Memo1.Lines.Strings[i]) > 0 then begin
        s := '';

        for p := pos(bild, Memo1.Lines.Strings[i]) to
        length(Memo1.Lines.Strings[i]) do
        if memo1.Lines.Strings[i][p] <> s then
        s := s + Memo1.Lines.Strings[i][p]
        else
        break;

        while pos(s[length(s)], '/>') = 0 do
        delete(s, length(s), 1);
        ListBox1.Items.Add(s);
        end;
        end;
end;

SirThornberry 4. Mai 2007 10:15

Re: Fehler in einer while Schleife
 
das hier kann doch vereinfacht werden
Delphi-Quellcode:
while pos(s[length(s)], '/>') = 0 do
        delete(s, length(s), 1);
anstelle bei jedem durchlauf das ganze zu kürzen kannst du auch einfach eine Varialbe nehmen in der du dir die Position merkst und dann am Ende einmal nur die ganzen zeischen löschst.
Delphi-Quellcode:
var
  lPos: Integer;
begin
[...]
lPos := Length(s);
while pos(s[lPos], '/>') = 0 do
  dec(lPos);
s := copy(s, 1, lPos);
Zudem solltest du dort eine Prüfung einbauen damit nicht auf Index 0 des Strings zugegriffen wird und auch keine endlosschleife draus wird falls keines der zeichen vorkommt:
Delphi-Quellcode:
while (length(s) > 0) and (pos(s[length(s)], '/>') = 0) do
        delete(s, length(s), 1);
bzw.
Delphi-Quellcode:
var
  lPos: Integer;
begin
[...]
lPos := Length(s);
while (lPos > 0) and (pos(s[lPos], '/>') = 0) do
  dec(lPos);
s := copy(s, 1, lPos);


nächster Punkt:
Anstelle jedes mal "memo1.Lines.Strings[i]" zu verwenden solltest du das ganze auf eine zwischenvariable zuweisen denn "memo1.Lines.Strings[i]" ruft intern jedesmal SendMessage auf um den Inhalt der Zeile abzufragen, kopiert dann den Inhalt in einen String und liefert dir diesen zurück. Wenn du also eine Zwischenvariable nutzt wird nur einmal das ganze in einen Puffer geschrieben der dir zurück gegeben wird und auf diesem kannst du dann viel schneller arbeiten.


nächster Kritikpunkt ist folgender Block (mal ordentlich formatiert)
Delphi-Quellcode:
for p := pos(bild, Memo1.Lines.Strings[i]) to length(Memo1.Lines.Strings[i]) do
  if memo1.Lines.Strings[i][p] <> s then
    s := s + Memo1.Lines.Strings[i][p]
  else
    break;
durch
Delphi-Quellcode:
s := s + Memo1.Lines.Strings[i][p]
wird die Länge von s immer wieder geändert. Anfangs hat s eine Länge von 0.
- Dann eine Länge von 1 -> Speicher für 1 Zeichen wird reserviert
- Dann eine Länge von 2 -> Speicher für 2 Zeichen wird reservert, das 1 Zeichen vom Schritt davor wird in den neuen Speicher kopiert, das neue Zeichen wird an die letzte Stelle im neuen Speicher geschrieben, Speicher vom Schritt davor wird frei gegeben
- Dann eine Länge von 3 -> Speicher für 3 Zeichen wird reservert, die 2 Zeichen vom Schritt davor werden in den neuen Speicher kopiert, das neue Zeichen wird an die letzte Stelle im neuen Speicher geschrieben, Speicher vom Schritt davor wird frei gegeben
[...]
es wird also immer wieder neuer speicher reserviert und der Inhalt wird umher kopiert weil der alte reservierte Speicher für den String nicht ausreicht.
Du weißt ja aber vorher das dein String eine maximale Länge von:
Delphi-Quellcode:
length(Memo1.Lines.Strings[i]) - pos(bild, Memo1.Lines.Strings[i]) + 1
zeichen haben kann. Setzte also mit SetLength die Variable s gleich auf diese maximale größe und zähle in einer variablen mit wieviel Zeichen du bisher rein geschrieben hast. Nach der Schleife setzt du dann mit SetLength die Größe von s auf die tatsächlich benötigte Größe. Und schon fällt das ständige umherkopieren und neu reservieren von speicher weg.


nächster Punkt:
Delphi-Quellcode:
if pos(bild, Memo1.Lines.Strings[i]) > 0 then
begin
  s := '';
  for p := pos(bild, Memo1.Lines.Strings[i]) to [...]
du rufst zweimal hintereinander pos auf mit den gleichen Parametern auf. Es wird also 2 mal nach dem ersten vorkommen gesucht. Sinnvoller wäre es hier doch das ergebnis des ersten Aufrufes in einer Variable zu speichern.


Zitat:

Ich hätte es vor allem noch gerne in einer Stringliste, damit ich mir das Memo sparen kann
dann lege doch einfach eine Stringliste an :gruebel: ( StringListInstanz := TStringList.Create() )


Hab den Quelltext von dir allerdings nur überflogen. Ich hoffe also ich hab nicht irgendwelchen Quelltext falsch verstanden.

moperswings 4. Mai 2007 10:51

Re: Fehler in einer while Schleife
 
Vielen Dank Grosser Meister!

Um Dein Posting durchzuarbeiten brauche ich noch Zeit!
Mit der Stringliste wäre ich ja wieder am Anfang meines Problems, dass ich da keinen Schleifen-Durchlauf hinbekomme :-(

Vielen Dank erstmal, ich schreibe zurück, wenn ich Deinen Text durchgearbeitet und verstanden (ich bemühe mich) habe!

SirThornberry 4. Mai 2007 10:55

Re: Fehler in einer while Schleife
 
Zitat:

Zitat von moperswings
Mit der Stringliste wäre ich ja wieder am Anfang meines Problems, dass ich da keinen Schleifen-Durchlauf hinbekomme :-(

du musst doch einfach nur "Memo1.Lines." durch "deineStringliste." ersetzen.
Delphi-Quellcode:
deineStringListe := TStringList.Create();
try
//dein bisheriger Quelltext mit "deineStringListe." anstelle von "Memo1.Lines."
finally
  deineStringListe.Free;
end;

raiguen 4. Mai 2007 12:13

Re: Fehler in einer while Schleife
 
Zitat:

Zitat von moperswings
Hallo,
ich möchte eine *.html-Datei nach Bildern durchsuchen und die gefundenen Bilder ...

:gruebel: WAS genau möchtest du 'extrahieren'?
a) den kompletten ImageTag
b) den Bildnamen einscjliesslich VerzeichnisPfad
c) den Bildnamen ohne VerzeichnisPfad

zu a)
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var ts: TStrings;
    i: integer;
    StartTag, EndTag, Pos2: Integer;
    s: String;
begin
  ts := TStringList.Create;
  ts.LoadFromFile('d:\image14\daten.html');
 
  //-- nur zur Kontrolle
  MEMO1.Lines.Assign(ts);

  for i := 0 to ts.Count -1 do begin
    StartTag := Pos('<img src="', ts[i]);
    if StartTag > 0 then begin
      //--zwischenspeichern
      s := Copy(ts[i], StartTag, Length(ts[i])-StartTag);
      //--EndtagZeichen > ermitteln
      EndTag := Pos('>',s);
      ListBox1.Items.Add(Copy(s, 1, EndTag));
    end;
  end;
  ts.Free;
end;
zu b)
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var ts: TStrings;
    i: integer;
    StartTag, EndTag, Pos2: Integer;
    s: String;
begin
  ts := TStringList.Create;
  ts.LoadFromFile('d:\image14\daten.html');

  for i := 0 to ts.Count -1 do begin
    StartTag := Pos('<img src="', ts[i]);
    if StartTag > 0 then begin
      s := Copy(ts[i], StartTag+10, Length(ts[i])-StartTag);
      //--abschliessendes " ermitteln
      EndTag := Pos('"',s);
      ListBox1.Items.Add(Copy(s,1, EndTag-1));
    end;
  end;

  ts.Free;
end;
zu c)
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var ts: TStrings;
    i: integer;
    StartTag, EndTag, Pos2: Integer;
    s: String;
begin
  ts := TStringList.Create;
  ts.LoadFromFile('d:\image14\daten.html');

  for i := 0 to ts.Count -1 do begin
    StartTag := Pos('<img src="', ts[i]);
    if StartTag > 0 then begin
      s := Copy(ts[i], StartTag+10, Length(ts[i])-StartTag);
      //--abschliessendes " ermitteln
      EndTag := Pos('"',s);

      //--ab gefundender Position rückwärts suchen nach /
      //--um Bildname zu extrahieren
      Pos2 := EndTag;

      repeat
        Dec(Pos2)
      until (s[Pos2]='/') or (Pos2=0);
      ListBox1.Items.Add(Copy(s,Pos2+1, EndTag - (Pos2+1)));
    end;
  end;
 
  ts.Free;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:56 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 by Thomas Breitkreuz