Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fehlersuche bei Listen (https://www.delphipraxis.net/81980-fehlersuche-bei-listen.html)

foxyteddy 6. Dez 2006 08:19


Fehlersuche bei Listen
 
Hallo zusammen.

Habe folgendes Problem: Ich habe eine "filmothek" geschrieben, die ihre Daten in einer Textdatei speichert und auch Laden kann. Klappt alles. Nur wenn ich die Sache Ausgeben lassen will, habe ich ein Problem. Die Idee ist, dass ich es Ausgeben lassen und durch klicke auf ein OnClick der nächste Element angezeigt wird (Also der Zeiger ein Element weiter gesetzt wird). Die "showmessage " dienen nur zur überprüfung, ob der Zeiger wirklich weiter geht. Sobald ich nun die Elemente in ein Form ausgeben will (was bei der ersten ausgabe klappt!) kommt folgender Fehler:
Im Projekt HauptprogrammProjekt.exe ist eine exception der klasse EAccessViolation aufgetreten. Meldung:'Zugriffsverletzung bei Adresse 0045BAB3 im modul 'HauptprogrammProjekt.exe'. Lesen von Adresse 00000004'. Prozess wurde angehalten. Mit einzelnen Anweisungen oder Start fortsetzen.

Könnt ihr mir helfen den Fehler zu finden? Denn offenbar funktioniert es ja, den nächsten Datensatz anzuzeigen (über showmessage) aber nicht in das Formular zu geben.

Anbei Quelltext.

KOPF, TEMP sind Global!

Delphi-Quellcode:
PROCEDURE ausgabeListe(L:Listenzeiger);
BEGIN
  BEGIN
    showmessage(l^.genre);
    ausgabeformular.titelaus.Items.add(l^.Titel);
    ausgabeformular.genreaus.Items.add(l^.genre);
    ausgabeformular.jahraus.Items.add(l^.jahr);
    ausgabeformular.regiseuraus.Items.add(l^.Regisseur);
    ausgabeformular.schauspieleraus.Items.add(l^.schauspieler);
    IF (hilf AND (l<>NIL)) THEN
        BEGIN
         l:=l^.Next;
         ausgabeListe(l);   f
         hilf:=false;
        END
      ELSE l:=NIL;
  END;
END;
Delphi-Quellcode:
procedure TAusgabeformular.WeiterClick(Sender: TObject);
begin
  titelaus.Clear;
  genreaus.Clear;
  jahraus.clear;
  regiseuraus.clear;
  schauspieleraus.clear;
//WHILE Temp<>NIL DO BEGIN
  hilf:=TRUE;
//  temp:=temp^.Next;
 // showmessage(temp^.titel);
  ausgabeliste(temp);
  end;
//end;
end.
Ich hatte auch die Idee es in dem letzten "weiter click" schon weiterzusetzten (Auskommentiert Temp:=temp^.next)

Vielen Dank für eure Hilfe!

Maja Jessica 6. Dez 2006 08:41

Re: Fehlersuche bei Listen
 
Moin,

bin noch nicht ganz wach ..., wie ist denn Temp definiert/deklariert?
In der Procedure ausgabeListe rufst du rekursiv ausgabeListe auf ! ?
Ist so gewollt?

Ich würde zwei Proceduren schreiben, eine zum "Zeigerbewegen" und eine zur Anzeige/Ausgabe.
Kann oft übersichtlicher wirken ;-)

MJ

Klaus01 6. Dez 2006 08:48

Re: Fehlersuche bei Listen
 
Delphi-Quellcode:
   
IF (hilf AND (l<>NIL)) THEN
  BEGIN
    l:=l^.Next;
    ausgabeListe(l);   f
    hilf:=false;       // dies hier wird erst dann aufgerufen wenn der Listenzeiger auf NIl steht
  END

Warum rufst Du ausgabeListe rekursiv auf, wenn Du immer nur das
nächste Element angezeigt bekommen willst.

Mach Dir doch eine Prozedur AusgabeElement(pointer) der du den Zeiger übergibst.

Das "weiterschalten" zum nächsten Element kannst Du dann im Weiterclick ausführen.

