Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem mit Zeigern (https://www.delphipraxis.net/109409-problem-mit-zeigern.html)

praesident 29. Feb 2008 19:40


Problem mit Zeigern
 
Hallo,

ich habe in der Schule beim Umstieg von Pascal auf Delphi ein Problem. Und zwar bekomme ich beim Arbeiten mit Zeigern ständig einen Exeption Fehler angezeugt.

Hier der problematische Programmteil:


Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:char;i:byte);
VAR zhilf,zneu:tzeiger;

BEGIN
 zhilf:=zkopf;
 zhilf^.next:=NIL;
IF NOT(i=1) THEN
 BEGIN
 REPEAT
  zhilf:=zhilf^.next;
 UNTIL zhilf^.next=NIL;
 END;
  new(zneu);
  zneu^.inhalt:=inhalt;
  zhilf^.next:=zneu;
  zneu^.next:=NIL;
END;
wenn ich einen Wert eingebe, bleibt er jedesmal bei zhilf^.next:=NIL; stehen. nehm ich die zeile raus, weiter unten.
bei Pascal hatte ich das Problem nicht. Woran liegt das?

Ich komm wirklich nicht mehr weiter
Danke für eure Hilfe.

mfg
de präsi

DP-Maintenance 29. Feb 2008 19:43

DP-Maintenance
 
Dieses Thema wurde von "Dax" von "Neuen Beitrag zur Code-Library hinzufügen" nach "Object-Pascal / Delphi-Language" verschoben.

SirThornberry 29. Feb 2008 19:46

Re: Problem mit Zeigern
 
wie rufst du die funktion auf und warum übergibst du zkopf als var parameter wenn du in der Funktion den Wert gar nicht neu setzt?

DeddyH 29. Feb 2008 19:46

Re: Problem mit Zeigern
 
Zitat:

Delphi-Quellcode:
zhilf^.next:=NIL;
IF NOT(i=1) THEN
BEGIN
REPEAT
  zhilf:=zhilf^.next;
UNTIL zhilf^.next=NIL;

Diese Logik versteh ich nicht. Du setzt den Nachfolger initial auf nil, weist diesen in der Schleife dem Zeiger selbst zu (also sind anschließend beide nil) und fragst ihn dann wieder ab :gruebel:

praesident 29. Feb 2008 19:51

Re: Problem mit Zeigern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von SirThornberry
wie rufst du die funktion auf und warum übergibst du zkopf als var parameter wenn du in der Funktion den Wert gar nicht neu setzt?

Hier wird die Prozedur aufgerufen:

Delphi-Quellcode:
  init(zkopf);
  laeng:=length(edit1.Text);
  FOR i:=1 TO laeng DO
   BEGIN
    push(zkopf,edit1.text[i],i);
   END;
"i" übernehme ich, weil die Funktion, die prüfen sollte, ob zkopf auf NIL zeigt auch diesen exeption fehler erzeugt hatte

ja, das mit dem VAR parameter wurde uns glaub ich von meinem info lehrer so gesagt...scheint aber wirklich überflüssig zu sein

danke

PS: ich hab den Fehler nochmal als anhang hochgeladen

mkinzler 29. Feb 2008 19:53

Re: Problem mit Zeigern
 
Was soll den die Funktion genau machen?

SirThornberry 29. Feb 2008 19:55

Re: Problem mit Zeigern
 
anhand des Fehlers sag ich mal das "zkopf" nil ist. Und damit krachts natürlich beim zugriff auf next.
Anhand dessen was du bisher gepostet hast empfehle ich dir das Video Pointerfun ( http://www.delphipraxis.net/internal...=357830#357830 ). Da werden Pointer wunderbar erklärt mit Beispiel.

praesident 29. Feb 2008 19:57

Re: Problem mit Zeigern
 
Zitat:

Zitat von mkinzler
Was soll den die Funktion genau machen?

naja, das ist teil eines rechners, wo ich die aufgabe in soner postfix-form eingebe...

dazu soll das eingabefeld ausgelesen werden und jedes zeichen einzeln in einen stack (die liste) geschrieben werden...

danach wird gerechnet...

DeddyH 29. Feb 2008 19:58

Re: Problem mit Zeigern
 
Nochmal:
Delphi-Quellcode:
zhilf^.next:=NIL; //Nachfolger ist nil
IF NOT(i=1) THEN
BEGIN
REPEAT
  zhilf:=zhilf^.next;   //jetzt ist auch zhilf nil
UNTIL zhilf^.next=NIL; //next von nil^?

Macci 29. Feb 2008 20:02

Re: Problem mit Zeigern
 
Warum nicht einfach so?

Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:char);
VAR zhilf,zneu:tzeiger;
BEGIN
zhilf:=zkopf;
WHILE NOT (zhilf^.next=NIL) DO zhilf:=zhilf^.next;

  new(zneu);
  zneu^.inhalt:=inhalt;
  zhilf^.next:=zneu;
  zneu^.next:=NIL;
