Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Pointer of Array of Pointer neues Prinzip (https://www.delphipraxis.net/164992-pointer-array-pointer-neues-prinzip.html)

Marcel2906 9. Dez 2011 08:36

Delphi-Version: 2010

Pointer of Array of Pointer neues Prinzip
 
Liste der Anhänge anzeigen (Anzahl: 1)
Nachdem ich mein Programm fertig habe, gab es eine neue Aufgabe:
Nun soll der Record Vorgänger, Wert und Nachfolger enthalten.
Ich füge mal ein jpg ein, dass ich bekommen habe zur Hilfe.

Nun wollte ich erstmal anfangen das eingeben zu Programmieren.
Also die erste Eingabe ist der start record und zeigt auf den 2, der auf den 3 usw.

Also ich hab mir das so gedacht, stimmt das? :

Delphi-Quellcode:
Type
   PEintrag = ^TEintrag;
   TEintrag = Record
      Vorgaenger: PEintrag;
      Wert: integer;
      Nachfolger: PEintrag;
   End;

Type
   TListe = Array Of PEintrag;
   PListe = ^TListe;

Type
   TForm1 = Class(TForm)
      LBOutNumber: TListBox;
      EdGetNumber: TEdit;
      BtBeenden: TButton;
      BtSort: TButton;
      BtHinzufuegen: TButton;
      Procedure FormCreate(Sender: TObject);
      Procedure FormDestroy(Sender: TObject);
   private
      Liste: PListe;
      Eintrag: PEintrag;
      Procedure Input;
      ...
   End;

..

Procedure TForm1.FormCreate(Sender: TObject);
Begin
   Liste := Nil;
   New(Liste);
End;

Procedure TForm1.FormDestroy(Sender: TObject);
Var
   i: integer;
Begin
   For i := Low(Liste^) To High(Liste^) Do
      Dispose(Liste^[i]);
   Dispose(Liste);
End;

Procedure TForm1.Input;
Var
   x, i: integer;
Begin
   // Init mit nichts
   Eintrag := Nil;
   new(Eintrag);
   //neuen Eintrag in Array eintragen
   Eintrag^.Wert := StrToInt(EdGetNumber.Text);
   //Array um 1 erweitern
   SetLength(Liste^, Length(Liste^) + 1);
   //Zahl ans Ende des Arrays eintragen
   x := high(Liste^);
   Liste^[x] := Eintrag;
   //Erste Eintrag hat den Vorgänger Nil
   Liste^[low(Liste^)].Vorgaenger := Nil;
   Liste^[low(Liste^)].Nachfolger := Liste^[(low(Liste^)+1)];
   //Vorgänger und Nachfolger der Einträge festlegen
   For i := (low(Liste^) + 1) To (high(Liste^) - 1) Do Begin
      Liste^[i].Vorgaenger := Liste^[i - 1];
      Liste^[i].Nachfolger := Liste^[i + 1];
   End;
   //Letzte Eintrag hat den NAchfolger Nil
   Liste^[high(Liste^)].Vorgaenger := Liste^[(high(Liste^)-1)];
   Liste^[high(Liste^)].Nachfolger := Nil;
End;

DeddyH 9. Dez 2011 08:48

AW: Pointer of Array of Pointer neues Prinzip
 
Das riecht stark nach doppelt verketteter Liste, dazu gibt es IIRC sogar ein Tutorial hier in der DP.

[edit] Japp, gefunden [/edit]

Marcel2906 9. Dez 2011 08:55

AW: Pointer of Array of Pointer neues Prinzip
 
dann werde ich da mal rein schauen und mich schlau machen :-P

Marcel2906 9. Dez 2011 09:41

AW: Pointer of Array of Pointer neues Prinzip
 
So, nun habe ich mich schlau gemacht, bekomme aber beim schließen meines Programme eine Fehlermeldung "Zugriffsverletzung"..wo liegt mein Fehler:

Delphi-Quellcode:

Type
   PEintrag = ^TEintrag;
   TEintrag = Record
      Vorgaenger: PEintrag;
      Wert: integer;
      Nachfolger: PEintrag;
   End;

Type
   TListe = Array Of PEintrag;
   PListe = ^TListe;

Type
   TForm1 = Class(TForm)
      LBOutNumber: TListBox;
      EdGetNumber: TEdit;
      BtBeenden: TButton;
      BtSort: TButton;
      BtHinzufuegen: TButton;

   private
      Liste: PListe;
      Eintrag: PEintrag;
      Procedure AddElement(Wert: integer);
      Procedure FreeKette;
   End;

Var
   Form1: TForm;
   First: PEintrag; //Anfang der Kette als globale Variable

Implementation
{$R *.dfm}

Procedure TForm1.FormCreate(Sender: TObject);
Begin
   Liste := Nil;
   New(Liste);
End;

Procedure TForm1.FormDestroy(Sender: TObject);
Var
   i: integer;
Begin
   For i := Low(Liste^) To High(Liste^) Do
      Dispose(Liste^[i]);
   Dispose(Liste);
   FreeKette;
End;

Procedure TForm1.BtHinzufuegenClick(Sender: TObject);
Begin
   Try
      AddElement(StrtoInt(EdGetNumber.Text));
      EDGetNumber.Clear;
   Except
      ShowMessage('Nur Zahlen bitte');
      EDGetNumber.Clear;
   End;
End;

Procedure TForm1.AddElement(Wert: integer);
Var
   hlp, hlp2: PEintrag;
Begin
   //Anfang vorhanden ?
   If (FIRST = Nil) Then Begin
      New(First);
      First^.Vorgaenger := Nil; //Der Anfang der Kette hat keinen Vorgänger;
      First^.Nachfolger := Nil; //Der Nachfolger ist auch erstmal nicht vorhanden.
      hlp2 := First;
   End Else Begin
      hlp := First;
      While (hlp^.Nachfolger <> Nil) Do
         hlp := hlp^.Nachfolger;
      new(hlp^.Nachfolger);
      hlp2 := hlp^.Nachfolger;
      hlp2^.Vorgaenger := hlp;
   End;
   hlp^.Wert := Wert;
End;

Procedure tForm1.FreeKette;
Var
   wrk: PEintrag;
Begin
   wrk := First^.Nachfolger;
   While (wrk <> Nil) Do Begin
      Dispose(first);
      first := wrk;
      wrk := wrk^.Nachfolger;
   End;
   Dispose(first);
End;
End.

DeddyH 9. Dez 2011 09:49

AW: Pointer of Array of Pointer neues Prinzip
 
In welcher Zeile denn?

Marcel2906 9. Dez 2011 09:56

AW: Pointer of Array of Pointer neues Prinzip
 
in keiner Zeile..Programm startet normal. Wenn ich dann Zahlen einfüge und mein TForm1 schließe, bekomme ich den Fehler angezeigt

DeddyH 9. Dez 2011 09:57

AW: Pointer of Array of Pointer neues Prinzip
 
Dann stepp doch einmal durch und schau, in welcher Zeile der Fehler auftritt. Übrigens: wozu ist eigentlich das Array gut, das wird doch gar nicht benutzt?

Marcel2906 9. Dez 2011 10:04

AW: Pointer of Array of Pointer neues Prinzip
 
wie gehe ich denn einzeln da durch, habs mit f7 gemacht. und bekomme den fehler erst ganz am ende, wenn das programm schon beendet ist.

Zitat:

Übrigens: wozu ist eigentlich das Array gut, das wird doch gar nicht benutzt?
Später möchte ich die Kette sortieren. Glaube dann brauch ich das array, oder nicht?? ^^

Zitat:

Erste Gelegenheit für Exception bei $7C812AFB. Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 004ADCFF in Modul 'Pointer.exe'. Lesen von Adresse 00000010'. Prozess Pointer.exe (3264)

Bummi 9. Dez 2011 10:08

AW: Pointer of Array of Pointer neues Prinzip
 
Vielleicht ist der Aufruf von FreeKette im Destruktor nach der Freigabe der Liste keine gute Idee

Marcel2906 9. Dez 2011 10:15

AW: Pointer of Array of Pointer neues Prinzip
 
auch wenn ich freeKette auskommentiere kommt der fehler

DeddyH 9. Dez 2011 10:22

AW: Pointer of Array of Pointer neues Prinzip
 
Die Liste wird ja nicht benutzt, daran liegt es nicht. Ich habe den Code jetzt mal hier unter XE eingefügt und kompiliert, da kommen einige Warnungen und Hinweise, insbesondere in AddElement.

Marcel2906 9. Dez 2011 10:32

AW: Pointer of Array of Pointer neues Prinzip
 
Ahh, habs...also hoffe das ist so richtig..habe new(hlp) hinzugefüht

DeddyH 9. Dez 2011 10:36

AW: Pointer of Array of Pointer neues Prinzip
 
Ich habe AddElement mal umgeschrieben:
Delphi-Quellcode:
Procedure TForm1.AddElement(Wert: integer);
Var
  hlp, neu: PEintrag;
Begin
  // Anfang vorhanden ?
  If (First = Nil) Then
    Begin
      New(First);
      First^.Vorgaenger := Nil; // Der Anfang der Kette hat keinen Vorgänger;
      First^.Nachfolger := Nil; // Der Nachfolger ist auch erstmal nicht vorhanden.
      neu := First;
    End
  Else
    Begin
      hlp := First;
      While (hlp^.Nachfolger <> Nil) Do
        hlp := hlp^.Nachfolger;
      New(neu);
      neu^.Vorgaenger := hlp;
      neu^.Nachfolger := nil;
      hlp^.Nachfolger := neu;
    End;
  neu^.Wert := Wert;
End;

Bummi 9. Dez 2011 10:38

AW: Pointer of Array of Pointer neues Prinzip
 
Delphi-Quellcode:
Procedure TForm1.AddElement(Wert: integer);
Var
   hlp, hlp2: PEintrag;
Begin
   //Anfang vorhanden ?
   If (FIRST = Nil) Then Begin
      New(First);
      First^.Vorgaenger := Nil; //Der Anfang der Kette hat keinen Vorgänger;
      First^.Nachfolger := Nil; //Der Nachfolger ist auch erstmal nicht vorhanden.
      hlp2 := First;
     
   End Else Begin
      hlp := First;
      While (hlp^.Nachfolger <> Nil) Do
         hlp := hlp^.Nachfolger;
      new(hlp^.Nachfolger);
      hlp2 := hlp^.Nachfolger;
      hlp2^.Vorgaenger := hlp;
   End;
   hlp2^.Wert := Wert;
End;

DeddyH 9. Dez 2011 10:42

AW: Pointer of Array of Pointer neues Prinzip
 
Zu spät :tongue:

Bummi 9. Dez 2011 10:45

AW: Pointer of Array of Pointer neues Prinzip
 
wo ist die rote Box hingekommen .....

Marcel2906 9. Dez 2011 10:48

AW: Pointer of Array of Pointer neues Prinzip
 
danke :))
kann man das ergebnis leicht in eine TListBox eintragen.
Sodass er einfach von vorne nach hinten durchgeht und die Werte einträgt?