Grüße
Klaus

Tastaturkürzel 6. Dez 2006 15:29

Re: Fehlersuche bei Listen
 
Hatte mich unter nem Freund einglockt...also das da oben ist mein Problem ;)

Zunächst JA es war gewollt dies Rekursiv aufzurfen.
Und TEMP ist im Hauptprogramm (nahezu zu beginn) deklariert als TEMP:=KOPF. Damit wollte ich verhindern, dass ich meinen Kopf klaue und dadurch meine ganze Liste verschwindet...

Der andere Vorschlag habe ich ja in dem Auskommentierten Teil verwirklicht. Habe es da ausprobiert, wenn ich nicht rekursiv mache sondern NUR beim klicken auf WEITER der zeiger.next genommen wird. Aber das sind beides Feinheiten.


Also das es gibt auch den selben Fehler wenn ich das ganze so gestalte:

Delphi-Quellcode:
PROCEDURE ausgabeListe(L:Listenzeiger);
BEGIN
  BEGIN
    showmessage(l^.genre);
    ausgabeformular.titelaus.Items.add(l^.Titel);
    ausgabeformular.genreaus.Items.add(l^.genre);
    ausgabeformular.jahraus.Items.add(l^.jahr);
    ausgabeformular.regiseuraus.Items.add(l^.Regisseur);
    ausgabeformular.schauspieleraus.Items.add(l^.schauspieler);
  END;
END;
und

Delphi-Quellcode:
procedure TAusgabeformular.WeiterClick(Sender: TObject);
begin
  titelaus.Clear;
  genreaus.Clear;
  jahraus.clear;
  regiseuraus.clear;
  schauspieleraus.clear;
  temp:=temp^.Next;
  ausgabeliste(temp);
  end;
end.
Mein Problem ist der EAccessViolation Fehler. Und dieser tritt leider bei beiden auf... :(

shmia 6. Dez 2006 15:37

Re: Fehlersuche bei Listen
 
Ist das eine Hausaufgabe für Pascal?
Deine Vorgehensweise ist veraltet und stammt aus der Zeit als man verkettete Listen selbst programmiert hat und Objektorientierung noch ein Fremdwort war.
Heutzutage verwendet man einfach TList oder TObjectList und vermeidet man Zeiger wann immer möglich.

Klaus01 6. Dez 2006 15:37

Re: Fehlersuche bei Listen
 
Produzierst Du auch so noch den Fehler?

Grüße
Klaus

Delphi-Quellcode:
procedure TAusgabeformular.WeiterClick(Sender: TObject);
begin
  titelaus.Clear;
  genreaus.Clear;
  jahraus.clear;
  regiseuraus.clear;
  schauspieleraus.clear;
  if temp <> nil then
    begin
      temp:=temp^.Next;  
      ausgabeliste(temp);
    end;
  end;
end.

Tastaturkürzel 6. Dez 2006 15:58

Re: Fehlersuche bei Listen
 
Vielen Dank Klaus! Der Fehler kommt nicht mehr (soweit ich das bis jetzt testen konnte...) Leider funktioniert es immer noch nicht wieder wie vorher (weil ich zu meine schande gestehen muss, dass ich es bereits hinbekommen hatte, dann die suchfunktion implementiert hab und danach gings nicht mehr ;) )

Achso und...Leider ist es ein Schulprojekt...und unser lehrer besteht auf die veraltete vorgehensweise...Delphi 2005 oder 2006 würde auch die Fehlersuche sowei ich weiß deutlich vereinfachen ;)

Gruß

Tasta

Tastaturkürzel 6. Dez 2006 16:00

Re: Fehlersuche bei Listen
 
Schade...leider taucht der Fehler doch noch immer auf...immer noch AccessViolation...wenn es hilft: Der gleiche Fehler kommt wenn ich etwas versuche auszugeben, die Liste aber leer ist!

Klaus01 6. Dez 2006 16:05

Re: Fehlersuche bei Listen
 
Initialisierst Du die Pointer.

