Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^ (https://www.delphipraxis.net/124234-problem-mit-doppelt-verkettete-liste-zeiger-wie-%5E%5E.html)

knocko 17. Nov 2008 11:14


Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Hi Leute, ich hoffe ich bin hier im richtigen Forum.
Hoffe doch dass Zeiger zum ObjectPascal gehören. :gruebel:

Also mein Problem konnte Google nicht lösen.
Fast jeder Google-Link ist schon mit lilaner Farbe gekennzeichnet ;)
Dazu kommt noch,dass mein Desktop jetzt mit haufen Beispielen und PDFs zugemüllt ist.
Nur nix davon bringt mich wirklich weiter.

Aber nun genug Offtopic.
Mein Problem ist folgendes:
Ich hab mir einen Zeiger definiert:
Code:
type
  PMyelement = ^TMyelement;
  TMyelement = record                                
           id: integer;
           titel: string;
           Next : PMyelement;
           Prev : PMyelement;
Dann kommen die globalen Variablen
Code:
var
  anf, akt, ende : PMyelement;                            { ** anf und akt stehen für Anfang und Aktuell ** }

Bis dahin kein Problem.
Jetzt (ich hoffe ich kriegs gut erklärt) möchte ich meinen Quelltext folgdendermaßen schreiben:
Das Einschreiben von Daten funktioniert schon.
Allerdings fügt er neue Elemente immer ganz hinten an.
Sagen wir aber ich befinde mich in der Mitte der Datensätze (die ich mit Hilfe von Vorwärts/Rückwärts-Buttons erreicht habe) und klicke nun auf "Übernehmen".
Dann soll er in dem aktuellen Datensatz nur die Daten "aktualisieren" und nicht hinten erneut speichern.
Anschließend soll er mir den nächsten Datensatz einfach anzeigen lassen.

Ich weiß ja auch warum er die Daten am Ende speichert, aber ich krieg diesen Fehler gedanklich nicht ausgemerzt!
Es fehlt mir irgendwo ne If-Abfrage die überprüft, ob der Zeiger nun am Ende des Datensatzes ist (sprich "nächste Datensatz := NIL")
oder ob da noch Datensätze folgen (sprich "nächste Datensatz <> NIL")
Ich hoffe einfach mal,dass die Beschreibung ausreicht für euch. Wenn es fragen gibt immer her damit!



Hier mein Quelltext zum Eintragen von Daten:
Code:
procedure TForm1.BitBtn3Click(Sender: TObject);    // Elemente einschreiben in Liste
var h1, h2 : PMyelement;   { ** h1 und h2 sind (H)ilfsvariablen ** }
begin
  new(h1);
  h1^.id := StrToInt(Edit1.Text) +1;
  h1^.titel := Edit2.Text;
  Edit1.Text := IntToStr(h1^.id);
  h1^.Next := NIL;
  if anf = NIL then
    begin
      anf := h1;
    end
  else
    begin
       h2 := anf;
       while (h2^.Next <> NIL) do
         begin
           h2 := h2^.Next;
         end;
       h2^.Next := h1;
     end;
  akt := h1;
end;

lg knocko

Klaus01 17. Nov 2008 11:32

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Hallo,

wenn Du "nur" die Daten eines Feldes ändern willst und
aktuell der Zeiger auf das aktuelle Feld ist:


Delphi-Quellcode:
aktuell^.id:=IntToStr(edit1.Text);
aktuell^.titel :=Edit2.Text;
Die Zeiger auf das vorhergehende Element und das nachfolgende Element
werden nicht geändert.

Anders sieht es aus, wenn Du ein Element in die Liste einfügen willst.
Aber laut Deiner Beschreibung willst Du das ja nicht.

Grüße
Klaus

[edit] Rechtschreibung

taaktaak 17. Nov 2008 11:33

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Wenn du nur einen vorhandenen Datensatz editieren willst, darfst du mit new() keinen Neuen erzeugen, sondern musst den Inhalt des aktuellen Datensatzes ändern....

Oder verstehe ich dich falsch?

// edit:
Nein, offenbar richtig verstanden!
Also: Nicht new() verwenden!!

knocko 17. Nov 2008 12:21

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hm naja ich habs ja schon mal anders versucht, aber mit meiner geistigen Kompetenz ist da eher Bullsh*t rausgekommen, anstatt ein vernünftiger Quelltext ;)

