Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi anfänger: stack als klasse erstellen (https://www.delphipraxis.net/69057-anfaenger-stack-als-klasse-erstellen.html)

nkaaa 9. Mai 2006 17:18


anfänger: stack als klasse erstellen
 
hallo,
ich möchte mir zu lernzwecken einen stack als klasse erstellen.
habe mir zur oop deshalb auch schon ein tutorial durchgelesen.

habe bis jetzt folgendes:
Delphi-Quellcode:
type
  Tmystack = class
    procedure create;
    procedure pop;
    procedure push(str : string);
    function firstItem: string;
  end;
bekomme sofort einen compilerfehler:

[Fehler] Unit1.pas(19): E2065 Ungenügende Forward- oder External-Deklaration: 'Tmystack.create'

für jede der proceduren. wäre nett wenn mir einer weiterhelfen könnte

gruß nkaaa

mkinzler 9. Mai 2006 17:21

Re: anfänger: stack als klasse
 
Du mußt die Methoden implementieren (zumindest als stubs).

nkaaa 9. Mai 2006 17:42

Re: anfänger: stack als klasse
 
danke, funktioniert :spin2:

leddl 9. Mai 2006 17:46

Re: anfänger: stack als klasse
 
Create würde ich allerdings als Konstruktor deklarieren, und nicht als normale Prozedur.
Delphi-Quellcode:
constructor Create;

Ultimator 9. Mai 2006 18:15

Re: anfänger: stack als klasse
 
Und Pop würde ich als function deklarieren, denn irgendwem musst du ja den Wert zuweisen, den du vom Stack holst ;)

nkaaa 9. Mai 2006 18:26

Re: anfänger: stack als klasse
 
dazu war eigentlich
Delphi-Quellcode:
function firstItem: string;
gedacht :wink:

also erst angucken was draufliegt und dann eventuell mit pop runterschmeissen.

DGL-luke 9. Mai 2006 18:28

Re: anfänger: stack als klasse
 
naja... wenn du nix aufm stack hast eben ne exception werfen ^^

ansonsten ist es so, dass "pop" ein anerkanntes "signalwort" ist. bei firstitem würd ich eher vermuten, dass ich da zugreifen kann, ohne dass er was runterschmeißt.

nkaaa 9. Mai 2006 18:37

Re: anfänger: stack als klasse
 
ich glaub du hast mich falsch verstanden.

die function firstitem liefert das element zurück, was ich zuletzt auf den stack gepackt habe;
danach entscheide ich mich dann, ob ich das element wirklich runterschmeissen will (mit pop).

pop schmeisst hier wirklich nur das element vom stack, ohne irgendetwas zurückzugeben.



Zitat:

bei firstitem würd ich eher vermuten, dass ich da zugreifen kann, ohne dass er was runterschmeißt.
so wollte ich das auch machen :wink:

3_of_8 9. Mai 2006 18:40

Re: anfänger: stack als klasse
 
Zwei Sachen fallen mir auf:

1. Pop ist normalerweise eine Funktion, die das oberste Element löscht und den Inhalt zurückgibt.
2. Die Funktion, die du firstItem nennst, bezeichnet man normalerweise als Peek.

Ist eigentlich egal, aber so habe zumindest ich es gelernt.

nkaaa 10. Mai 2006 17:14

Re: anfänger: stack als klasse erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
so hab ein bisschen weitergearbeitet:
Delphi-Quellcode:
type
  Tzeiger = ^Tinfo;
  Tinfo = Record
            info : String;
            next : Tzeiger;
          End;

  Tstack = class(Tobject)
    constructor create;
    procedure pop;  //Element vom Stack runterschmiessen, OHNE es zurückzuliefern!
    procedure push(info : String);  //Element draufpacken
    function empty : Boolean;   //Ist der Stack leer?
    function GetFirstItem : String; //Liefert das erste Element vom Stack zurück
    destructor destroy;
    private
      var first : Tzeiger; //Zeiger auf das erste Element im STack
  end;


implementation

constructor Tstack.create();
begin
  inherited;
  new(stack.first);
  first:=nil;
end;


procedure Tstack.pop;
var help : Tzeiger;
begin
  if not (first = nil) then
    begin
      help:=first;
      first:=first^.next;
      dispose(help);
    end;