Ist die Liste leer ist temp dann nil?
Wird bei dem ersten Listenelement ^.next auf nil gesetzt?
Beim zweiten Listenelement der ^.next des ersten Elementes auf
die Adresse des zweiten Elemetes gesetzt und der ^.next des zweiten Elementes
auf nil geseztz?

Grüße
Klaus

Tastaturkürzel 6. Dez 2006 16:19

Re: Fehlersuche bei Listen
 
Also eigentlich kann es daran nicht liegen, da ich den "inhalt" der liste durch "laden" aus einer textdatei bekomme und definitiv weiß das mindestens 4 elemente in der textdatei stehen. Habe die Datei folgendermaßen abgeändert und nun funktioniert es für ein weiteres Element:
Delphi-Quellcode:
procedure TAusgabeformular.WeiterClick(Sender: TObject);
begin
  titelaus.Clear;
  genreaus.Clear;
  jahraus.clear;
  regiseuraus.clear;
  schauspieleraus.clear;
if temp.next<> nil then
    begin
      temp:=temp^.Next;  
      ausgabeliste(temp);
    end;
  end;
end.
Delphi-Quellcode:
PROCEDURE ausgabeListe(L:Listenzeiger);
BEGIN
    ausgabeformular.titelaus.Items.add(l^.Titel);
    ausgabeformular.genreaus.Items.add(l^.genre);
    ausgabeformular.jahraus.Items.add(l^.jahr);
    ausgabeformular.regiseuraus.Items.add(l^.Regisseur);
    ausgabeformular.schauspieleraus.Items.add(l^.schauspieler);
END;
Wenn ich nun nicht if temp.next<>NiL mache, sagt er mir beim dritten klick auf WEITER den bekannten Fehler und markiert die Zeile "ausgabeformular.titelaus.Items.add(l^.titel). Bei temp.next<>NIL macht er zwar auch nur 2x weiter (es wird nur zweimal was ausgegeben) und danach passiert gar nichts mehr (obwohl noch was in der liste sein sollte) aber wenigstens stürtzt das Programm nicht ab.

Gruß

Tasta

Muetze1 6. Dez 2006 16:51

Re: Fehlersuche bei Listen
 
Kannst du dir sicher sein, dass AusgabeListe() niemals einen NIL Zeiger bekommt? Also wenn z.B. die Liste leer ist? Weil wenn dies nicht 100%ig gewährleistet ist, dann folgendes:

Delphi-Quellcode:
PROCEDURE ausgabeListe(L:Listenzeiger);
BEGIN
  If l <> Nil Then
  Begin
    ausgabeformular.titelaus.Items.add(l^.Titel);
    ausgabeformular.genreaus.Items.add(l^.genre);
    ausgabeformular.jahraus.Items.add(l^.jahr);
    ausgabeformular.regiseuraus.Items.add(l^.Regisseur);
    ausgabeformular.schauspieleraus.Items.add(l^.schauspieler);
  End;
END;
Weil sonst l^.Titel schon eine AV schmeissen würde.

Klaus01 6. Dez 2006 18:30

Re: Fehlersuche bei Listen
 
Zeige uns doch einmal die Einleseroutine, bitte.

Grüße
Klaus

Tastaturkürzel 6. Dez 2006 19:32

Re: Fehlersuche bei Listen
 
Zwischendurch schonmal ein großes DANKE für eure Hilfe;)
hier kommt der Code:

Delphi-Quellcode:
PROCEDURE listeLaden(L:Listenzeiger);
var a,b,c,d,e:STRING;
    k,anz:INTEGER;
begin
  assignfile(test,'test.txt');
  reset(test);
  anz:=filesize(test);
FOR k:=0 TO (ANZ) DO
    BEGIN
      readln(test,a);
      readln(test,b);
      readln(test,c);
      readln(test,d);
      readln(test,e);
      FuegeHintenAn(a,b,c,d,e,l);
    END;
  closefile(test);
  kopf:=l;

  {ausgabeformular.TitelAUS.Items.Add(a);
  ausgabeformular.GenreAUS.Items.Add(b);
  ausgabeformular.JahrAUS.Items.Add(c);
  ausgabeformular.RegiseurAUS.Items.Add(d);
  ausgabeformular.SchauspielerAUS.Items.Add(e);}
