Liste mit Stapeln von Kisten mit Pascal



  • Guten Morgen zusammen,

    momentan hänge ich bei einer Übungsaufgabe und würde mich über Hilfe oder Anregungen sehr freuen. Es geht sich um folgendes Codefragment:

    procedure remove(inName:String; var ioKiste:tRefKiste);
    {Entfernt die oberste Kiste eines Stapels} 
    
    var
    pKiste : tRefKiste;
    gefunden : boolean;
      
    procedure abhaengen (var ioZeig : tRefKiste);
    
    var
    Hilfszeig : tRefKiste;
    
    begin {abhaengen}
      Hilfszeig := ioZeig;
      ioZeig := iozeig^.next;
      dispose (hilfszeig)
    end;{abhaengen}
    
    begin {remove}
      gefunden := false;
      if ioKiste = nil then {Liste ist Leer}
      gefunden := false;
      if ioKiste <> nil then {Liste ist nicht leer}
        if ioKiste^.name = inName then  
          abhaengen(ioKiste) {erstes Element ist zu entfernen}
        else
          begin {durchlaufen der Liste}
            pKiste := ioKiste;
            while (pKiste^.next <> nil) and not (gefunden) do
              if pKiste^.next^.name = inName then
                abhaengen(pKiste^.next)
              else
                pKiste := pKiste^.next;
          end; {durchlaufen}                    
    end; {remove}
    

    Und zwar muss die letzte Kiste eines gesuchten Stapels gefunden und abgehängt werden, und mit dieser Prozedur soll das Abhängen geschrieben werden.

    Die ioKisten sind folgendermaßen aufgebaut:

    es existieren 4 Zeiger in jeder Kiste und zwar mit:

    • Up (für die nächste obere Kiste),
    • Zahl,
    • Name,
    • Next (für den nächsten Stapel)

    Mit freundlichen Grüßen,

    Denis



  • Und wie lautet deine Frage?



  • Eine richtige Frage ist es nicht unbedingt, nur habe ich das Gefühl mich irgendwo "verlaufen" zu haben oder den sprichwörtlichen Wald vor lauter Bäumen nicht mehr zu sehen.

    Deshalb habe ich es hier mal rein gestellt, um Anregungen zu erhalten, wie man es anders/besser machen kann, da ich es ja auch besser verstehen und auch besser werden möchte 🙂



  • Gut, dann gebe ich mal meinen Senf dazu:

    • auch wenn man in Pascal Funktionen verschachteln kann, ist das häufig keine so gute Idee. Ich würde daher eher das "abhaengen" rausziehen. Dann entfällt auch der Kommentar für den Funktionsnamen bei begin/end.

    • was tut "abhängen" genau? Ist nicht das wesentliche an dieser Funktion, dass sie vorne abhängt? Wäre vielleicht gut, das im Namen zu haben.

    • in folgendem Code:

       gefunden := false;
       if ioKiste = nil then {Liste ist Leer}
       gefunden := false;
      

      Hier ist erstmal die Einrückung nicht gut (in Zeile 3 in meinem Zitat). Aber das andere ist: in Zeile 1 setzt du gefunden auf false. In der nächsten Zeile machst du irgendeinen if-Test und wenn der true ist, dann setzt du gefunden erneut auf false, weil du dem false-Setzen in Zeile 1 nicht vertraust? In anderen Worten: die Zeilen 2 und 3 sind überflüssig.

    • Dann sieht deine Funktion zum Entfernen sehr kompliziert aus - insbesondere sowas wie if pKiste^.next^.name = inName then - vielleicht wäre es klüger, immer nur den aktuellen Namen zu testen (also pKiste^.name) und wenn der nicht gefunden wird, auf next zu springen?

    • Da du auch einen up-Pointer hast, musst du den auch anpassen.

    • Und dieser Text hier ist nicht korrekt:

      es existieren 4 Zeiger in jeder Kiste und zwar mit:

      • Up (für die nächste obere Kiste),
      • Zahl,
      • Name,
      • Next (für den nächsten Stapel)

      Es gibt nur 2 Zeiger, nicht 4, nämlich up und next. Zahl und Name sind keine Zeiger.



  • @AhornGrabung10 Eine Meldung an die aufrufende Procedire, ob die Aktion erfolgreich war, wäre auch ganz nützlich.



  • Erstmal vielen Dank für die Kommentare bis jetzt 🙂

    Das Verschachteln von Funktionen finde ich auch nach einer Zeit sehr unübersichtlich, und werde versuchen dies einfacher zu gestallten.

    Die Funktion abhängen sollte eigentlich, die oberste Kiste des Stapels löschen, habe aber eben selber erkannt, dass ich im Stapel gar nicht nach oben gehe 🙈 werde also nachher mal schauen, wie ich den Up-Pointer da rein baue.

    Was mich da mit dem If-Test geritten hat, könnte ich jetzt nicht mehr sagen.

    Ich werde mich nochmal ran setzen und werde eure Vorschläge beherzigen 🙂

    Vielen Dank schon einmal und ich wünsche euch einen schönen Abend noch 🙂



  • Guten Tag zusammen 🙂

    ich habe mich nochmal ran gesetzt und versucht, die Punkte zu berücksichtigen. Habe nun aber das Gefühl es verschlimmbessert zu haben 😅 werde aber trotzdem weiter dran bleiben und es weiter versuchen. Habe zudem versucht mehr mit den Zeigern zu arbeiten, was sich aber als schwieriger herausstellt als gedacht.

    Hat sich eurer Meinung nach etwas verbessert, oder befinde ich mich auf dem falschen Weg? Habe versucht mehr Fallunterscheidungen zu betrachten, was m.M.n. die Struktur verbessert

    Viele Grüße,

    Denis

    procedure remove(inName:String; var ioKiste:tRefKiste);
    {entfernt das letzte Element eines gesuchten Stapels}
    
    var
      p1, p2 :  tRefKiste;
    
    begin {procedure}
      
      p1 := nil; 
      p2 := nil;
      
      if (ioKiste <> nil) then {prüft ob Kiste leer}
      begin
      	if (inName = ioKiste^.name) then {prüft ob erster Stapel der richtige ist}
      	begin
      		if (ioKiste^.up = nil) then {keine weitere Kiste oben}
      		begin
      			p1 := ioKiste^.next;
      			dispose(ioKiste);
      			ioKiste := p1;
      		end {if keine weitere Kiste oben}
      		else
      		begin {weitere Kisten oben}
      			p1 := ioKiste;
      			if (p1^.up <> nil) then {nach oben laufen}
      			begin 
      				while (p1^.up <> nil) do
      				begin
      					p2 := p1;
      					p1 := p1^.up;
      				end; {while}
      			end; {nach oben laufen}
      			dispose(p1);
      			p1 := ioKiste;
      			p2 := ioKiste;
      		end {else weitere Kisten oben}
      	end {if Prüfung Stapel eins}
      	else
      	begin {prüft weitere Stapel}
      		while (inName <> ioKiste^.name) AND (ioKiste^.next <> nil) do {nach rechts laufen bis Stapel gefunden}
      		begin
      			ioKiste := ioKiste^.next;
      		end; {while}
      		if (ioKiste^.up = nil) then {keine weitere Kiste oben}
      		begin
      			p1 := ioKiste^.next;
      			dispose(ioKiste);
      			ioKiste := p1;
      			p2 := p1;
      		end {if keine weitere Kiste oben}
      		else
      		begin {weitere Kisten oben}
      			p1 := ioKiste;
      			p2 := ioKiste;
      			if (p1^.up <> nil) then {nach oben laufen}
      			begin 
      				while (p1^.up <> nil) do
      				begin
      					p2 := p1;
      					p1 := p1^.up;
      				end; {while}
      			end; {nach oben laufen}
      			dispose(p1);
      			p1 := ioKiste;
      			p2 := ioKiste;
      		end {else weitere Kisten oben}
      	end {else Prüfung für weitere Stapel}
      end {if leere Kiste}
    end; {procedure}
    


  • Was ich bei dir generell noch nicht verstanden habe, ist, was eigentlich exakt die Aufgabe der Funktionen ist. Was bedeutet "entfernt das letzte Element eines gesuchten Stapels"? Wieso hat remove diesen inName-Parameter? Wenn remove das letzte Element entfernen soll, dann sollte es nur genau das tun. Was ist ein "Stapel"? Wenn ich das richtig verstehe, hast du doch eine verkettete Liste?

    Dann würde ich generell dazu raten, dass du zwei Dinge trennst:

    1. Die Node. Zum Beispiel so:
    type
      PNode = ^TNode;
      TNode = record
        up: PNode;
        next: PNode;
        name: String;
      end;
    

    Und dann separat dazu eine Klasse, die einen Head-Pointer hat und die Funktionen enthält:

    type
      TLinkedList = class
      private
         head: PNode;
      public
        constructor create;  // hier head auf nil initialisieren
        destructor destroy; // hier dann alle Nodes löschen
        procedure add_front(...);
        function pop_front: String;
        ...
      end;
    

    (Keine Garantie für die Syntax, habe schon lange kein Delphi mehr geschrieben)


Anmelden zum Antworten