DeddyH 9. Dez 2011 10:49

AW: Pointer of Array of Pointer neues Prinzip
 
Ja klar.

[edit] Bei doppelt verketteten Listen macht es auch Sinn, neben First ein Last zu haben, das auf dem letzten Element steht, dann kann man die Liste sowohl von vorn als auch von hinten durchlaufen ;) [/edit]

Marcel2906 9. Dez 2011 11:06

AW: Pointer of Array of Pointer neues Prinzip
 
Wie kann ich denn sagen er soll alles ausgeben bis er zum letzten kommt.
Ich habs so probiert, er gibt mir dann die 10 ersten aus, leider zeigt er vorher wieder eine Fehlermeldung...glaube ich hab das mit dem Pointer noch nicht ganz verstanden.

Delphi-Quellcode:
Procedure TForm1.OutList;
Var
   x: integer;
   Next: pEintrag;
Begin
   new(Next);
   LBOutNumber.Items.Strings[0] := IntToStr(first.Wert);
   Next := first.Nachfolger;
   For x := 1 To 10 Do Begin
      LBOutNumber.Items.Strings[x] := IntToStr(Next.Wert);
      Next := Next.Nachfolger;
   End;
End;

Bummi 9. Dez 2011 11:19

AW: Pointer of Array of Pointer neues Prinzip
 