end;
da fuegehintean benutzt wird, auch diese:
Delphi-Quellcode:
PROCEDURE FuegeHintenAn (Titel,Genre,Regisseur,Jahr,Schauspieler:STRING; VAR L : ListenZeiger);
VAR p,lauf : ListenZeiger;
BEGIN
     NEW(p);
     p^.Titel:=Titel;
     p^.Genre:=Genre;
     p^.Regisseur:=Regisseur;
     p^.Jahr:=Jahr;
     p^.Schauspieler:=Schauspieler;
     p^.Next:=NIL;
     IF IstListeLeer(L) THEN L:=p
     ELSE
     BEGIN
          lauf:=L;
          WHILE lauf^.Next<>NIl DO lauf:=lauf^.Next;
          lauf^.Next:=p
     END
END;

Klaus01 6. Dez 2006 21:17

Re: Fehlersuche bei Listen
 
Delphi-Quellcode:
PROCEDURE FuegeHintenAn (Titel,Genre,Regisseur,Jahr,Schauspieler:STRING; VAR kopf,L : ListenZeiger);
VAR
  p : ListenZeiger;
BEGIN
  NEW(p);
  p^.Titel:=Titel;
  p^.Genre:=Genre;
  p^.Regisseur:=Regisseur;
  p^.Jahr:=Jahr;
  p^.Schauspieler:=Schauspieler;
  p^.Next:=NIL;

  IF Not IstListeLeer(L) THEN
    L^.next:=p;   // Vorgängerelement^.next bekommt die Adresse des neuen Listenelementes
  else
    kopf:=p;      // erstes Element in der Liste

  L:=p; // Listenzeiger zeigt auf das neue Listenelement

END;
Delphi-Quellcode:
PROCEDURE listeLaden(L:Listenzeiger);
var a,b,c,d,e:STRING;
    k,anz:INTEGER;
begin
  assignfile(test,'test.txt');
  reset(test);
  anz:=filesize(test);
FOR k:=0 TO (ANZ) DO
    BEGIN
      readln(test,a);
      readln(test,b);
      readln(test,c);
      readln(test,d);
      readln(test,e);
      FuegeHintenAn(a,b,c,d,e,kopf,l);
    END;
  closefile(test);
  // kopf:=l; das ist falsch, weil Du da den Kopf immer auf das letzte Element zeigen läßt
               // der Kopf sollte auf das erste Element zeigen

  {ausgabeformular.TitelAUS.Items.Add(a);
  ausgabeformular.GenreAUS.Items.Add(b);
  ausgabeformular.JahrAUS.Items.Add(c);
  ausgabeformular.RegiseurAUS.Items.Add(d);
  ausgabeformular.SchauspielerAUS.Items.Add(e);}
end;
Habe etwas an Deinem Code geändert in der Hoffnung das es nun besser läuft.

kopf -> erstesElement, erstesElement^.next -> zweitesElement,zweitesElement^.next -> nil ; nil = Listenende

Grüße
Klaus

Tastaturkürzel 6. Dez 2006 21:54

Re: Fehlersuche bei Listen
 
Also der Fehler ist mitlerweile verschwunden...aber das war er ja eben auch bereits. Ein letzten Versuch mach ich noch, danach danke ich euch und lasse es auf sich beruhen denke ich.
Also meine Textdatei beinhaltet ca. 18 einträge. Wenn ich das ganze mir nun im Programm über die nun bekannte Ausgabe ausgeben lasse, bekomme ich 7 einträge richtig (glaube ich^^) angezeigt. Die 8.Ausgabe ist leer und danach passiert um genau zu sein NIX. Ne idee?

Meniskusschaden 6. Dez 2006 22:37

Re: Fehlersuche bei Listen
 
Zitat:

Zitat von Tastaturkürzel
Delphi-Quellcode:
anz:=filesize(test);
FOR k:=0 TO (ANZ) DO

