Pascal Code lesen für Idioten. Wie lest Ihr Code und was kann ich besser machen?

Registriert
Nov. 2018
Beiträge
1
Hallo.



Ich bin neu hier und wende mich an euch, weil ich ein Informatik Studium (Fernuni) begonnen habe und doch Schwierigkeiten mit der Praxis aber scheinbar nicht mit der Theory habe. Mein Problem bezieht sich also auf das Programmieren selbst. Oft komme ich beim lesen des Codes komplett durcheinander und oder weiß nicht womit oder wie bzw. wo ich anfangen soll. Ich glaube mein Problem liegt daher in erster Linie daran das ich Probleme habe den Code zu lesen/Verstehen um ihn dann zu bearbeiten/ergänzen. Ich möchte euch gerne daher mal meine vorgehensweiße erklären und auch darauf hinweisen was mir daran schwerfällt und wo ich z.B dann nicht mehr weiterkomme. Als Beispiel nehme ich eine Aufgabe, die bereits ABGELAUFEN ist und die ich nicht geschafft habe. Wofür ich aber bereits eine Musterlösung bekam. Das drauf schauen auf die Musterlösung hilft mir aber in diesem Fall nicht, denn bei der nächsten Aufgabe schon stoße ich auf das gleiche Problem. Also die Aufgabe, die ich jetzt vorgebe ist bereits keine Aufgabe mehr die ich einzureichen habe und kann daher auch gerne gelöst bzw. teilgelöst werden. Mir ist nur wichtig das ich für mich den richtigen Weg finden kann.



Sortieren durch Einfügen ist ein für bereits teilweise sortierte Listen sehr effizientes Sortierverfahren.

Wir durchlaufen die Elemente einer Liste von vorne nach hinten. In jedem Schleifendurchlauf verschieben wir das aktuelle Element an die richtige Position im vorderen und bereits sortierten Teil der Liste. Durch diese Vorgehensweise vergrößert sich der bereits sortierte Teil der Liste in jedem Durchlauf um ein Element.

Als Beispiel eines Schleifendurchlaufs betrachten wir das folgende Bild. Das aktuelle Element mit dem Inhalt 3 wird in den vorderen Teil der Liste zwischen die Elemente mit den Werten 2 und 4 verschoben. Dadurch sind dann die ersten vier Elemente der Liste sortiert und wir betrachten im nächsten Durchlauf das Element mit dem Wert 1.



Hier fehlt leider eine Grafik. Die Grafik zeigt eine Zahlenfolge an 2,4,5,3,1,8 worin die ersten drei Zahlen (2,4,5) zu einem Sortierten Feld gehören und 3,1,8 somit zu einem unsortierten Feld. Ein Pfeil verweist von der 3 im Unsortierten Feld, zwischen den zahlen 2 und 4 im Sortierten Feld.​


In jedem Durchlauf existieren drei Fälle:



  • Das zu sortierende Element wird der neue Anfgang der Liste,
  • das zu sortierende Element darf bleiben wo es ist oder
  • wir durchsuchen die Liste bis wir die richtige neue Position gefunden haben.
Aufgabe: Implementieren Sie das Sortieren durch Einfügen für eine nicht-leere Liste natürlicher Zahlen, indem Sie den folgenden Programmcode geeignet ergänzen. Sie sollen dafür die Elemente umhängen, keinesfalls sollen Sie Werte kopieren oder überschreiben.



Code:
{$R+}

{$B+}

program TesteSortiereListe(input, output);

{ sortiert eine Liste durch Einfügen }



type

tNatZahl = 0..maxint;

tRefListe = ^tListe;

tListe = record

wert : tNatZahl;

next : tRefListe;

end;



var

RefListe : tRefListe;



procedure SortiereListe (var ioRefListe : tRefListe);

{ sortiert eine nicht-leere lineare Liste aufsteigend }



var

EinfuegePosition,

WirdJetztSortiert,

IstSchonSortiert : tRefListe;