Ich muss sagen, dass der jetzige Quelltext, den ich zusammengewürfelt habe eigentlich eher aus dem Internet rauskopiert ist. Dadurch ist er noch nicht wirklich auf meine Bedürfnisse zusammengeschnitten. Ich hab mich aber bemüht, den Quelltext Zeile für Zeile zu verstehen und bin soweit, dass ich weiß was bei jeder Zeile gemacht wird.

Und da komm ich zum Entschluss, dass die While Schleife evtl. durch eine If-Abfrage ersetzt werden kann.
Nur da bekomm ich meine Probleme.

Die If Abfrage hab ich mir so vorgestellt:

Code:
Button Klick
begin
  speichere daten in zeiger                                    
  if (wenn...) nächstes glied = leer/nicht vorhanden/nil dann
      mach Edit1.text := IntToStr(zeiger.id) + 1;              // Dieser Teil soll einfach nur die Felder "vorbereiten" sodass ich neue eingaben machen kann.
           Edit2.Text := ''        
  else
      Zeige mir Daten vom nächsten Listenglied in Edit1 und Edit2   // Soll einfach das nächste Glied anzeigen
end

So ungefähr soll es laufen, wenn ich auf den Button klicke.



@taaktaak
Das new() muss ich einbauen. ANsonsten kommt ein fehler.
Und wenn ich new() beim Form.Create einbaue, dann funktioniert meine Vorwärts/Rückwärts-Blätter funktio nicht mehr.

DeddyH 17. Nov 2008 12:25

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Zu verketteten Listen gibt es hier in der DP ein Tutorial. Evtl. hilft Dir das ja schonmal weiter.

Klaus01 17. Nov 2008 12:31

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Vorausgesetzt der Pointer "aktuell" zeigt auf das aktuelle Listenelement:

Delphi-Quellcode:
//Button Klick
begin
  //speichern                                    
  aktuell^.id:=StrToint(Edit1.Text);
  aktuell^.titel:=Edit2.Text;
  //if (wenn...) nächstes glied nicht leer/vorhanden/<> nil dann
  if aktuell^.next <> nil then
    begin
      aktuell:=aktuell^.next;
      //mach Edit1.text := IntToStr(zeiger.id) + 1;              // Dieser Teil soll einfach nur die  
      //Felder "vorbereiten" sodass ich neue eingaben machen kann.
      Edit1.text:=IntToStr(aktuell^.id);
      Edit2.Text:=aktuell^.titel;
    end
  else  // Listenende
    begin
           Edit2.Text := ''        
           Edit1.text:=IntToStr(aktuell^.id +1);
    end;
end;
Grüße
Klaus

knocko 17. Nov 2008 12:41

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Ja, genau so hatte ich es schonmal gehabt. ;)
Und da kommt mein Programm nicht klar.

Sieht so aus, als würde er nur das erste Glied einschreiben.

Würde es euch helfen, wenn ich das Programm online stelle?
Würde sich jemand damit beschäftigen?

Klaus01 17. Nov 2008 13:01

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
So, jetzt mal Butter bei die Fische.

Der Übernehmen Button, was soll er machen?

a) Ein neues Element in die Liste einfügen?
b) Die Daten in ein bestehendes Listenelement schreiben?

Wie fügst Du neue Elemente in die Liste ein?

Aktuallisiertst Du immer den Pointer aktuell wenn Du dich
in der Liste bewegst?

Grüße
Klaus

knocko 17. Nov 2008 13:17

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Der Button soll:

a) Entweder neues Element in die Liste einfügen und dann die Felder quasi "vorbereiten", sodass ein neues nächstes Element eingetragen werden kann
b) oder (wenn schon eins vorhanden ist) soll er das vorhandene blos überschreiben bzw. aktualisieren und automatisch zum nächsten Listenglied wandern und anzeigen

Der Fall b) würde ja eintreffen, wenn ich Rückwärts in der Liste gehe.

