Einzelnen Beitrag anzeigen

Nathaniel

Registriert seit: 17. Jun 2012
11 Beiträge
 
#1

Einfaches Listenprogramm mittels Zeigern

  Alt 17. Jun 2012, 14:10
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...
  Mit Zitat antworten Zitat