istEingefuegt : boolean;



begin

{ die einelementige Liste ist immer sortiert }

IstSchonSortiert := ioRefListe;

{ wir beginnen das zweite Element zu sortieren }

WirdJetztSortiert := ioRefListe^.next;

{ solange es noch etwas zu sortieren gibt }

while WirdJetztSortiert <> nil do

begin

istEingefuegt := false;



{ Fall 1: WirdJetztSortiert ist das neue kleinste Element }







{ Fall 2: WirdJetztSortiert bleibt wo es ist }







{ Fall 3: richtige EinfuegePosition im sortieten Teil suchen und verschieben }







WirdJetztSortiert := IstSchonSortiert^.next

end

end;



procedure Anhaengen(inZahl : tNatZahl; var ioListe : tRefListe);

{ Haengt inZahl an ioListe an }



var

Zeiger : tRefListe;



begin

Zeiger := ioListe;

if Zeiger = nil then

begin

new(ioListe);

ioListe^.wert := inZahl;

ioListe^.next := nil;

end

else

begin

while Zeiger^.next <> nil do

Zeiger := Zeiger^.next;

new(Zeiger^.next);

Zeiger := Zeiger^.next;

Zeiger^.wert := inZahl;

Zeiger^.next := nil;

end;

end;



procedure ListeEinlesen(var outListe:tRefListe);

{ liest eine Folge von Zahlen ein }



var

Liste : tRefListe;

Zahl : integer;



begin

Liste := nil;

read(Zahl);

while Zahl<>-1 do

begin

Anhaengen(Zahl, Liste);

read(Zahl)

end;

outListe := Liste

end;



procedure GibListeAus(inListe : tRefListe);

{ Gibt die eine nicht-leere Liste aus }



var

Zeiger : tRefListe;



begin

Zeiger := inListe;

write(Zeiger^.wert);

Zeiger := Zeiger^.next;

while Zeiger <> nil do

begin

write(', ');

write(Zeiger^.wert);

Zeiger := Zeiger^.next;

end;

writeln('')

end;



begin

ListeEinlesen(RefListe);

SortiereListe(RefListe);

GibListeAus(RefListe)

end.



So ich gehe wie folgt vor:

Ich mache mir kurz Gedanken über eine Lösung (ob das der Richtige Weg ist stellt sich beim probieren heraus):

  • Das zu sortierende Element wird der neue Anfang der Liste,
  • das zu sortierende Element darf bleiben wo es ist oder
  • wir durchsuchen die Liste bis wir die richtige neue Position gefunden haben.
Punkt 1: Kann man mit einem Zeiger verweis eventuell lösen.

Punkt 2: Anhand von einer if Anweisung wird geschaut ob das neue erste Element größer oder kleiner ist als das vorherige erste Element.

Punkt 3: sollte die neue erste Zahl größer sein so durchlaufen wir eine Schleife, die überprüft wo die nächst größerer Zahl liegt.



Das klingt für mich erstmal plausibel, auch wenn ich bislang keine Ahnung habe wie ich das realisieren kann.



Ich fange an den Code zu lesen von Oben nach unten!

Erstes was mir auffällt

{$R+}

{$B+}

gehört nicht zu Pascal :D. Scherz bei Seite.



kurze Anmerkung. Ich verbildliche mir manche Sachen. Type Variablen sind für mich Kartons mit unveränderbaren werten und Variablen sind Kartons mit immer veränderbaren werten. Die Größe der Kartons nimmt, mit dem zu was sie aufnehmen.