END;

mkinzler 29. Feb 2008 20:04

Re: Problem mit Zeigern
 
Und zKopf ist dann die Wurzel?

Delphi-Quellcode:
PROCEDURE push(zkopf:tzeiger;inhalt:char;i:byte);
VAR zneu:tzeiger;
BEGIN
    //Ermittle letztes Element
    while zhilf^.next<>NIL do
        zkopf := zkopf^.Next;
    new(zneu);
    zneu^.inhalt:=inhalt;
    zneu^.next:=NIL;
    zkopf^.next:=zneu;
END;

praesident 29. Feb 2008 20:06

Re: Problem mit Zeigern
 
Zitat:

Zitat von Macci
Warum nicht einfach so?

Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:char);
VAR zhilf,zneu:tzeiger;
BEGIN
zhilf:=zkopf;
WHILE NOT (zhilf^.next=NIL) DO zhilf:=zhilf^.next;

  new(zneu);
  zneu^.inhalt:=inhalt;
  zhilf^.next:=zneu;
  zneu^.next:=NIL;
END;

da kommt bei mir hier:

Delphi-Quellcode:
WHILE NOT (zhilf^.next=NIL) DO zhilf:=zhilf^.next;
auch ein fehler

SirThornberry 29. Feb 2008 20:08

Re: Problem mit Zeigern
 
garantiert der gleiche weil zu dem Zeitpunkt schon wieder versucht wird einen Zeiger zu derefernzieren der nil ist (hab ich oben bereits geschrieben).

Macci 29. Feb 2008 20:08

Re: Problem mit Zeigern
 
Komisch... gib doch bitte mal die Definiton von TZeiger

DeddyH 29. Feb 2008 20:09

Re: Problem mit Zeigern
 
Delphi-Quellcode:
WHILE (zhilf <> nil) and (zhilf^.next <> NIL) DO zhilf:=zhilf^.next;

SirThornberry 29. Feb 2008 20:10

Re: Problem mit Zeigern
 
er übergibt der Funktion Push bereits nil

DeddyH 29. Feb 2008 20:12

Re: Problem mit Zeigern
 
Dann kann das nix werden, außer dass der Fehler dann später kommt.

3_of_8 29. Feb 2008 20:12

Re: Problem mit Zeigern
 
Dein Code ist wirklich nicht sonderlich gut. In Pascal kann man sowas schreiben, aber Delphi hat ganz andere Konventionen.

Aber abgesehen von den Konventionen: Warum gehst du immer bis zum Ende hindurch? Wenn das ein Stack ist, könntest du auch einfach dein neues Element ganz vorne hinsetzen. Dann könntest du in konstanter Zeit pushen und poppen.

Außerdem, warum machst du das nicht gleich in einer Klasse?

praesident 29. Feb 2008 20:14

Re: Problem mit Zeigern
 
Zitat:

Zitat von DeddyH
Delphi-Quellcode:
WHILE (zhilf <> nil) and (zhilf^.next <> NIL) DO zhilf:=zhilf^.next;

wenn ich die Zeile eingebe, hängts hier

Delphi-Quellcode:
  zhilf^.next:=zneu;
hier die deklaration:

Delphi-Quellcode:
TYPE tzahl=char;
     tinhalt=tzahl;
     tzeiger=^tknoten;
     tknoten= RECORD
               inhalt: tinhalt;
               next:tzeiger;
               END;

VAR zliste,zkopf :tzeiger;

DeddyH 29. Feb 2008 20:16

Re: Problem mit Zeigern
 
Wenn Du nil an die Funktion übergibst, kommt der Fehler eben an der besagten Stelle.

praesident 29. Feb 2008 20:21

Re: Problem mit Zeigern
 
Zitat:

Zitat von DeddyH
Wenn Du nil an die Funktion übergibst, kommt der Fehler eben an der besagten Stelle.

bitte entschuldigt, aber ich habe das auch nur von meinem lehrer vorgesetzt bekommen...und nun macht mal

hab das erst seit einer woche und wir hatten vorher nur mit pascal gearbeitet...