end;


procedure Tstack.push(info : String);
var help : Tzeiger;
begin
  new(help);
  help^.info:=info;
  help^.next:=nil;
  if (first=nil) then first^:=help^
    else
      begin
        help.next:=first;
        first:=help;
      end;
end;


function Tstack.empty : Boolean;
begin
  result:=(First=nil);
end;


function Tstack.GetFirstItem : String;
begin
  if not (first=nil) then result:=first^.info
    else result:='Kein Element im Stack';
end;


destructor Tstack.destroy;
begin
  inherited;
end;


procedure TForm1.Button3Click(Sender: TObject);
begin
  stack.create;
end;
anbei noch meine kleine testumgebung.
bekomme im testprogramm sofort beim Stack.create eine zugriffsverletzung :/
die Fehlermeldung kommt selbst dann noch, wenn ich das
Delphi-Quellcode:
new(stack.first);
ausklammere.

wer weiß rat? :wink:

Khabarakh 10. Mai 2006 17:30

Re: anfänger: stack als klasse erstellen
 
Delphi-Quellcode:
type
  Tzeiger = ^Tinfo;
Du solltest dir die Pascal Naming-Conventions angewöhnen:
Delphi-Quellcode:
PZeiger = ^TInfo;
Delphi-Quellcode:
      var first : Tzeiger; //Zeiger auf das erste Element im STack
Eigentlich sollte er hier schon beim var streiken.
Delphi-Quellcode:
FFirst: PInfo;
Delphi-Quellcode:
constructor Tstack.create();
begin
  inherited;
  new(stack.first);
  first:=nil;
end;
Erstens greifst du hier auf eine Variable Stack zu, ganz pöse und auch unsinnig. Zweitens weist du FFirst gleich danach nil zu, also spar dir doch das Erstellen.
Ergo: Bis jetzt kannst du den Konstruktor einfach weglassen.

Delphi-Quellcode:
else result:='Kein Element im Stack';
Delphi-Referenz durchsuchenExceptions

Delphi-Quellcode:
  stack := TStack.Create;
Den Rest kann ich mir leider nicht mehr anschauen, Simpsons rufen ;) .

nkaaa 10. Mai 2006 17:55

Re: anfänger: stack als klasse erstellen
 
naja gut, die bezeichnung werd ich dann noch ändern.

Delphi-Quellcode:
  Tstack = class(Tobject)
    ...
    ...
    private
      var first : Tzeiger; //Zeiger auf das erste Element im Stack
  end;
die variable "first" brauche ich aber in jedem fall, sie zeigt immer auf das erste element im stack.
wie bzw. wo könnte ich sie denn besser deklarieren?


Delphi-Quellcode:
constructor Tstack.create();
begin
  inherited;
  stack:=stack.create;
  first:=nil;
end;
mit dem constructor habe ich das so verstanden, dass er speicherplatz für ein element reserviert.
jetzt weiß ich aber auch nicht genau. :|
mit
Delphi-Quellcode:
var stack : Tstack
wird ja eigentlich auch schon der speicherplatz für die variable stack reserviert oder?
wozu dann extra das "constructor"? könnte man nicht immer einfach "procedure" nehmen?


Delphi-Quellcode:
first:=nil;
: ein neuer stack hat noch kein element, deshalb habe ich "first" auf nil gesetzt.

phXql 10. Mai 2006 18:31

Re: anfänger: stack als klasse erstellen
 
Instanzvariablen werden automatisch auf 0 initialisiert. also eine referenz ist automatisch nil.

nkaaa 10. Mai 2006 18:46

Re: anfänger: stack als klasse erstellen
 
also so wie es aussieht ist der constructor dann wirklich überflüssig.

bleibt noch die frage wo ich das
Delphi-Quellcode:
var first : Tzeiger; //Zeiger auf das erste Element im Stack
innerhalb der klasse deklarieren soll.

Ultimator 10. Mai 2006 18:51

Re: anfänger: stack als klasse erstellen
 
Mach aus dem
Delphi-Quellcode:
type
  Tzeiger = ^Tinfo;
mal ein
Delphi-Quellcode:
type
  PInfo = ^TInfo;
Dann weiß jeder sofort was gemeint ist: T->Klasse, P: Zeiger (Pointer) ;)

Und das first-Element gehört in den private-Teil, allerdings musst du das var davor weglassen.

nkaaa 10. Mai 2006 19:22

Re: anfänger: stack als klasse erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
hab jetzt alles so gemacht
Delphi-Quellcode:
type
  Pinfo = ^Tinfo;
  Tinfo = Record
            info : String;
            next : Pinfo;
          End;

  Tstack = class(Tobject)
    //constructor create;
    procedure pop;  //Element vom Stack runterschmiessen, OHNE es zurückzuliefern!
    procedure push(info : String);  //Element draufpacken
    function empty : Boolean;   //Ist der Stack leer?
    function GetFirstItem : String; //Liefert das erste Element vom Stack zurück
    destructor destroy;
    private
      first : Pinfo; //Zeiger auf das erste Element im Stack
  end;



var
  Form1: TForm1;

var
  st : Tstack;


implementation

{$R *.dfm}

{constructor Tstack.create();
begin
  inherited;
  //new(stack.first);
  //first:=nil;
end;                       ist anscheinend überflüssig }


procedure Tstack.pop;
var help : Pinfo;
begin
  if not (first = nil) then
    begin
      help:=first;
      first:=first^.next;
      dispose(help);
    end;
end;


procedure Tstack.push(info : String);
var help : Pinfo;
begin
  new(help);
  help^.info:=info;
  help^.next:=nil;
  if (first=nil) then first^:=help^
    else
      begin
        help.next:=first;
        first:=help;
      end;
end;


function Tstack.empty : Boolean;
begin
  result:=(First=nil);
end;


function Tstack.GetFirstItem : String;
begin
  if not (first=nil) then result:=first^.info
    else result:='Kein Element im Stack';
end;


destructor Tstack.destroy;
begin
  inherited;
end;

procedure TForm1.createClick(Sender: TObject);
begin
  //st.create;
end;


procedure TForm1.pushClick(Sender: TObject);
begin
  st.push(edit1.text);
end;


procedure TForm1.popClick(Sender: TObject);
begin
  st.pop;
end;
anbei die ganze testumgebung.
bekomme immernoch einen fehler (zugrissverletzung)
beim "pushen" in der zeile:
Delphi-Quellcode:
  if (first=nil) then first^:=help^

Khabarakh 10. Mai 2006 19:28

Re: anfänger: stack als klasse erstellen
 
Delphi-Quellcode:
begin
  if (first=nil) then
    first := help
  else
  begin
    help.next:=first;
    first:=help;
  end;
end;
Delphi-Quellcode:
procedure TForm1.createClick(Sender: TObject);
begin
  st := TStack.Create;
end;

Hawkeye219 10. Mai 2006 19:38

Re: anfänger: stack als klasse erstellen
 
Hallo,

einige Anmerkungen:
  • Den Destruktor Destroy solltest du mit OVERRIDE kennzeichnen, da du ihn überschreibst:

    Delphi-Quellcode:
    destructor Destroy; override;
  • In der Implementierung des Destruktors solltest du alle noch enthaltenen Elemente wieder freigeben.
  • Vor dem Beenden des Programms (z.B. in FormDestroy) solltest du die Instanz (Variable st) wieder freigeben.
  • Warum nutzt die Methode empty nicht in den anderen Methoden? Stattdessen überprüfst du die Variable First immer direkt auf den Wert NIL.
Gruß Hawkeye

nkaaa 10. Mai 2006 20:10

Re: anfänger: stack als klasse erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
habe das programm soweit verbessert, zumindest kommen jetzt keine abstürze mehr.
allerdings ist wohl irgendwo ein fehler in der push oder pop procedure.
ich kann elemente in den stack packen und er zeigt mir auch immer das oberste elemente mit "getfirstitem",
aber wenn ich einmal die pop procedure ausführe wird nur noch (meine exception) angezeigt "Keine Elemente im Stack".
hab jetzt schon ne ganze zeit lang geguckt, finde den fehler aber nicht :|
Delphi-Quellcode:
type
  Pinfo = ^Tinfo;
  Tinfo = Record
            info : String;
            next : Pinfo;
          End;

  Tstack = class(Tobject)
    constructor create;
    procedure pop;  //Element vom Stack runterschmiessen, OHNE es zurückzuliefern!
    procedure push(info : String);  //Element draufpacken
    function empty : Boolean;   //Ist der Stack leer?
    function GetFirstItem : String; //Liefert das erste Element vom Stack zurück
    destructor destroy;
    private
      first : Pinfo; //Zeiger auf das erste Element im Stack
  end;