1. Ich schaue mir zuerst die Typen an und stelle fest, tNatZahl ist eine Type-Variable mit mehreren Wertebereiche/Felder, die nicht definiert sind. tRefListe ist eine Type-Variable die den Wert ^tListe erhält. Wohingegen ^tListe ein Verbund ist und folgende Unterwerte besitzt. Wert : tNatZahl und next : tRefListe. Wert sagt mir das hier drin jede Natürliche Zahl von 1 bis Maxint drin sein kann. next : tRefListe hingegen zeigt mir das hier ein Verweis auf die Type-Variable tRefListe gegeben wird. Dies wiederum führt dazu das jeder next Befehl eine neue Verbund Variable erschafft bzw mir die Möglichkeit gibt einen weiteren Zahlen-Wert in die Variable "Wert" hinein zu schreiben ohne dass der vorherige Wert überschrieben werden MUSS. Also bildlich dargestellt ist next : tRefListe nichts anderes als ein Karteikarten Spender.



2. Ich schau mir kurz die Variablen an. Ok, RefListe : tRefListe bekommt den Wert tRefListe und somit den ganzen Karteikarten Spender



3. Ich überspringe alle Prozeduren und Funktionen um sie erst zu lesen, wenn sie aufgerufen werden!



4. Unten im Begin/end Abteil beginne ich somit und sehe anfangen tut es mit einem Prozedur/Funktion Aufruf ListeEinlesen(RefListe). Also hoch zur Prozedur ListeEinlesen(RefListe) und diese lesen. Vorher aber kurz noch ein Blick auf ListeEinlesen(RefListe) werfen. Ein in der Funktion bzw Prozedur erreichter Wert wird in den Parameter RefListe gespeichert. Hier werde ich schon unsicherer, da ich nicht genau weiß, was und wie jetzt da etwas gespeichert wird. Es verwirrt mich etwas.



5. ListeEinlesen(RefListe) anschauen.

Zur Erinnerung:

Code:
procedure ListeEinlesen(var outListe:tRefListe);

{ liest eine Folge von Zahlen ein }



var

Liste : tRefListe;

Zahl : integer;



begin

Liste := nil;

read(Zahl);

while Zahl<>-1 do

begin

Anhaengen(Zahl, Liste);

read(Zahl)

end;

outListe := Liste

end;



Der Kommentar sagt das die Prozedur Zahlen einließt. Man kann davon ausgehen, dass sie dies auch tut dennoch schau ich nochmal drüber.

procedure ListeEinlesen(var outListe:tRefListe); var outListe bedeutet das der Wert auch außerhalb der Prozedur aufgerufen werden kann richtig? outListe bekommt wieder einmal den Karteikarten Spender.

Die Variable "Liste" bekommt den Wert der Karteikarten Spender. Zahl ist eine Deklarierte Integer Variable.

Als erstes wird die ganze Liste auf leer gesetzt (nil) dann wird soll eine Zahl eingegeben werden, die den eingegebenen Wert in die variable Zahl abspeichert. Woraufhin geschaut wird ob die eingebende Zahl ungleich -1 ist. Ist sie es wird die Funktion Anhaengen(Zahl, Liste); aufgerufen und nach der Liste wird wieder verlangt das eine Zahl eingeben wird. outListe := Liste kommt danach und ich muss zugeben es verwirrt mich etwas. Das mit den in, out, inout habe ich noch nicht so drauf. Ich gehe davon aus das outListe aufgerufen wird, wenn die zu vorige Schleife verlassen bzw. deren Bedingung erfüllt ist. outListe bekommt den Wert Liste zugewiesen und Out vermittelt, das dieser Wert übermittelt wird in den Parameter (RefListe) von der Prozedur ListeEinlesen(RefListe).

Wenn ich Falsch liege bitte korrigieren!



Gehen wir kurz nochmal in die Schleife, dort drin wurde eine Funktion aufgerufen.

Also, die Liste wird geleert es wird eine Zahl eingegeben und dann anhand einer While Schleife überprüft. Die Zahl enthält nicht den Wert -1 und läuft somit durch. Die Prozedur Anhaengen wird aufgerufen und bekommt zwei Parameter (Zahl, Liste). Also schauen wir jetzt mal bei der Prozedur Anhaengen nach.

Code:
procedure Anhaengen(inZahl : tNatZahl; var ioListe : tRefListe);

{ Haengt inZahl an ioListe an }



