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:
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.
Ich habe hier einige Prozeduren, welche hier nicht relevant sind (OnCreate) einfach weggelassen, um es übersichtlicher zu gestalten...
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:
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.
Problembeschreibung vom Programm
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...