![]() |
Einfaches Listenprogramm mittels Zeigern
Hallo,
ich hatte vor gehabt, ein kleines Beipsielprogramm umzusetzen um das Prinzip der Zeigern und Listen richtig zu verstehen. Dazu habe ich eine doppelt verkettete lineare Liste benutzt, weil diese besser in dem Programmkontext passt. Kurzbeschreibung vom Programm • Der Nutzer gibt den Vornamen und Nachnamen ein • Diese Informationen werden in einer Liste gespeichert • Es ist möglich hin und her zu wechseln mittels den Buttons "Vor" und "Weiter" • Somit kann man vorherige Einträge einsehen Wenn ich den Programmcode in einer Unit schreibe, dann funktioniert auch alles... Ich habe nur Probleme damit, es eine andere Unit zu transferieren, was ich aber gerne möchte! Ich hatte wie gesagt vorher alles in der Main-Unit reingeschrieben und bin jetzt dabei es Schritt für Schritt auf die andere Unit auszulagern. Insofern sind noch einige Sachen in der Main.
Delphi-Quellcode:
Ich habe hier einige Prozeduren, welche hier nicht relevant sind (OnCreate) einfach weggelassen, um es übersichtlicher zu gestalten...
unit UMain;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, UTypes, UData; type TForm1 = class(TForm) Label1: TLabel; Label2: TLabel; EdVorname: TEdit; EdNachname: TEdit; BtnVor: TButton; BtnEinfuegen: TButton; BtnLoeschen: TButton; BtnWeiter: TButton; procedure BtnEinfuegenClick(Sender: TObject); procedure BtnWeiterClick(Sender: TObject); procedure BtnVorClick(Sender: TObject); procedure BtnLoeschenClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormCreate(Sender: TObject); private { Private-Deklarationen } Current: TElementPointer; procedure ShowCurrent; function getInformation:TInfo; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} { TForm1 } procedure TForm1.BtnEinfuegenClick(Sender: TObject); var TempElement:TElementPointer; info:TInfo; begin InsertElement(getInformation); // In UData deklariert end; procedure TForm1.BtnVorClick(Sender: TObject); begin if Current^.VorElement <> nil then // Wenn das vorherige Element NICHT leer ist, dann... begin Current^.Namen.Vorname := EdVorname.Text; // Lese den Namen aus und trage ins EdtFeld ein Current^.Namen.Nachname := EdNachname.Text; Current := Current^.VorElement; // Setze den Zeiger auf das vorherige (jetzt aktuelle) Element ShowCurrent; // Zeige die Veränderung BtnVor.Enabled:=Current^.VorElement <> nil; BtnWeiter.Enabled:=true; end else ShowMessage('Zugriffsverletzung auf vorderes Element!'); ActiveControl:=EdVorname; end; procedure TForm1.BtnWeiterClick(Sender: TObject); begin if Current^.NachElement <> nil then // Wenn das nächste Element NICHT leer ist, dann... begin Current^.Namen.Vorname:=EdVorname.Text; // Lese den Namen aus und trage ins EdtFeld ein Current^.Namen.Nachname:=EdNachname.Text; Current := Current^.NachElement; // Setze Zeiger auf aktuellem Element ShowCurrent; // Zeige Veränderungen BtnWeiter.Enabled:= Current^.NachElement <> nil; BtnVor.Enabled:=true; end else showMessage('Zugriffsverletzung auf nachfolgende Element!'); ActiveControl := EdVorname; end; function TForm1.getInformation: TInfo; begin getInformation.Vorname:=EdVorname.Text; getInformation.Nachname:=EdNachname.Text; end; procedure TForm1.ShowCurrent; begin EdVorname.Text:=Current^.Namen.Vorname; EdNachname.Text:=Current^.Namen.Nachname; end; end.
Delphi-Quellcode:
unit UData;
interface uses SysUtils, UTypes; function NewElement(info:TInfo): TElementPointer; procedure InsertElement(info:TInfo); procedure getNext; procedure getPrevious; implementation var Current:TElementPointer; {----------------------------- NewElement -----------------------------------} function NewElement(info:TInfo): TElementPointer; var TempElement:TElementPointer; begin New(TempElement); TempElement^.Namen.Vorname:= info.Vorname; TempElement^.Namen.Nachname:= info.Nachname; TempElement^.VorElement:=nil; TempElement^.NachElement:=nil; NewElement:=TempElement; end; {----------------------------- InsertElement ---------------------------------} procedure InsertElement(info:TInfo); var TempElement:TElementPointer; begin TempElement:=NewElement(info); if Current<>nil then begin TempElement^.NachElement:=Current; TempElement^.VorElement :=Current^.VorElement; Current^.VorElement:=TempElement; if TempElement^.VorElement<>nil then TempElement^.VorElement^.NachElement := TempElement; end; Current:=TempElement; end; {----------------------------- getNext ---------------------------------------} procedure getNext; begin // Code end; {----------------------------- getPrevious -----------------------------------} procedure getPrevious; begin // Code end; end.
Delphi-Quellcode:
Problembeschreibung vom Programm
unit UTypes;
interface type TInfo = record Vorname: string[30]; Nachname: string[30]; end; TElementPointer = ^TListElement; TListElement = record Namen: TInfo; VorElement : TElementPointer; NachElement: TElementPointer; end; implementation end. Ich kann völlig normal auf Einfügen klicken und die Prozedur InsertElement ausführen, womit ich ein neues Listenelement erzeuge und darin die Informationen aus den Editfeldern reinschreibe. Wenn ich nun aber zurückblättern möchte (oder vor) kommt die Exception "EAccessViolation". Wahrscheinlich ist die Lösung sehr einfach, allerdings kann ich es mir nicht erklären, weil ja eigentlich die Listenelemente exisitieren... |
AW: Einfaches Listenprogramm mittels Zeigern
Ich glaube, dass Problem ist, dass du Current 2x definiert hast - 1x in beiden Units. Es wird aber hauptsächlich mit UData.Current gearbeitet...
Problemlösung: Entferne die Deklaration aus der UData Unit und gebe der Funktion InsertElement() Current als Parameter mit! |
AW: Einfaches Listenprogramm mittels Zeigern
Hallo,
danke für die Antwort, allerdings war diese nicht das Problem. Das Problem habe ich soeben gelöst bekommen und es lag daran, dass ich bei dem Wechsel zwischen den Namen mittels den BtnWeiter und BtnVor auf eine Speicheradresse zugegriffen habe, welche nicht existiert hat... Ich hab jetzt einfach die Funktion in UData "getNext" wie folgt deklariert:
Delphi-Quellcode:
Also mittels Referenzparameter Ausgabe.
procedure getNext(info:TInfo; var ausgabe:TInfo);
begin // if Current^.VorElement <> nil then begin Current^.Namen.Vorname := info.Vorname; Current^.Namen.Nachname := info.Nachname; Current := Current^.NachElement; ausgabe.Vorname:=Current^.Namen.Vorname; ausgabe.Nachname:=Current^.Namen.Nachname; end Diese Prozedur rufe ich auf wenn der BtnWeiter betätigt wurde:
Delphi-Quellcode:
Danke trotzdem : )
procedure TForm1.BtnWeiterClick(Sender: TObject);
var aus:TInfo; begin getNext(getInformation, aus); EdVorname.Text:=aus.Vorname; EdNachname.Text:=aus.Nachname; end; |
AW: Einfaches Listenprogramm mittels Zeigern
Vielleicht hilft das noch zum Verständnis:
![]() |
AW: Einfaches Listenprogramm mittels Zeigern
Vielen Dank, werde ich mir die Tage mal durchlesen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:23 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