Delphi-PRAXiS
Seite 1 von 2  1 2      

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


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:04 Uhr.
Seite 1 von 2  1 2      

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