könntet ihr also für einen totalen delphi anfänger den fehler noch einmal zusammenfassen? und wenn es nicht allzu viel umstände macht noch einen kleinen programmcode als verbesserung?

wäre echt meine rettung, da mir das mit den zeigern in delphi nicht genauer erläutert wurde


danke

SirThornberry 29. Feb 2008 20:30

Re: Problem mit Zeigern
 
beim aufruf deiner Funktion "push" hat zkopf den Wert nil
das heißt er zeigt auf keinen Speicher. Dementsprechend kracht es immer sobald du auf Untereigenschaften davon zugreifen willst. Wie bereits erwähnt empfehle ich dir das Video Pointerfun damit du ein Gespür für Pointer bekommst.

DeddyH 29. Feb 2008 20:32

Re: Problem mit Zeigern
 
Ungetestet:
Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:char);
VAR zhilf, zneu:tzeiger;
BEGIN
  //erstes Element soll angelegt werden
  if zkopf = nil then
    begin
      new(zhilf);
      zhilf^.inhalt := inhalt;
      zhilf^.next := nil;
    end
  //eine weiteres Element soll angehängt werden
  else
    begin
      zhilf:=zkopf;
      while (zhilf <> nil) and (zhilf^.next <> nil) do
          zhilf:=zhilf^.next;
      new(zneu);
      zneu^.inhalt:=inhalt;
      zneu^.next:=NIL;
      zhilf^.next:=zneu;
    end;
  zkopf := zhilf;
END;

praesident 29. Feb 2008 20:36

Re: Problem mit Zeigern
 
Zitat:

Zitat von DeddyH
Ungetestet:
Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:char);
VAR zhilf, zneu:tzeiger;
BEGIN
  //erstes Element soll angelegt werden
  if zkopf = nil then
    begin
      new(zhilf);
      zhilf^.inhalt := inhalt;
      zhilf^.next := nil;
    end
  //eine weiteres Element soll angehängt werden
  else
    begin
      zhilf:=zkopf;
      while (zhilf <> nil) and (zhilf^.next <> nil) do
          zhilf:=zhilf^.next;
      new(zneu);
      zneu^.inhalt:=inhalt;
      zneu^.next:=NIL;
      zhilf^.next:=zneu;
    end;
  zkopf := zhilf;
END;

super danke...schon mal kein fehler

werd mir das mal genauer anschauen, damit ich verstehe, warum bei mir immer der Fehler erzeugt wurde...

danke nochmal für eue hilfe

Macci 29. Feb 2008 20:40

Re: Problem mit Zeigern
 
Stimmt, daran dass zkopf schon mit nil übergeben wird, habe ich gar nicht gedacht ;-)

@DeddyH:

Hier
Delphi-Quellcode:
 while (zhilf <> nil) and (zhilf^.next <> nil) do
          zhilf:=zhilf^.next;
ist die erste Abfrage (zhilf<>nil) unnötig ;-)
zhilf kann ja nie nil werden.

DeddyH 29. Feb 2008 20:42

Re: Problem mit Zeigern
 
Stimmt, war noch vom C&P übrig geblieben (schadet aber auch nicht) :zwinker:

praesident 29. Feb 2008 20:43

Re: Problem mit Zeigern
 
aber müsste nicht das:

Delphi-Quellcode:
  zkopf := zhilf;
ganz vor, als letzte zeile der ersten fallunterscheidung?

sonst könnte ich ja nie mehr auf das erste element zugreifen!?

DeddyH 29. Feb 2008 20:45

Re: Problem mit Zeigern
 
Durch diese Zuweisung hast Du immer das letzte Element der Liste in zkopf stehen. Soll das nicht so sein?

praesident 29. Feb 2008 20:48

Re: Problem mit Zeigern
 
Zitat:

Zitat von DeddyH
Durch diese Zuweisung hast Du immer das letzte Element der Liste in zkopf stehen. Soll das nicht so sein?

nein, eigentlich sollte es immer das erste sein...aber das ist ja eigentlich kein aufwand, oder?

DeddyH 29. Feb 2008 20:52

Re: Problem mit Zeigern
 
Nö, ist kein Aufwand, dann mach es so, wie Du selbst schon gesagt hast:
Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:char);
VAR zhilf, zneu:tzeiger;
BEGIN
  //erstes Element soll angelegt werden
  if zkopf = nil then
    begin
      new(zhilf);
      zhilf^.inhalt := inhalt;
      zhilf^.next := nil;
      zkopf := zhilf;
    end
  //eine weiteres Element soll angehängt werden
  else
    begin
      zhilf:=zkopf;
      while (zhilf <> nil) and (zhilf^.next <> nil) do
          zhilf:=zhilf^.next;
      new(zneu);
      zneu^.inhalt:=inhalt;
      zneu^.next:=NIL;
      zhilf^.next:=zneu;
    end;