Das ist mein "Übernehmen" Button.
Von mir aus kannst du auch andre Variablennamen nutzen. Die Namen sind nur ausm Internet rauskopiert :(
Dazu hab ich noch deinen Quelltext genommen

Code:
procedure TForm1.BitBtn3Click(Sender: TObject);    // Elemente einschreiben in Liste
begin
  new(h1);
  h1^.id := StrToInt(Edit1.Text) +1;
  h1^.titel := Edit2.Text;
  Edit1.Text := IntToStr(h1^.id);
  h1^.Next := NIL;
  if anf = NIL then
    begin
      anf := h1;
    end
  else
    if akt^.Next <> nil then
      begin
        Edit1.Text := IntToStr(akt^.id);
        Edit2.Text := akt^.titel;
      end
    else
      begin
        Edit2.Text := '';
        Edit1.Text := IntToStr(akt^.id+1);
      end;
  akt := h1;
end;

Das ist mein Vorwärts-Button

Code:
procedure TForm1.BitBtn4Click(Sender: TObject);    // Vorwärts blättern
begin
  if akt^.Next <> NIL then                                                     { ** Wenn akt^.Next Inhalt aufweist, dann... ** }
    begin
      akt := akt^.Next;                                                        { ** ...geh bei jedem Klick auf den Vorwärts-Button ein Listenglied weiter. ** }
      Edit1.Text := IntToStr(akt^.id);                                             { ** Trägt die aktuellen ("akt") Werte, bei dem der Zeiger steht, in die Edit-Komponenten ** }
      Edit2.Text := akt^.titel;
    end
  else
    begin
      Edit1.Text := IntToStr(akt^.id+1);                                       { ** Wenn das Ende erreicht ist, werden die Felder so vorbereitet, dass man gleich ein neues Element eintragen kann ** }
      Edit2.Text := '';
    end;
end;

Der Button sorgt dafür, dass ich wieder am Anfang der Liste lande

Code:
procedure TForm1.BitBtn1Click(Sender: TObject);    // Erste Glied anzeigen lassen
begin
  akt := anf;                                                                  { ** Zeiger wird auf das erste Record gesetzt ** }
  Edit1.Text := IntToStr(akt^.id);                                             { ** Trägt die Werte vom ersten Listenglied in die Editkomponenten ein ** }
  edit2.Text := akt^.titel;
end;



Achso und PS:
Das Tutorial hab ich schon runtergeladen.
Ist eines von vielen auf meinem Desktop ;)
Wie gesagt -> Fast alle Google Links sind Lila :)

Klaus01 17. Nov 2008 18:28

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Zitat:

Zitat von knocko
Der Button soll:

a) Entweder neues Element in die Liste einfügen und dann die Felder quasi "vorbereiten", sodass ein neues nächstes Element eingetragen werden kann
b) oder (wenn schon eins vorhanden ist) soll er das vorhandene blos überschreiben bzw. aktualisieren und automatisch zum nächsten Listenglied wandern und anzeigen

Der Fall b) würde ja eintreffen, wenn ich Rückwärts in der Liste gehe.

Das ist mein "Übernehmen" Button.
Von mir aus kannst du auch andre Variablennamen nutzen. Die Namen sind nur ausm Internet rauskopiert :(
Dazu hab ich noch deinen Quelltext genommen

zu Deinem Punkt b, ein Feld ist immer dann vorhanden wenn die Liste nicht leer ist.
Delphi-Quellcode:
procedure TForm1.BitBtn3Click(Sender: TObject);    // Elemente einschreiben in Liste
begin
  new(h1);
  h1^.id := StrToInt(Edit1.Text) +1;
  h1^.titel := Edit2.Text;
  Edit1.Text := IntToStr(h1^.id);
  h1^.Next := NIL;
  if anf = NIL then
    begin
      anf := h1;
    end
  else
    if akt^.Next <> nil then
      begin
        Edit1.Text := IntToStr(akt^.id);
        Edit2.Text := akt^.titel;
      end
    else
      begin
        Edit2.Text := '';
        Edit1.Text := IntToStr(akt^.id+1);
      end;
  akt := h1;  // hier machst Du dir die Liste kaputt

end;
Wenn Du ein Feld überschreiben willst, solltest Du nur den Inhalt überschreiben,
nicht auch noch die Adresse des Feldes.

Wenn Du ein Feld hinzufügen willst, musst Du mit new() ein Feld erstellen
und dieses an die Liste anhängen.

Der Einfachheit halber würde ich das mit zwei Buttons machen wollen
einen mit Namen "hinzufügen" und einen mit Namen "überschreiben".

Auch solltest Du noch darauf achten bei Deinem Pointer das Element prev zu versorgen,
denn sonst gibt es Probleme in der Liste nach vorne zu wandern.

.. und noch ein Link zu dynamischen Datenstrukturen.

Musst Du mit Pointerlisten arbeiten, wenn nicht, kannst Du dir mal
dynamische Array oder auch die Klasse TList anschauen.

Grüße
Klaus

knocko 17. Nov 2008 20:28

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Jo danke für deine Hilfe.
Werd es bei Zeiten testen.

Bin grad noch dabei das Programm weiter auszubauen.
Wird ne Belegarbeit für die Schule, von daher hab ich leider nicht soviel Freiraum. Soll alles über 1 Button laufen.
Aber krieg das schon noch hin ;)