Liegt der Fehler vielleicht hier? Filesize liefert m.E. doch
die Dateigröße und nicht die Anzahl der Textzeilen.

Klaus01 7. Dez 2006 09:01

Re: Fehlersuche bei Listen
 
Zitat:

Zitat von Tastaturkürzel
Also der Fehler ist mitlerweile verschwunden...aber das war er ja eben auch bereits. Ein letzten Versuch mach ich noch, danach danke ich euch und lasse es auf sich beruhen denke ich.
Also meine Textdatei beinhaltet ca. 18 einträge. Wenn ich das ganze mir nun im Programm über die nun bekannte Ausgabe ausgeben lasse, bekomme ich 7 einträge richtig (glaube ich^^) angezeigt. Die 8.Ausgabe ist leer und danach passiert um genau zu sein NIX. Ne idee?

Deine Datei hat 18 Zeilen, pro Listenelement ließt Du 5 Zeilen ein
Delphi-Quellcode:
FOR k:=0 TO (ANZ) DO
    BEGIN
      readln(test,a);
      readln(test,b);
      readln(test,c);
      readln(test,d);
      readln(test,e);
      FuegeHintenAn(a,b,c,d,e,kopf,l);
    END;
Macht also 3 Listenelemente. Und einen Lesefehler weil Du über das Dateiende hinausließt.
Mußt Du das mit TextDateien machen, es würde meines Erachtens einfacher
mit Records zu arbeiten, ein Listenelement = 1 Datensatz(Record).

Edit1: Aus der Delphi Hilfe: Note: FileSize can't be used on a text file.
Da hat Meniskusschaden wohl einen guten Ansatz geliefert.

Grüße
Klaus

Tastaturkürzel 7. Dez 2006 13:43

Re: Fehlersuche bei Listen
 
Also es waren schon 18 elemente a 5 strings. Denke aber das Hauptproblem liegt in der geschichte mit filesize. Nur wenn ich jetzt auf RECORDS umstellen will, würde ich doch alles abändern müssen (vor allem speichern und laden?!?) oder irre ich mich?

Klaus01 7. Dez 2006 13:53

Re: Fehlersuche bei Listen
 
ein wenig umstellen, schon.

Aber du brauchst dann halt nur einmal einen Datensatz einlesen umd alle 5 Strings zu lesen.
Der Record bindet halt alle Informationen eines Datensatzes zu einem Päckchen zusammen.

Oder Du liest die Daten mit

Delphi-Quellcode:
Zeile:=0;
while not eof(DeineDatei) do
  begin
    inc(zeile);
    ReadLn(DeineDatei,Daten);
    Case Zeile of
      1: a := daten;
      2: b := daten;
      3: c := daten;
      4: d := daten
      5: begin
            e:= daten;
            Zeile := 0;
          end;
    end;
  end;
ein.

Grüße
Klaus

Tastaturkürzel 7. Dez 2006 17:13

Re: Fehlersuche bei Listen
 
Leider verstehe ich deinen letzten Quellcode nicht so ganz...?!? Was muss ich bei "daten" einsetzen

Meniskusschaden 7. Dez 2006 18:01

Re: Fehlersuche bei Listen
 
Zitat:

Zitat von Tastaturkürzel
Leider verstehe ich deinen letzten Quellcode nicht so ganz...?!? Was muss ich bei "daten" einsetzen

Du musst gar nichts für "Daten" einsetzen. "Daten" ist der Name der Variablen, in die mit "readln" eingelesen wird. Sie wird hier als Eingabepuffer genutzt, dessen Inhalt dann abwechselnd in die Variablen a, b, c, ... übertragen wird. Nach der Übertragung in die Variable "e" kannst Du jeweils Deine Einfügeoperation durchführen.

Tastaturkürzel 7. Dez 2006 22:07

Re: Fehlersuche bei Listen
 
Also habe es jetzt ein wenig anders gemacht und...selbst hinbekommen (ist glaub ich für den Lerneffekt eh besser;) )

Aus jeden Fall vielen Dank euch allen für eure gute Hilfe (vor allem Klaus;) und auch für die Gedult.

Gruß

Tasta!


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:35 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