var

Zeiger : tRefListe;



begin

Zeiger := ioListe;

if Zeiger = nil then

begin

new(ioListe);

ioListe^.wert := inZahl;

ioListe^.next := nil;

end

else

begin

while Zeiger^.next <> nil do

Zeiger := Zeiger^.next;

new(Zeiger^.next);

Zeiger := Zeiger^.next;

Zeiger^.wert := inZahl;

Zeiger^.next := nil;

end;

end;



6. Dann mal auf ein Neues! Kommentar gelesen, dennoch überprüfen!

procedure Anhaengen(inZahl : tNatZahl; var ioListe : tRefListe); verstehe ich so: inZahl wird wieder eine natürliche Zahl von 0 bis Maxint. Und ioListe bekommt den Wert trefListe. Also ioListe ist wieder ein Karteikarten Spender. Aber er übernimmt keine Werte von der vorherigen Prozedur mit. Soweit richtig?



Dann kommt Variable "Zeiger" der bekommt die Karteikarten Spender Eigenschaft! Wenn ich nicht darüber nachdenken würde, dass jede Prozedur oder Funktion in sich abgeschlossen ist, würde mich (meine Vorstellungskraft) die ganzen Variablen mit diesen Karteikarten Spendern überfordern, aber zum Glück ist das Thema abgehakt sobald eine Prozedur oder Funktion endet.

Weiter gehts:

"Zeiger" der durch tRefListe bereits ein Karteikartenspender ist, bekommt jetzt alle Zahlen der ioListe übermittelt welche auch ein Karteikartenspender ist. Also nichts so zu sagen, soweit richtig? "Zeiger" wird hier ebenfalls gebraucht um die darauffolgende If-Anweißung starten zu können!

Jetzt wird geprüft durch If ob der Zeiger nil also 0 ist. Was er natürlich sein muss, weil wir nur Karteikarten Spender in Karteikarten Spender gesteckt haben obwohl alle Karteikarten leer sind.

Gehen wir davon aus die Anweisung (if) greift da Nil eintrifft! Es wird also begonnen mit dem Befehl new eine neue Karteikarte zu erstellt! ioListe^.wert := inZahl; sagt aus, dass, durch das (^), in der Liste "ioListe" der Eintrag "Wert" den Wert "inZahl" bekommt, welcher vorher in der Prozedur ListeEinlesen eingegeben wurde. Finde es gerade sehr kompliziert und verliere so schnell den Überblick hierbei.

Sobald die neue Karteikarte beschrieben ist, endet die Prozedur in gibt die Parameter Zahl also inZahl und Liste also ioListe wieder. Heißt in Parameter Zahl steckt jetzt die Zahl des Wertes der Karteikarte (ioListe^.wert := inZahl;) und in Liste steckt jetzt so zu sagen die new Karte, die angelegt wurde.



Sollte der Zeiger (die übernommene Karteikarten Spender Liste) nicht nil (0) sein, was bei einem zweiten Durchlauf der Schleife in ListeEinlesen der Fall ist, passiert folgendes. Es beginnt eine neue Schleife deren Bedingung es ist, dass der Zeiger verweis auf next ungleich nil (0) ist. Und der Zeiger next ist doch 0 denn er hatte keinen Wert zugewiesen bekommen.



Anmerkung: So etwas könnte ich selbst nicht schreiben. Ich würde gar nicht darauf kommen, while Zeiger^.next <> nil do so zu schreiben/verwenden. Denn wenn ich das verbildlichen würde, hätte ich schon irgendwo früher den Faden verloren! Es muss doch eine Möglichkeit geben, selbst auf so etwas zu kommen bzw zurück greifen zu können ohne sich erschlagen und ahnungslos zu fühlen.



Weiter! Next ist nil und die schleife greift. Die Variable Zeiger die eine Karteikarten Spender (ich nenne es vorsichtig Funktion) Funktion besitzt bekommt den Wert Zeiger^.next . Also den Wert Next, next verweist wieder auf tRefListe und tRefListe auf ^tListe und damit fängt es schon wieder von vorne an. Also sind wir wieder am Anfang einer neuen leeren Karte, Richtig?



