User Tools

Site Tools


k10:k10.5:k10.5.5:start

10.5.5 GoTo

The following four chapters describe control structures, the use of which is controversially discussed:

  • GoTo Unconditional jump to a destination (-Label).
  • GoSub Call of a local subroutine.
  • On GoTo Calculated unconditional jump to a selected target (-Label).
  • On GoSub Calculated call of local subroutines.

As can be shown in the examples under consideration, there are many applications in which the above four statements can be replaced by other control structures. Or put it another way: The use of the four above statements is avoidable if you don't fear the complexity of the Gambas code, for example, to leave a triple For control structure in an orderly fashion under a particular condition.

10.5.5.1 GoTo syntax

The system switches to a target (-label) that is declared elsewhere in a procedure or function:

GoTo Label
…
Label:
  <Instruction(s)>

10.5.5.2 Notes on syntax

  • Label points here to a target for the GoTo statement. The target specification ends with a colon. You can use capital letters or a preceding underscore to make your destination (-label) stand out in a special way.
  • A label is always local to a function or procedure.
  • 'Label' in connection with the instruction' GoTo Label' should not be confused with the class label? chapter 16.1 Label!
  • GoTo and Label can be used to exit a control structure.However, GoTo and Label cannot be used to enter a control structure.

The GoTo in connection with the above statement must be distinguished from the method Editor. Goto (…) of the component Editor (gb. qt4. ext):

Editor1.GoTo(0, String.Len(Editor1.Lines[0].Text)) ' Place cursor at the end of the 1st line
Editor1.GoTo(Editor1.Lines.Count, String.Len(Editor1.Text)) ' Place cursor at end of text

The examples in the next section mainly show source code excerpts and are commented adequately.

10.5.5.3 Example 1

The statement' GoTo Label' is sometimes acceptable as ultima ratio. This is exactly when you want to leave two nested loops:

variant 1 - without using the' GoTo Label' instruction

Dim i, j As Integer 
Dim bBreak As Boolean 
 
For i = 0 To 10 
  For j = 0 To 10 
    ' The double loop should be exited as soon as i*j > 20
    If (i * j > 20) Then 
      bBreak = True 
      Break 
    Endif 
  Next ' j
  If bBreak = True Then Break 
Next ' i

You can only jump from the innermost loop with' Break'. Therefore, you must set a variable that also signals to the outer loop that it should also be exited. * The variable' bBreak' is only true if you jumped out of the inner loop and leave the outer loop. You have to decide for yourself whether the above source code is easy to read.

Variant 2 - Use of the' GoTo Label' instruction

Dim i, j As Integer 
 
For i = 0 To 10 
  For j = 0 To 10 
    If i * j > 20 Then GoTo LEAVEBOTH 
  Next 
Next 
 
LEAVEBOTH: 
<Instruction(s)>
'  more...

10.5.5.4 Example 2

An example of a task in which the GoTo statement can demonstrate its strength is the search in an N-dimensional array for a certain integer value - here in a two-dimensional integer[][][]-array.

Dim iN, iI, iX As Integer 
 
For iN = 0 To aArray.Max 
  For iI = 0 To aArray[iN].Max 
    If iX = aArray[iN][iI] Then GoTo _Found 
  Next 
Next 
 
_Found: 
' Here you can use iN and iI. The element was found if iN <= aArray. Max

Bild 1

Figure 10.5.5.4.1: Searching for an (integer) number in a 2-dimensional array

The complete project for example 2 can be found in the download area.

The only way in example 2 to dispense with the GoTo statement to jump from two nested For control structures when a certain condition is fulfilled is to use a flag:

Dim iN, iI As Integer 
Dim bBreak As Boolean = False 
 
For iN = 0 To aArray.Max 
  For iI = 0 To Array[iN].Max 
    If iX = aArray[iN][iI] Then 
      bBreak = True 
      Break 
    Endif 
  Next 
  If bBreak Then Break 
Next 

In my opinion, however, this is not a good solution because it is less legible and less efficient. For several nested loops, it is definitely more complicated. A similar problem occurs if, for example, you want to iterate over an N-dimensional array and N is only known at runtime. Since a For control structure can only be counted linearly, you need N nested For control structures. If N is not known at runtime, a dynamically allocated array of iterators can be used to build an N-dimensional For control structure using GoTo. This is required, for example, when generating all possible character strings with N characters from a certain alphabet, where N is selected by the user - as it is done with' brute forcing'.

Download

10.5.5 GoTo

In den folgenden vier Kapiteln werden Kontroll-Strukturen beschrieben, deren Verwendung kontrovers diskutiert wird:

  • GoTo Unbedingter Sprung zu einem Ziel(-Label).
  • GoSub Aufruf eines lokalen Unterprogramms.
  • On GoTo Berechneter unbedingter Sprung zu einem ausgewählten Ziel(-Label).
  • On GoSub Berechneter Aufruf lokaler Unterprogramme.

Wie in den betrachteten Beispielen noch gezeigt werden kann, gibt es viele Anwendungsfälle, in denen die o.a. vier Anweisungen durch andere Kontroll-Strukturen ersetzt werden können. Oder anders formuliert: Die Verwendung der vier o.a. Anweisungen ist vermeidbar, wenn Sie die Komplexität des Gambas-Code nicht schreckt, um zum Beispiel eine dreifache For-Kontroll-Struktur bei einer bestimmten Bedingung geordnet zu verlassen.

10.5.5.1 GoTo-Syntax

Es wird zu einem Ziel(-Label) gewechselt, das an einer anderen Stelle in einer Prozedur oder Funktion deklariert ist:

GoTo Label
…
Label:
  Anweisung(en)

10.5.5.2 Hinweise zur Syntax

  • Label zeigt hier auf ein Ziel für die GoTo-Anweisung. Die Ziel-Angabe endet mit einem Doppelpunkt. Sie können Ziel(-Label) durch die Schreibweise mit großen Buchstaben oder mit einem vorangestellten Unterstrich in besonderer Weise auffallend kennzeichnen.
  • Ein Label ist stets lokal zu einer Funktion oder Prozedur.
  • 'Label' im Zusammenhang mit der Anweisung 'GoTo Label' ist nicht zu verwechseln mit der Klasse Label → Kapitel 16.1 Label!
  • GoTo und Label können verwendet werden, um eine Kontroll-Struktur zu verlassen.
  • GoTo und Label können dagegen nicht verwendet werden, um in eine Kontroll-Struktur einzusteigen.

Das GoTo im Zusammenhang mit der o.a. Anweisung ist von der Methode Editor.Goto(…) der Komponente Editor (gb.qt4.ext) wohl zu unterscheiden:

Editor1.GoTo(0, String.Len(Editor1.Lines[0].Text)) ' Cursor an das Ende der 1.Zeile setzen
Editor1.GoTo(Editor1.Lines.Count, String.Len(Editor1.Text)) ' Cursor an das Textende setzen

Die Beispiele im nächsten Abschnitt zeigen vorwiegend Quelltext-Ausschnitte und werden hinreichend kommentiert.

10.5.5.3 Beispiel 1

Die Anweisung 'GoTo Label' ist in manchen Fällen als ultima ratio akzeptabel. Nämlich genau dann, wenn Sie zwei verschachtelte Schleifen verlassen möchten:

Variante 1 – ohne Verwendung der 'GoTo Label'-Anweisung

Dim i, j As Integer 
Dim bBreak As Boolean 
 
For i = 0 To 10 
  For j = 0 To 10 
    ' Die Doppel-Schleife soll verlassen werden, sobald i*j > 20 ist 
    If (i * j > 20) Then 
      bBreak = True 
      Break 
    Endif 
  Next ' j
  If bBreak = True Then Break 
Next ' i
  • Sie können über 'Break' nur aus der innersten Schleife springen. Also müssen Sie eine Variable setzen, die der äußeren Schleife ebenfalls signalisiert, dass auch diese verlassen werden soll.
  • Die Variable 'bBreak' ist nur dann True, wenn aus der inneren Schleife gesprungen wurde und damit auch die äußere Schleife verlassen wird. Ob der o.a Quelltext gut lesbar ist, müssen Sie für sich entscheiden.

Variante 2 – Einsatz der 'GoTo Label'-Anweisung

Dim i, j As Integer 
 
For i = 0 To 10 
  For j = 0 To 10 
    If i * j > 20 Then GoTo LEAVEBOTH 
  Next 
Next 
 
LEAVEBOTH: 
Anweisung(en)
 
' Hier geht es weiter...

10.5.5.4 Beispiel 2

Ein Beispiel für eine Aufgabe, bei der die GoTo-Anweisung ihre Stärke demonstrieren kann, ist die Suche in einem N-dimensionalen Array nach einem bestimmten Integer-Wert – hier in einem zwei-dimensionalen Integer[][]-Array.

Dim iN, iI, iX As Integer 
 
For iN = 0 To aArray.Max 
  For iI = 0 To aArray[iN].Max 
    If iX = aArray[iN][iI] Then GoTo _Found 
  Next 
Next 
 
_Found: 
' Hier kann man iN und iI verwenden. Gefunden wurde das Element, wenn iN <= aArray.Max

Bild 1

Abbildung 10.5.5.4.1: Suche nach einer (Integer-)Zahl in einem 2-dimensionalen Array

Das vollständige Projekt zum Beispiel 2 finden Sie im Download-Bereich.

Die einzige Möglichkeit im Beispiel 2 auf die GoTo-Anweisung zu verzichten, um bei Erfüllung einer bestimmten Bedingung aus zwei verschachtelten For-Kontroll-Strukturen zu springen, ist ein Flag:

Dim iN, iI As Integer 
Dim bBreak As Boolean = False 
 
For iN = 0 To aArray.Max 
  For iI = 0 To Array[iN].Max 
    If iX = aArray[iN][iI] Then 
      bBreak = True 
      Break 
    Endif 
  Next 
  If bBreak Then Break 
Next 

Diese Lösung ist aber m.E. nicht gut, denn sie ist zum einen weniger gut lesbar und zum anderen weniger effizient. Für mehrere verschachtelte Schleifen wird es auf jeden Fall komplizierter. Ein ähnliches Problem tritt auf, wenn Sie beispielsweise über ein N-dimensionales Array iterieren wollen und N nur zur Laufzeit bekannt ist. Da eine For-Kontroll-Struktur nur linear aufzählen kann, benötigt man N verschachtelte For-Kontroll-Strukturen. Wenn N zur Laufzeit nicht bekannt ist, kann man ein dynamisch alloziertes Array von Iteratoren verwenden und mittels GoTo eine N- dimensionale For-Kontrollstruktur aufbauen. Dies wird z.B. bei der Generierung aller möglichen Zeichenketten mit N Buchstaben aus einem bestimmten Alphabet benötigt, wobei N vom Benutzer ausgewählt wird – so wie es beim 'Brute Forcing' praktiziert wird.

Download

The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k10/k10.5/k10.5.5/start.txt · Last modified: 02.07.2018 (external edit)

Page Tools