Delphi-Quellcode:
Procedure TForm1.OutList;
Var
   x: integer;
   Next: pEintrag;
Begin
   next := First;
   LBOutNumber.Items.Clear;
   while Assigned(next) do
      begin
        LBOutNumber.Items.Add(IntToStr(next.Wert));
        next := next.Nachfolger;
      end;
End;

Marcel2906 9. Dez 2011 11:58

AW: Pointer of Array of Pointer neues Prinzip
 
danke :))

DeddyH 9. Dez 2011 12:06

AW: Pointer of Array of Pointer neues Prinzip
 
Du musst Dich einfach von dem Gedanken lösen, dass Du auf eine verkettete Liste irgendwie indiziert zugreifen könntest :zwinker:

Marcel2906 9. Dez 2011 12:57

AW: Pointer of Array of Pointer neues Prinzip
 
Zitat:

Zitat von DeddyH (Beitrag 1140510)
[edit] Bei doppelt verketteten Listen macht es auch Sinn, neben First ein Last zu haben, das auf dem letzten Element steht, dann kann man die Liste sowohl von vorn als auch von hinten durchlaufen ;) [/edit]

Das habe ich jetzt mal versucht. Aber weiß nicht wie ich das machen soll. Das neu hinzugefügte ist ja quasi immer das letzte...

DeddyH 9. Dez 2011 13:13

AW: Pointer of Array of Pointer neues Prinzip
 
Zitat:

Zitat von Marcel2906 (Beitrag 1140539)
Das neu hinzugefügte ist ja quasi immer das letzte...

Ja eben. Willst Du nun ein neues Element hinzufügen, musst Du nicht mehr von vorn bis hinten die ganze Liste durchgehen, sondern springst gleich zu Last, erstellst das neue Element, weist es Last als Nachfolger zu und machst es dann zum neuen Last.

Marcel2906 9. Dez 2011 13:27

AW: Pointer of Array of Pointer neues Prinzip
 
also so ?! :

Delphi-Quellcode:
Procedure TForm1.AddElement(Wert: integer);
Var
   hlp: PEintrag;
Begin
   // Anfang vorhanden ?
   If (First = Nil) Then Begin
      New(First);
      First^.Vorgaenger := Nil; // Der Anfang der Kette hat keinen Vorgänger;
      First^.Nachfolger := Nil; // Der Nachfolger ist auch erstmal nicht vorhanden.
      last := First;
   End Else Begin
      hlp := First;
      While (hlp^.Nachfolger <> Nil) Do
         hlp := hlp^.Nachfolger;
      New(last);
      last^.Vorgaenger := hlp;
      last^.Nachfolger := Nil;
      hlp^.Nachfolger := last;
   End;
   last^.Wert := Wert;
End;

DeddyH 9. Dez 2011 13:34

AW: Pointer of Array of Pointer neues Prinzip
 
Gerade das Durchhangeln wollen wir uns doch sparen.
Delphi-Quellcode:
Procedure TForm1.AddElement(Wert: integer);
Var
   hlp: PEintrag;
Begin
   // Anfang vorhanden ?
   If (First = Nil) Then Begin
      New(First);
      First^.Vorgaenger := Nil; // Der Anfang der Kette hat keinen Vorgänger;
      First^.Nachfolger := Nil; // Der Nachfolger ist auch erstmal nicht vorhanden.
      last := First;
   End Else Begin
      New(hlp);
      hlp^.Vorgaenger := Last;
      hlp^.Nachfolger := nil;
      Last^.Nachfolger := hlp;
      Last := hlp;
   End;
   Last^.Wert := Wert;
End;
Ungetestet, sollte aber stimmen.


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