Anmerkung, Ich habe so langsam den Überblick verloren, kann mir das Bildlich nicht mehr vorstellen irgendwie zu verworren.



Da wir wieder uns am Anfang befinden, müssen/können wir wieder neue Karteikarten einfügen. Was auch passiert mit dem Kommenden

new(Zeiger^.next); Befehl. new(Zeiger^.next); heißt das die nächste Karte bei dem variablen Zeiger mit dem Verweis (^) .next beginnt, sprich wieder ganz vorne an einer neuen Karte (siehe oben: next verweist wieder auf tRefListe und tRefListe auf ^tListe und damit fängt es schon wieder von vorne an.). Warum haben wir zuerst den Zeiger auf next also auf den Anfang zurückgesetzt, wenn wir sowieso eine neue Karte auf den Anfang setzen?



In den nächsten Zeilen:



Zeiger := Zeiger^.next;

Zeiger^.wert := inZahl;

Zeiger^.next := nil;



Wird erst wieder der Zeiger auf next gesetzt, wohlmöglich um zu verhindern das bei einen weiteren Schleifen Durchlauf der vorherige Wert überschrieben wird mit dem Befehl New. Was eigentlich Unsinn ist da schon beim ersten Zeiger := Zeiger^.next; direkt unter der Schleife dies verhindert wird. In Zeiger^.wert := inZahl; wird eine Zahl (Tippe auf die in der Vorherigen Eingabe in der Prozedur ListeEinlesen) in inZahl genauer in der Variable Zeiger mit dem Werweiß auf "Wert" geschrieben.

Zum Schluss wird der Zeiger genauer der Verweis next wieder auf nil (0) gesetzt um einen nächsten schleifendurchlauf zu gewährleisten.

Zusammen gefasst wird also in der Prozedur Anhaengen die Parameter Zahl, Liste die neuen Werte inZahl und ioListe angehangen.

(Ich weiß hier schon nicht mehr was genau das für Zahlen sein sollen/können)



7. im Teil Begin ganz am Anfang haben wir jetzt die erste Prozedur ListeEinlesen mit Ihrer Unterprozedur Anhaengen wie ich finde viel zu kompliziert und verwirrend abgearbeitet. Jetzt startet die eigentliche Aufgabe in dem nächsten Funktionsaufruf Sortierliste.



8. Die Sortierliste,

Code:
procedure SortiereListe (var ioRefListe : tRefListe);

{ sortiert eine nicht-leere lineare Liste aufsteigend }



var

EinfuegePosition,

WirdJetztSortiert,

IstSchonSortiert : tRefListe;

istEingefuegt : boolean;



begin

{ die einelementige Liste ist immer sortiert }

IstSchonSortiert := ioRefListe;

{ wir beginnen das zweite Element zu sortieren }

WirdJetztSortiert := ioRefListe^.next;

{ solange es noch etwas zu sortieren gibt }

while WirdJetztSortiert <> nil do

begin

istEingefuegt := false;



{ Fall 1: WirdJetztSortiert ist das neue kleinste Element }







{ Fall 2: WirdJetztSortiert bleibt wo es ist }







{ Fall 3: richtige EinfuegePosition im sortieten Teil suchen und verschieben }







WirdJetztSortiert := IstSchonSortiert^.next

end

end;



Anfangen tut es damit das wieder mit:

procedure SortiereListe (var ioRefListe : tRefListe); Also var ioRefliste ist eine Variable von der außerhalb und innerhalb der Prozedur/Funktion scheinbar zugegriffen werden kann, und diese Variable ist zudem ein Karteikarten Spender oder übernimmt die bislang gemachten Karteikarten?



Danach werden Variablen erstellt. IstSchonSortiert wird wieder ein Karteikarten Spender und istEingefuegt wird als eine Boolesche Variable deklariert.

