Warum Goto und Gosub nur mit Vorsicht gebrauchen.
Verfasst: 16.10.2005 18:27
Warum man Goto und Gosub nicht benutzen soll, Sie aber trotzdem manchmal gebraucht werden.
Damals in den Anfangstagen der Basicprogrammierung war die Sprache Basic sehr Zeilenorientiert.
Man hat vor jeder Zeile eine Zeilenummer mitprogrammiert.
Diese Zeilennummer war dann wie eine Sprungmarke. Damit konnte man nun im Programm sagen das das Programm z.B. von Zeile 10 in die Zeile 30 Springen soll und da weitermachen soll.
Man hat die Zeilen in 10er Schritten Nummeriert um Später Zeilen einfügen zu können.
Auch PureBasic bietet so etwas wie Sprungmarken an.
Eine Sprungmarke ist einfach ein Wort mit einem Doppelpunkt am ende.
z.B. SpringeHierHin:
Wenn man jetzt nun die Zeile lZahl = 5 in lZahl = 4 oder lZahl = 1 ändert und das Programm ausführt, wird einem schnell klar, das man auf den Programmverlauf nach der Sprungmarke sehr gut aufpassen muss.
Wenn man einen sehr langen Quelltext hat, wird es für den Programmierer sehr sehr schwer, das hin und her gehüpfe, kreuz und quer durch den Quelltext zu verfolgen.
Das nennt man in der Fachsprache "Spagetticode" weil es nur sehr schwer zu verfolgen ist.
Schnell passieren Fehler, die in einer Endlosschleife oder gar zum Programmabsturz führen.
Bei Modernen Programmiersprachen, wie auch PureBasic, nutzt man Prozeduren oder Funktionen als Sprungmarken.
Diese Prozeduren oder Funktionen werden angesprungen, der dort enthaltene Code wird ausgeführt und das Programm geht automatisch an den Ort zurück von wo die Prozedur aufgerufen wurde.
Die Programmsteuerung ist also von vorne herein geregelt und leicht nachvollziehbar.
Deshalb sollte man die Proceduren nutzen, die auch noch mehrer andere vorteile haben in Bezug der Gültigkeit der Variablen und mehr.
Es gibt jedoch einen Vorteil den das Gespann aus Goto und Sprungmarke hat.
Eine Sprungmarke ist beim Programmablauf eine Speicheradresse in die das Programm sehr leicht springen kann ohne vorher zu suchen.
Das Gespann aus Goto und Sprungmarke ist also schneller als ein Sprung zu einer Prozedur und wieder zurück.
Bei sehr Zeitkritischen schnellen Operationen kann man Goto und Sprungmarke nutzen.
Wenn aber aus irgendwelchen Gründen die Sprungmarke (Speicheradresse) falsch oder Ungültig ist dann springt das Goto ins ungewisse!!!!!!!!!!
Gosub, Return und FakeReturn
Gosub ist eine Abkürzung für 'Go to sub routine', es ist also auch ein Goto das weiterentwickelt wurde. Nach Gosub muss auch eine Sprungmarke angegeben werden.
Ist im Programm ein Gosub, so merkt sich das Progamm im Stack die Speicheradresse, von der Stelle wo das Gosub steht (die Adresse wird auf den Stack gelegt, Stack = Spezieller Speicher der sich Sachen merkt).
Nun kann man später an diese stelle wieder zurückkehren, weil man sich die Adresse gemerkt hat.
Dann wird die Programmausführung ab der Sprungmarke weitergeführt, bis ein Return auftaucht. Return heißt soviel wie: Kehre zu der stelle zurück an der das Gosub stand (die stellen haben wir uns im Stack gemerkt).
Nach Return kann der Stack die gemerkte Adresse wieder „vergessen“.
Wenn also das Return erreicht wurde, wird die Programmausführung hinter dem aufrufenden Gosub fortgesetzt.
Genauso Funktionieren auch Proceduren! Proceduren sind aus mehreren gründen vorzuziehen!
Gosub ist aber nützlich, um einigermaßen strukturierten Code zu erstellen der in der Ausführung schnell ist.
Wenn Sie aus der Gosub-Routine mit dem Befehl Goto in einen anderen Programmteil außerhalb der Gosub-Routine springen möchten , müssen Sie FakeReturn benutzen, um ein Return zu simulieren, ohne es wirklich auszuführen (englisch Fake = gefälscht). Wenn Sie diesen Befehl nicht benutzen, wird Ihr Programm abstürzen. Diese Funktion sollte nutzlos sein, da ein ordentlich aufgebautes und strukturiertes Programm kein Goto benutzt.
In einem Programm das nur mit Goto und Gosub Programmiert ist sind alle Variablen Global und somit unsicher vor versehentlichen Veränderungen!
Weil Goto und Gosub so viele Nachteile haben, hat man die Funktionen und Proceduren entwickelt.
Die Prozeduren sind also eine Weiterentwicklung.
Wer sich Programmiertechnisch weiter entwickeln will, nutzt Prozeduren.
Proceduren haben gegenüber Goto und Gosub folgende Vorteile:
* Der Programmablauf ist Leichter nachvollziehbar
* die Variablen in Prozeduren und Programm haben ordentlich definierte Gültigkeitsbereiche
* Prozeduren haben definierte Übergabe- und Rückgabeschnittstellen (so wie DLL Libraries)
* Ein Fehlsprung im Speicher ist mit Prozeduren durch die Überprüfung beim Kompelieren nicht Möglich
Goto und Gosub sind schneller….
Damals in den Anfangstagen der Basicprogrammierung war die Sprache Basic sehr Zeilenorientiert.
Man hat vor jeder Zeile eine Zeilenummer mitprogrammiert.
Diese Zeilennummer war dann wie eine Sprungmarke. Damit konnte man nun im Programm sagen das das Programm z.B. von Zeile 10 in die Zeile 30 Springen soll und da weitermachen soll.
Code: Alles auswählen
10 if Zahl = 1 then goto 30
20 print "Zahl ist nicht 1 !!"
30 print "Zahl ist 1!!"
Code: Alles auswählen
10 if Zahl = 1 then goto 30
11 if Zahl = 2 then goto 31
20 print "Zahl ist nicht 1 und nicht 2!!"
30 print "Zahl ist 1!!"
31 print "Zahl ist 2!!"
Eine Sprungmarke ist einfach ein Wort mit einem Doppelpunkt am ende.
z.B. SpringeHierHin:
Code: Alles auswählen
If OpenConsole()
lZahl = 5
Select lZahl
Case 1
Goto Melde1
Case 2
Goto Melde2
Case 3
Goto Melde3
Case 4
Goto Melde4
Case 5
Goto Melde5
Case 6
Goto Melde6
Default
Goto MeldeNix
EndSelect
Melde1:
PrintN("Die Zahl ist 1!")
Melde2:
PrintN("Die Zahl ist 2!")
Melde3:
PrintN("Die Zahl ist 3!")
Melde4:
PrintN("Die Zahl ist 4!")
Melde5:
PrintN("Die Zahl ist 5!")
Goto ProgrammEnde
Melde6:
PrintN("Die Zahl ist 6!")
MeldeNix:
PrintN("Die Zahl wurde nicht gefunden!")
ProgrammEnde:
PrintN("....druecke Enter.....")
Input()
CloseConsole()
End
EndIf
Wenn man einen sehr langen Quelltext hat, wird es für den Programmierer sehr sehr schwer, das hin und her gehüpfe, kreuz und quer durch den Quelltext zu verfolgen.
Das nennt man in der Fachsprache "Spagetticode" weil es nur sehr schwer zu verfolgen ist.
Schnell passieren Fehler, die in einer Endlosschleife oder gar zum Programmabsturz führen.
Code: Alles auswählen
If OpenConsole()
Anfang:
lZahl = 1
Select lZahl
Case 1
Goto Melde1
Case 2
Goto Melde2
Case 3
Goto Melde3
Case 4
Goto Melde4
Case 5
Goto Melde5
Case 6
Goto Melde6
Default
Goto MeldeNix
EndSelect
Melde1:
PrintN("Die Zahl ist 1!")
Melde2:
PrintN("Die Zahl ist 2!")
Melde3:
PrintN("Die Zahl ist 3!")
Melde4:
PrintN("Die Zahl ist 4!")
Melde5:
PrintN("Die Zahl ist 5!")
Goto ProgrammEnde
Melde6:
PrintN("Die Zahl ist 6!")
MeldeNix:
PrintN("Die Zahl wurde nicht gefunden!")
ProgrammEnde:
PrintN("....druecke Enter.....")
Input()
Goto Anfang
CloseConsole()
End
EndIf
Diese Prozeduren oder Funktionen werden angesprungen, der dort enthaltene Code wird ausgeführt und das Programm geht automatisch an den Ort zurück von wo die Prozedur aufgerufen wurde.
Die Programmsteuerung ist also von vorne herein geregelt und leicht nachvollziehbar.
Code: Alles auswählen
Global lZahl1,lZahl2,lErgebnis
Procedure Rechne()
lErgebnis = lZahl1 + lZahl2
EndProcedure
If OpenConsole()
lZahl1 = 5
lZahl2 = 6
Rechne()
PrintN("Ergebnis = " + Str(lErgebnis))
PrintN("....druecke Enter.....")
Input()
EndIf
End
Es gibt jedoch einen Vorteil den das Gespann aus Goto und Sprungmarke hat.
Eine Sprungmarke ist beim Programmablauf eine Speicheradresse in die das Programm sehr leicht springen kann ohne vorher zu suchen.
Das Gespann aus Goto und Sprungmarke ist also schneller als ein Sprung zu einer Prozedur und wieder zurück.
Bei sehr Zeitkritischen schnellen Operationen kann man Goto und Sprungmarke nutzen.
Wenn aber aus irgendwelchen Gründen die Sprungmarke (Speicheradresse) falsch oder Ungültig ist dann springt das Goto ins ungewisse!!!!!!!!!!
Gosub, Return und FakeReturn
Gosub ist eine Abkürzung für 'Go to sub routine', es ist also auch ein Goto das weiterentwickelt wurde. Nach Gosub muss auch eine Sprungmarke angegeben werden.
Ist im Programm ein Gosub, so merkt sich das Progamm im Stack die Speicheradresse, von der Stelle wo das Gosub steht (die Adresse wird auf den Stack gelegt, Stack = Spezieller Speicher der sich Sachen merkt).
Nun kann man später an diese stelle wieder zurückkehren, weil man sich die Adresse gemerkt hat.
Dann wird die Programmausführung ab der Sprungmarke weitergeführt, bis ein Return auftaucht. Return heißt soviel wie: Kehre zu der stelle zurück an der das Gosub stand (die stellen haben wir uns im Stack gemerkt).
Nach Return kann der Stack die gemerkte Adresse wieder „vergessen“.
Wenn also das Return erreicht wurde, wird die Programmausführung hinter dem aufrufenden Gosub fortgesetzt.
Genauso Funktionieren auch Proceduren! Proceduren sind aus mehreren gründen vorzuziehen!
Gosub ist aber nützlich, um einigermaßen strukturierten Code zu erstellen der in der Ausführung schnell ist.
Code: Alles auswählen
a = 1
b = 2
Gosub ComplexOperation
PrintNumberN(a)
End
ComplexOperation:
a = b*2+a*3+(a+b)
a = a+a*a
Return
Wenn Sie aus der Gosub-Routine mit dem Befehl Goto in einen anderen Programmteil außerhalb der Gosub-Routine springen möchten , müssen Sie FakeReturn benutzen, um ein Return zu simulieren, ohne es wirklich auszuführen (englisch Fake = gefälscht). Wenn Sie diesen Befehl nicht benutzen, wird Ihr Programm abstürzen. Diese Funktion sollte nutzlos sein, da ein ordentlich aufgebautes und strukturiertes Programm kein Goto benutzt.
Code: Alles auswählen
Gosub SubRoutine1
SubRoutine1:
...
If a = 10
FakeReturn
Goto Main_Loop
EndIf
Return
Weil Goto und Gosub so viele Nachteile haben, hat man die Funktionen und Proceduren entwickelt.
Die Prozeduren sind also eine Weiterentwicklung.
Wer sich Programmiertechnisch weiter entwickeln will, nutzt Prozeduren.
Proceduren haben gegenüber Goto und Gosub folgende Vorteile:
* Der Programmablauf ist Leichter nachvollziehbar
* die Variablen in Prozeduren und Programm haben ordentlich definierte Gültigkeitsbereiche
* Prozeduren haben definierte Übergabe- und Rückgabeschnittstellen (so wie DLL Libraries)
* Ein Fehlsprung im Speicher ist mit Prozeduren durch die Überprüfung beim Kompelieren nicht Möglich
Goto und Gosub sind schneller….