knocko 20. Nov 2008 11:01

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Doppelpost mit einem etwas anderen Thema aber auch mit Zeiger.



Also das Projekt hab ich jetz soweit wie es soll.
Jetzt sollen wir noch eine Suchfunktion einbauen.

Und zwar sollen wir einen Suchbegriff eingeben und anschließend soll er in einer Listbox ALLE Begriffe bzw alle Zeiger anzeigen, die mit dem Suchbegriff übereinstimmen.
Jemand ne Idee wonach man googlen kann?

"Suchfunktion Zeiger" (oder ähnlich) hat überhaupt nicht geholfen. Wundert mich ...
Kann jemand Tips geben wie ich die Sache angehen könnte???


mfg

Klaus01 20. Nov 2008 11:15

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Hallo,

Du musst Da nur die Liste von Anfang bis zum Ende durchlaufen und
prüfen ob ein Feld dem Suchbegriff entspricht.

Soll dann die Zeigeradresse ausgegeben werden?

Grüße
Klaus

knocko 20. Nov 2008 11:30

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Naja nicht die Adresse sondern die informationen die sich dort befinden..

also zum beispiel: aktuell^.titel oder so


Naja ok, thanks, so ungefähr hab ichs mir auch vorgestellt, ich hoffe ich kriegs hin...
irgendwie versteh ich diesen zeigerkrams nur zur hälfte hehe :)

naja nur noch das projekt, dann ist die sache auch vorbei :)

knocko 22. Nov 2008 14:11

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
OK, es läuft alles soweit, jetzt müssen die Daten nur noch gespeichert und geladen werden können.


für speichern hab ich jetzt folgendes geschrieben:


Code:
procedure TForm1.Speichern1Click(Sender: TObject);
begin
  assignfile(file,'c:\lala.dat');
  rewrite(filename);
  akt := anf; { das soll dafür sorgen, dass wir uns am anfang der kette befinden und er glied für glied speichert }
  while (akt^.next <> NIL) do
    begin
      { hier hab ich z.b. kein plan wie ich meine daten speichern kann }
    end;
end;
Soweit wäre der Code richtig oder?
Jeztt habi hc noch ne frage.. bei "assignfile" was muss ich für nen datentyp angeben für die variabel "File" ??
ich hab im prinzip zweit methoden gefunden...
eine wäre "file : Textfile;" oder "file : file of xyz"
das erste fällt ja flach, weil es keine textdatei is.
und beim zweiten weiß ich nicht was ichj für XYZ einschreiben muss...

DeddyH 22. Nov 2008 14:16

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Naja, file of TMyelement böte sich hier an. Das hat aber den Nachteil, dass Du die Pointer mitspeicherst, was vollkommen unnötig ist. Evtl. solltest Du den ursprünglichen Record in Nutzdaten und Pointer aufteilen.

knocko 22. Nov 2008 14:36

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
mit TMyElement hba ich auch probiert dann kommt folgendes problem:

[Fehler] Unit1.pas(81): Typ 'TMyelement' benötigt Finalization - nicht im Dateityp erlaubt


;)

und zu deinem vorschlag fällt mir nur das ein -> :gruebel: *g*
weiß nit wie ich das machen soll

DeddyH 22. Nov 2008 14:47

Re: Problem mit doppelt Verkettete Liste - Zeiger - Wie? ^^
 
Ich dachte an so etwas:
Delphi-Quellcode:
type
  TNutzdaten = record
    id: integer;
    titel: string; //besser ShortString, sonst speicherst Du nur Pointer ab
  end;

  PMyelement = ^TMyelement;
  TMyelement = record                                
    Daten: TNutzdaten;
    Next : PMyelement;
    Prev : PMyelement;
  end;
Beim Speichern nimmst Du dann nur die enthaltenen Nutzdaten und speicherst die ab.


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