Es fängt an indem die Variable "IstSchonSortiert" die bereits ein Karteikarten Spender ist die ioRefListe zugewiesen bekommt die ebenfalls ein Karteikarten Spender ist. Ich kann mich täuschen aber liegt diese ioRefListe nicht die inzwischen durch den ersten Prozeduraufruf erstellte fertige Liste außerhalb unserer derzeitigen Prozedur? Also werden bislang alle new Karten aus der Prozedur ListeEinlesen hier hineingebracht.



Jetzt wird das zweite Element sortiert. WirdJetztSortiert := ioRefListe^.next; hier wird WirdJetztSortiert die Variable ioRefListe mit dem Verweis auf Next zugewiesen. Somit kommt WirdJetztSortiert automatisch auf eine neue/nächste Karteikarte der Variable ioRefListe.



Bevor wir selbst anfangen können, beginnt eine While Schleife die dafür sorgt das WirdJetztSortiert ungleich nil (0) ist. Also wird sichergestellt, dass WirdJetztSoltiert wirklich bei einer neuen leeren karte anfängt.



Jetzt kommt unser Part und hier endet es auch leider schon! Die ganzen Prozeduren auseinander puzzeln und die dadurch entstandenen Zahlen, Variablen und das alles bringen mich komplett raus und hat sehr viel Zeit gekostet. Ich weiß weder wie ich anfangen soll noch was ich zuvor eigentlich gemacht habe. Es wirkt bildlich gesehen sowie drei große Haufen Merkzettel (stellen Prozeduren dar) die ich sehr langsam und schwer zusammengestellt habe, und die dann einfach wild zusammengeschoben werden. Ich verliere so zu sagen den kompletten Überblick. Daher meine Frage wie macht Ihr das mit Code lesen? Was mache ich Falsch oder kann ich besser machen? Ich möchte nicht vor so einer Aufgabe sitzen und keine Ahnung haben wie ich jetzt noch anfangen soll mit dem ganzen Wissen.



Ich hoffe Ihr könnt mich verstehen und mir helfen. Programmieren finde ich echt interessant und ich will es auch auf keinen Fall aufgeben, aber das ist gerade alles so niederschlagend und das soll sich ändern. Wie gesagt Theory scheint (laut meiner Punktanzahl) gut zu laufen. Aber Programmieren und damit den Code lesen und verstehen zu lernen ohne den Überblick zu verlieren :(.
 
Zuletzt bearbeitet:
Ich kann dir nur raten, such dir jemanden, der mehr Erfahrung hat bzw. es grundsätzlich besser versteht. Setz dich mit dem hin, geh das Programm (und/oder anderen Code) durch. Dabei aus meiner Sicht wichtig: DU erklärst ihm den Code... und er korrigiert dich dabei. Fallen dabei grundsätzliche Defizite beim Verständnis einiger Themen auf, werden die gezielt angegangen.

In deinem konkreten Fall oben geht es offensichtlich ums Sortieren. Dazu gibt es im Internet zu den diversen Sortieralgorithmen teils schöne und anschauliche grafische Darstellungen, wie sie arbeiten. Such dir was passendes raus und verstehe als erstes das Problem, dass mit dem Code gelöst werden soll.

Ansonsten, schreib selber Code. Such dir Einsteigerprogramme im Internet. Schreib die selber nach, bau Veränderungen ein und so weiter. Programmieren lernen, ohne selber Code zu schreiben, gelingt meiner Erfahrung nach nur den wenigstens Leuten.

Ergänzung:
Hab eben bemerkt, dass die Aufgabenstellung auch vorhanden ist. Da steht eigentlich alles drin, zumindest, um welches Problem es sich handelt. Hast du das denn zumindest verstanden? Hast du verstanden, dass du zwei Zahlen miteinander vergleichen sollst und je nachdem, was der Vergleich ergibt, die Position der Zahl in der Liste ggf. verändern sollst?

Themen, die man sich dazu geziehlt anschauen könnte: (einfach) verkettete Listen, Vergleich von Ganzzahlen (größer/kleiner/gleich).
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: areiland und psYcho-edgE
Und ohne Einrückungen ist das lesen gleich noch viel mehr Qual.

Und fremden Code lesen macht auch nicht wirklich Spass.
Ist seltsam, aber dein Code ist ungefähr gleich schlecht lesbar wie dein Post selbst.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Xenons
Ich wünschte ich könnte Pascal um dir zu helfen :p

Per se ist Insert Sort doch relativ einfach, nur macht mir der Code es schwer zu verstehen, was die einzelnen Funktionen und Prozeduren hier in diesem Fall so treiben.

Eine Idee: Versuche das Programm mal mit Pseudocode für dich selbst zu schreiben, also quasi eine Programmskizze zu erstellen. An dieser kannst du dich entlanghangeln und so dir sowohl die Stellen erklären, die dir prinzipiell bekannt sind als auch grobe Strukturfehler erkennen und ändern und Fehlendes ergänzen.
 
Zuletzt bearbeitet:
Programmiernoob schrieb:
Erstes was mir auffällt
{$R+}
{$B+}
gehört nicht zu Pascal :D. Scherz bei Seite.

Doch, das sind Compiler Schalter.
Nur um sicher zu gehen dass du das eh wusstest.
 
Zuletzt bearbeitet:
>Oft komme ich beim lesen des Codes komplett durcheinander und oder weiß nicht womit oder wie bzw. wo ich anfangen soll.

Code lesen vs. Code schreiben sind zwei paar Schuhe; Code lesen ist dabei wesentlich langsamer, als schreiben.

Mach dir erst selbst über die Problemlösung Gedanken: was für Infos (Daten) brauchst du, im das Problem anzugehen? Wie werden diese Daten manipuliert und wie sollen diese dann ausgeben/gespeichert werden? Ganz flach 08/15 EVA-Prinzip. Male ein Flussdiagramm (https://automatetheboringstuff.com/images/000100.jpg); das geht am schnellsten per Hand.

Dann geh in den Code. Verwende einen Editor mit Syntax-Highlighting und geh Zeile für Zeile mit einem Debugger durch (oder halt Schreibtischtest). Mach dir bewusst, wofür ein jeweiliger Teilschritt im Code geschieht; wie die Lösung eines Teilschrittes zur Lösung der Gesamtproblem weiterhilft.

Ich kann kein Pascal, aber Code (Scripts) mit 10+ Zeilen, die von oben nach unten nur so runtergerotzt wurden, Rekursion beinhalten und halt einfach scheiße sind, sind nun mal schwer zu lesen. Daher verwendet man Funktionen/Methoden. Darum strukturiert man Code ("Single Level of Abstraction"). Wie sonst, sollte man sich in einer Codebase zurechtfinden?

Zum Schluss: Programmieren lernt man nur durch selber programmieren. Mit der Zeit klappt das dann auch mit dem lesen etwas besser :)
 
Zuletzt bearbeitet: (url korrigiert)
  • Gefällt mir
Reaktionen: psYcho-edgE und areiland
Außerdem verwendet man auch einen Debbuger.
Setzt Breakpoints etc.

Und wenn möglich das gesamte Listing in 1 Fenster und strukturiert ohne x Leerzeilen.
Zumindest bei solchen Kleinigkeiten ohne fremde Libaries.

Verstehe gerade sowieso nicht warum der Code hier nicht eingerückt wird.
Mein Code wird eingerückt. Gerade getestet.
 
Zuletzt bearbeitet:
NPC schrieb:
Ich kann kein Pascal, aber Code (Scripts) mit 10+ Zeilen, die von oben nach unten nur so runtergerotzt wurden, Rekursion beinhalten und halt einfach scheiße sind, sind nun mal schwer zu lesen. Daher verwendet man Funktionen/Methoden. Darum strukturiert man Code ("Single Level of Abstraction"). Wie sonst, sollte man sich in einer Codebase zurechtfinden?

Naja, da sind schon Funktionen und Prozeduren drin, so isses nicht. Nur sieht es ohne Highlighting und vor allem ohne Einrückung halt schon sehr durcheinander aus.

@NPC Check nochmal den Link
 
Wie viele hier schon angemerkt haben, man sollte erstmal hingehen und den Code richtig formatieren.

Folgender Code ist der gleiche nur "korrekt" formatiert. (Nach meiner schreibweise)
Änderungen sind: Einrückungen und entfernung von leerzeilen sowie das hinzufügen von ;
Wichtig ist das in Pascal jede zeile mit einem ; abgeschlossen werden muss.
Der Compiler zeigt fehlende semikolons im Code an, aber leider nicht vor einem "end;" (hier sind sie leider "erlaubt") dennoch sollte man meiner Meinung nach bei jedem zeilenabschluss ein semikolon setzen da dadurch folgefehler direkt ausgeschlossen werden können.

Code:
{$R+}

{$B+}

program TesteSortiereListe(input, output);
{ sortiert eine Liste durch Einfügen }

type
  tNatZahl = 0..maxint;
  tRefListe = ^tListe;

tListe = record
    wert : tNatZahl;
    next : tRefListe;
end;

var
  RefListe : tRefListe;

{ sortiert eine nicht-leere lineare Liste aufsteigend }
procedure SortiereListe (var ioRefListe : tRefListe);
var
  EinfuegePosition, WirdJetztSortiert, IstSchonSortiert : tRefListe;
  istEingefuegt : boolean;
begin
  { die einelementige Liste ist immer sortiert }
  IstSchonSortiert := ioRefListe;

  { wir beginnen das zweite Element zu sortieren }
  WirdJetztSortiert := ioRefListe^.next;

  { solange es noch etwas zu sortieren gibt }
  while WirdJetztSortiert <> nil do begin
    istEingefuegt := false;
    { Fall 1: WirdJetztSortiert ist das neue kleinste Element }



    { Fall 2: WirdJetztSortiert bleibt wo es ist }



    { Fall 3: richtige EinfuegePosition im sortieten Teil suchen und verschieben }



    WirdJetztSortiert := IstSchonSortiert^.next;
  end;
end;
            
{ Haengt inZahl an ioListe an }
procedure Anhaengen(inZahl : tNatZahl; var ioListe : tRefListe);
var
  Zeiger : tRefListe;
begin
  Zeiger := ioListe;
  if Zeiger = nil then begin
    new(ioListe);
    ioListe^.wert := inZahl;
    ioListe^.next := nil;
  end
  else begin
    while Zeiger^.next <> nil do
      Zeiger := Zeiger^.next;

    new(Zeiger^.next);
    Zeiger := Zeiger^.next;
    Zeiger^.wert := inZahl;
    Zeiger^.next := nil;
  end;
end;
                  
{ liest eine Folge von Zahlen ein }
procedure ListeEinlesen(var outListe:tRefListe);
var
  Liste : tRefListe;
  Zahl : integer;
begin
  Liste := nil;
  read(Zahl);
  while Zahl<>-1 do begin
    Anhaengen(Zahl, Liste);
    read(Zahl);
  end;

  outListe := Liste;
end;
  
{ Gibt die eine nicht-leere Liste aus }
procedure GibListeAus(inListe : tRefListe);
var
  Zeiger : tRefListe;
begin
  Zeiger := inListe;
  write(Zeiger^.wert);
  Zeiger := Zeiger^.next;
  while Zeiger <> nil do begin
    write(', ');
    write(Zeiger^.wert);
    Zeiger := Zeiger^.next;
  end;

  writeln('');
end;

begin
  ListeEinlesen(RefListe);
  SortiereListe(RefListe);
  GibListeAus(RefListe);
end.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: cbtestarossa und psYcho-edgE
Zurück
Oben