END;

praesident 29. Feb 2008 20:53

Re: Problem mit Zeigern
 
Zitat:

Zitat von DeddyH
Nö, ist kein Aufwand, dann mach es so, wie Du selbst schon gesagt hast:
Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:char);
VAR zhilf, zneu:tzeiger;
BEGIN
  //erstes Element soll angelegt werden
  if zkopf = nil then
    begin
      new(zhilf);
      zhilf^.inhalt := inhalt;
      zhilf^.next := nil;
      zkopf := zhilf;
    end
  //eine weiteres Element soll angehängt werden
  else
    begin
      zhilf:=zkopf;
      while (zhilf <> nil) and (zhilf^.next <> nil) do
          zhilf:=zhilf^.next;
      new(zneu);
      zneu^.inhalt:=inhalt;
      zneu^.next:=NIL;
      zhilf^.next:=zneu;
    end;
END;

genau, danke...ich hoffe jetzt pack ich auch was allein

DeddyH 29. Feb 2008 20:56

Re: Problem mit Zeigern
 
[OT] Gibt es hier eigentlich noch kein Tut zu einfach/doppelt verketteten Listen? Wäre ja mal 'ne schöne Gelegenheit, sich mit seinem neuen Delphi vertraut zu machen :mrgreen: [/OT]

grenzgaenger 29. Feb 2008 21:54

Re: Problem mit Zeigern
 
tja, mal 'n hinweis, hier wird das thema auch behandelt: hier

ausserdem gibts massenweise threads und tutorials über verkettete listen z.b.Hier im Forum suchenverkettete listen, In der Entwickler-Ecke suchenverkettete listen, Bei Google suchenverkettete listen

DeddyH 29. Feb 2008 22:07

Re: Problem mit Zeigern
 
Also, Tuts hab ich auf Anhieb keine entdeckt, und bei den meisten (aktuellen) gefundenen Threads innerhalb der DP war ich selbst beteiligt ;)

praesident 29. Feb 2008 22:54

Re: Problem mit Zeigern
 
ich hab noch ein kleines problem...

und zwar, wenn ich nun eine zweite liste erzeuge und dort soll die erste in umgekehrter reihenfolge hineingeschrieben werden.....

dafür habe ich zkopf und zkopf2 in der ersten unit deklariert...die waren vorher gar nicht deklariert

allerdings bekomme ich jetzt immer diese fehlermeldung: [Fehler] Unit1.pas(51): Die Typen der tatsächlichen und formalen Var-Parameter müssen übereinstimmen


hier nocheinmal die zugehörige Prozedur:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
VAR laeng,i:byte;
    zkopf,zkopf2 :tzeiger;
begin
  init(zkopf);
  laeng:=length(edit1.Text);
  FOR i:=1 TO laeng DO
     push(zkopf,edit1.text[i]);

  init(zkopf2);
  FOR i:=1 TO laeng DO
     push(zkopf2,pop(zkopf));
  edit1.text:=top(zkopf2);
end;
die pop-funktion:

Delphi-Quellcode:
FUNCTION pop(VAR zkopf:tzeiger):char;
VAR zhilf1,zhilf2:tzeiger;
    z:char;
BEGIN
 zhilf1:=zkopf;
 zhilf2:=zkopf^.next;
 WHILE NOT(zhilf2^.next = NIL) DO
  BEGIN
   zhilf1:=zhilf2;
   zhilf2:=zhilf2^.next;
  END;
  zhilf1^.next:=NIL;
  pop:=zhilf2^.inhalt;
END;


und die im vorigen teil besprochene push prozedur:

Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:char);
VAR zhilf, zneu:tzeiger;
BEGIN
  //erstes Element soll angelegt werden
  if zkopf = nil then
    begin
      new(zhilf);
      zhilf^.inhalt := inhalt;
      zhilf^.next := nil;
      zkopf := zhilf;
    end
  //eine weiteres Element soll angehängt werden
  else
    begin
      zhilf:=zkopf;
      while (zhilf <> nil) and (zhilf^.next <> nil) do
          zhilf:=zhilf^.next;
      new(zneu);
      zneu^.inhalt:=inhalt;
      zneu^.next:=NIL;
      zhilf^.next:=zneu;
    end;

END;
danke

Macci 29. Feb 2008 23:29