var
  Form1: TForm1;

var
  st : Tstack;


implementation

{$R *.dfm}

constructor Tstack.create;
begin
  inherited;
end;


procedure Tstack.pop;
var help : Pinfo;
begin
  if not empty then
    begin
      help:=first;
      first:=first^.next;
      dispose(help);
    end;
end;


procedure Tstack.push(info : String);
var help : Pinfo;
begin
  new(help);
  help^.info:=info;
  help^.next:=nil;
  if not empty then first:=help
    else
      begin
        help.next:=first;
        first:=help;
      end;
end;


function Tstack.empty : Boolean;
begin
  result:=(First=nil);
end;


function Tstack.GetFirstItem : String;
begin
  if not empty then result:=first^.info
    else result:='Kein Element im Stack';
end;


destructor Tstack.destroy;
begin
  inherited;
  //fehlt noch: nacheinander alle stackelemente "disposen"
end;


procedure TForm1.createClick(Sender: TObject);
begin
  st := TStack.Create;
end;


procedure TForm1.pushClick(Sender: TObject);
begin
  st.push(edit1.text);
end;


procedure TForm1.popClick(Sender: TObject);
begin
  st.pop;
end;

procedure TForm1.Oberstes_ItemClick(Sender: TObject);
begin
  showmessage(st.GetFirstItem);
end;

Hawkeye219 10. Mai 2006 20:18

Re: anfänger: stack als klasse erstellen
 
Der Fehler steckt in der Methode push:

Delphi-Quellcode:
if empty then first := help // so sollte es aussehen!
Wenn du dir die Routine nach der Korrektur etwas genauer ansiehst, wirst du sie sicher vereinfachen können...

Gruß Hawkeye

nkaaa 10. Mai 2006 20:30

Re: anfänger: stack als klasse erstellen
 
vielen dank euch allen, kaum zu glauben, aber es funktioniert endlich :mrgreen:


Zitat:

Zitat von Hawkeye219
Wenn du dir die Routine nach der Korrektur etwas genauer ansiehst, wirst du sie sicher vereinfachen können...

Gruß Hawkeye

Delphi-Quellcode:
procedure Tstack.push(info : String);
var help : Pinfo;
begin
  new(help);
  help^.info:=info;
  if empty then
    begin
      help^.next:=nil;
      first:=help;
    end
    else
      begin
        help.next:=first;
        first:=help;
      end;
end;
meinst du so vereinfachen?
er würde dann einmal die zuweisung help^.next:=nil; sparen, wenn der stack nicht leer ist.

lizardking 10. Mai 2006 20:37

Re: anfänger: stack als klasse erstellen
 
Zitat:

Zitat von nkaaa
meinst du so vereinfachen?
er würde dann einmal die zuweisung help^.next:=nil; sparen, wenn der stack nicht leer ist.

Schau Dir mal an, was Du mit "empty" ueberpruefst, also welchen Wert first in dem Fall hat, wenn "empty" true zurueckliefert. Und dann ueberleg mal ganz genau, ob im if...then-Zweig bei Push ueberhaupt was anderes passiert, als im else-Zweig. :wink:

Gruesse,

Lizzy

nkaaa 10. Mai 2006 20:52

Re: anfänger: stack als klasse erstellen
 
Delphi-Quellcode:
procedure Tstack.push(info : String);
var help : Pinfo;
begin
  new(help);
  help^.info:=info;
  help^.next:=nil;
  if empty then first:=help
    else
      begin
        help.next:=first;
        first:=help;
      end;
end;
Delphi-Quellcode:
procedure Tstack.push(info : String);
var help : Pinfo;
begin
  new(help);
  help^.info:=info;
  if empty then
    begin
      help^.next:=nil;
      first:=help;
    end
    else
      begin
        help.next:=first;
        first:=help;
      end;
end;
verdammt.. ich sehe ehrlich keine Möglichkeit, wie ich das verbessern könnte :wall:


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