Re: Problem mit Zeigern
 
Würde statt

Delphi-Quellcode:
FUNCTION pop(VAR zkopf:tzeiger):char;
VAR zhilf1,zhilf2:tzeiger;
    z:char;
BEGIN
zhilf1:=zkopf;
zhilf2:=zkopf^.next;
WHILE NOT(zhilf2^.next = NIL) DO
  BEGIN
   zhilf1:=zhilf2;
   zhilf2:=zhilf2^.next;
  END;
  zhilf1^.next:=NIL;
  pop:=zhilf2^.inhalt;
END;

nicht einfach nur

Delphi-Quellcode:
FUNCTION pop(VAR zkopf:tzeiger):char;
BEGIN
result:=zkopf^.inhalt;
zkopf := zkopf^.next
END;
genügen?

Macci 29. Feb 2008 23:31

Re: Problem mit Zeigern
 
Achso, nein würde es nicht, weil du ja keine FIFO-Schlage sondern einen LIFO-Keller willst. Sorry ;-)

Allerdings würde mein Vorschlag passen, wenn du für das Push auch eine entsprechende Prozedur verwenden würdest, die das neue Element am Anfang einfügt, die übrigens viel einfacher wäre.

praesident 29. Feb 2008 23:34

Re: Problem mit Zeigern
 
Zitat:

Zitat von Macci
Würde statt

Delphi-Quellcode:
FUNCTION pop(VAR zkopf:tzeiger):char;
VAR zhilf1,zhilf2:tzeiger;
    z:char;
BEGIN
zhilf1:=zkopf;
zhilf2:=zkopf^.next;
WHILE NOT(zhilf2^.next = NIL) DO
  BEGIN
   zhilf1:=zhilf2;
   zhilf2:=zhilf2^.next;
  END;
  zhilf1^.next:=NIL;
  pop:=zhilf2^.inhalt;
END;

nicht einfach nur

Delphi-Quellcode:
FUNCTION pop(VAR zkopf:tzeiger):char;
BEGIN
result:=zkopf^.inhalt;
zkopf := zkopf^.next
END;
genügen?

nein, würde ich jetzt nicht sagen...

denn, wenn zkopf das erste element ist und pop jeweils das letzte entfernen und freigeben soll muss ich ja solange in der liste weitergehen, bis ein element auf nil zeigt, oder?

bei mir hängts im moment an der letzten zeile der pop prozedur

Delphi-Quellcode:
FUNCTION pop(VAR zkopf:tzeiger):char;
VAR zhilf1,zhilf2:tzeiger;

BEGIN
 zhilf1:=zkopf;
 zhilf2:=zkopf^.next;
 WHILE (zhilf2 <> nil) AND (zhilf2^.next <> NIL) DO
  BEGIN
   zhilf1:=zhilf2;
   zhilf2:=zhilf2^.next;
  END;
  zhilf1^.next:=NIL;
  pop:=zhilf2^.inhalt;
END;
es kommt wieder jedesmal ein exeption fehler

Macci 29. Feb 2008 23:36

Re: Problem mit Zeigern
 
Schau mal, so klappts:

Delphi-Quellcode:
PROCEDURE push(VAR zkopf:tzeiger;inhalt:Char);
var zhilf:tzeiger;
BEGIN
new(zhilf);
zhilf^.inhalt:=inhalt;
zhilf^.next:=zkopf;
zkopf:=zhilf
END;

FUNCTION pop(VAR zkopf:tzeiger):char;
BEGIN
result:=zkopf^.inhalt;
zkopf := zkopf^.next
END;

Hab ich erfolgreich gesetet mit:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var tmp:tzeiger;
begin
push(tmp,'a');
push(tmp,'b');
push(tmp,'c');
showmessage(pop(tmp));  //c
showmessage(pop(tmp));  //b
showmessage(pop(tmp));  //a
end;

praesident 29. Feb 2008 23:39

Re: Problem mit Zeigern
 
Zitat:

Zitat von Macci
Achso, nein würde es nicht, weil du ja keine FIFO-Schlage sondern einen LIFO-Keller willst. Sorry ;-)

Allerdings würde mein Vorschlag passen, wenn du für das Push auch eine entsprechende Prozedur verwenden würdest, die das neue Element am Anfang einfügt, die übrigens viel einfacher wäre.

ich weiß nicht, ich glaube wir sollten das aus i-einem grund immer am ende einfügen...den sinn seh ich aber grad auch nicht

probiers gleich mal mit deiner vorgeschlagenen prozedur


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:45 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz