2.9 Kontrollstrukturen
Es gibt sicherlich kein ernsthaftes Anwendungsprogramm, das ohne die Steuerung des Programmablaufs zur Laufzeit auskommt. Das Programm muss Entscheidungen treffen, die vom aktuellen Zustand oder den Benutzereingaben abhängen. Jede Programmiersprache kennt daher Kontrollstrukturen, um den Programmablauf der aktuellen Situation angepasst zu steuern. In diesem Abschnitt werden Sie alle Möglichkeiten kennenlernen – bis auf Schleifen, die im nächsten Abschnitt folgen.
2.9.1 Die If-Anweisung
Die If-Anweisung bietet sich an, wenn bestimmte Programmteile nur beim Eintreffen einer oder mehrerer Bedingungen ausgeführt werden sollen. Betrachten Sie dazu das folgende Beispiel:
' ...\Sprachsyntax\Kontrollstrukturen\Kontrollstrukturen.vb |
Option Strict On
Namespace Sprachsyntax
Module Kontrollstrukturen
...
Sub IfElse()
'Zahl im Bereich 0 <= intZufall <= 3 ermitteln
Dim intZufall As Int32 = Now.Millisecond Mod 4
'Zahl raten
Console.Write("Raten Sie eine Zahl zwischen 0 und 3:")
Dim intWahl As Int32 = Int32.Parse(Console.ReadLine())
If intWahl = intZufall Then
Console.WriteLine("Erraten!")
Else
Console.WriteLine("Korrekt wäre {0}", intZufall)
End If
Console.ReadLine()
End Sub
End Module
End Namespace
Der Millisekundenteil der aktuellen Zeit wird herangezogen, um eine »zufällige« Zahl zu erzeugen. Dann soll der Benutzer die Zahl erraten. ReadLine liest eine mit einem Zeilenvorschub abgeschlossene Textzeile ein, die von der Funktion Parse in eine Zahl umgewandelt wird. Wenn die Zahl erraten wurde, ist intWahl = intZufall wahr, und "Erraten!" wird ausgegeben. Sonst wird im Else-Zweig die zu erratende Zahl ausgegeben.
Kernkonstrukt der Überprüfung ist die If-Struktur mit folgender Syntax. Jeder ElseIf- und der Else-Zweig sind optional, was durch die eckigen Klammern kenntlich gemacht wird. Kursive Teile müssen Sie Ihren Bedürfnissen anpassen.
If <Bedingung1> Then |
Beim Eintritt in die Bedingungsstruktur wird zunächst die Bedingung1 geprüft. Ist deren Aussage wahr (True), werden alle Anweisungen ausgeführt bis zum nächsten Abschnitt, der mit ElseIf, Else oder End If anfängt. Ist Bedingung1 falsch (False), wird, wenn vorhanden, im ElseIf-Zweig mit Bedingung2 analog verfahren. Sollten alle folgenden Bedingungen falsch sein oder sollte kein einziger ElseIf-Zweig existieren, wird, wenn vorhanden, der Else-Zweig ausgeführt. Es wird maximal einer (gegebenenfalls keiner) der Zweige ausgeführt. Egal, welcher ausgeführt wird, das Programm fährt mit der nächsten Anweisung nach dem End If fort.
Eine If-Bedingung ohne ElseIf kann auch in einer Zeile geschrieben werden. Auch ihr Else-Zweig ist optional. Anstatt einer einzelnen Anweisung kann auch eine Sequenz von Anweisungen folgen, die durch Doppelpunkte voneinander getrennt sind. Der Einzeiler hat kein End If (auch hier müssen Sie kursive Teile Ihren Bedürfnissen anpassen).
If <Bedingung> Then <Anweisung1> [Else <Anweisung2>] |
Für die Bedingungen stehen alle Möglichkeiten zur Verfügung, die in den Abschnitten 2.7.2, »Relationale Operatoren«, und 2.7.3, »Logische Operatoren«, beschrieben sind.
If-Anweisungen dürfen beliebig verschachtelt werden. Dazu wird ein If-Block vollständig in einen anderen eingebettet. Das folgende Beispielprogramm demonstriert diese Technik. Dazu wird das letzte Beispiel etwas erweitert:
' ...\Sprachsyntax\Kontrollstrukturen\Kontrollstrukturen.vb |
Option Strict On
Namespace Sprachsyntax
Module Kontrollstrukturen
...
Sub IfElseIf ()
'Zahl im Bereich 0 <= intZufall <= 3 ermitteln
Dim intZufall As Int32 = Now.Millisecond Mod 4
'Zahl raten
Console.Write("Raten Sie eine Zahl zwischen 0 und 3:")
Dim intWahl As Int32 = Int32.Parse(Console.ReadLine())
If intWahl = intZufall Then
Console.WriteLine("Erraten!")
Else
If intWahl < intZufall Then
Console.Write("Zu klein: ")
Else
Console.Write("Zu gross: ")
End If
Console.WriteLine("korrekt wäre {0}", intZufall)
Else
Console.WriteLine("Nicht zwischen 0 und 3!")
End If
Console.ReadLine()
End Sub
End Module
End Namespace
2.9.2 Select-Case-Anweisung
Im Prinzip kann mit der If-Struktur jede Art von Bedingungen geprüft werden. Soll ein einzelner Ausdruck gegen gewisse Werte oder Wertebereiche getestet werden, bietet die Select-Case-Anweisung jedoch eine elegantere Möglichkeit. Sie hat folgende allgemeine Struktur (optionale Teile stehen wieder in eckigen Klammern, Alternativen sind durch | getrennt, kursive Teile müssen Sie Ihren Bedürfnissen anpassen):
Select [Case] <Ausdruck> |
Hinter Select Case wird der Ausdruck angegeben, der überprüft werden soll. Für jedes in Frage kommende Ergebnis der Prüfung wird ein eigener Case-Zweig angegeben. Entspricht der Inhalt des Testausdrucks dem der Angabe hinter Case, werden alle Anweisungen bis zum nächsten Case (oder End Select) ausgeführt. Danach wird das Programm hinter dem blockschließenden End Select fortgesetzt. Die Case Else-Anweisungen werden genau dann ausgeführt, wenn kein zutreffender Ausdruck in den Case-Zweigen vorher gefunden wird.
Zur Demonstration der Fallunterscheidungen mit Select-Case formulieren wir das letzte Beispiel um. Es könnte eleganter formuliert werden, würde dann aber nicht alle Fälle zeigen.
' ...\Sprachsyntax\Kontrollstrukturen\Kontrollstrukturen.vb |
Option Strict On
Namespace Sprachsyntax
Module Kontrollstrukturen
...
Sub SelectCase()
'Zahl im Bereich 0 <= intZufall <= 3 ermitteln
Dim intZufall As Int32 = Now.Millisecond Mod 4
'Zahl raten
Console.Write("Raten Sie eine Zahl zwischen 0 und 3:")
Dim intWahl As Int32 = Int32.Parse(Console.ReadLine())
Select Case intWahl
Case intZufall
Console.WriteLine("Erraten!")
Case 0 To 3
Select Case intWahl
Case Is < intZufall
Console.Write("Zu klein: ")
Case Is > intZufall
Console.Write("Zu gross: ")
End Select
Console.WriteLine("korrekt wäre {0}", intZufall)
Case Else
Console.WriteLine("Nicht zwischen 0 und 3!")
End Select
Console.ReadLine()
End Sub
End Module
End Namespace
Die Werte in den Case-Zweigen müssen nicht ganze Zahlen sein. Das nächste Codefragment zeigt, dass selbst String-Bereiche möglich sind. Die Kommentare geben an, für welche Einstellung von Option Compare der jeweilige Zweig angesprochen wird.
' ...\Sprachsyntax\Kontrollstrukturen\Kontrollstrukturen.vb |
Option Strict On
Option Compare Binary
Namespace Sprachsyntax
Module Kontrollstrukturen
...
Sub SelectCaseTo()
Select Case 0.2
Case 0 To 0.5
Console.WriteLine("Kleiner 1/2.")
End Select
Select Case "Mein"
Case "dein" To "sein"
Console.WriteLine("dein To sein") 'Text
Case "Dein" To "Sein"
Console.WriteLine("Dein To Sein") 'Binary
End Select
Console.ReadLine()
End Sub
End Module
End Namespace
Anstatt eines einzelnen Wertes kann auch eine Sequenz von Werten angegeben werden. Die Ausgabe des nächsten Codefragments, "A, G", zeigt, dass der erste positiv getestete Zweig einer Select-Struktur angesprochen wird.
' ...\Sprachsyntax\Kontrollstrukturen\Kontrollstrukturen.vb |
Option Strict On
Namespace Sprachsyntax
Module Kontrollstrukturen
...
Sub SelectCaseAufzaehlung()
Select Case "G"
Case "A", "G"
Console.WriteLine("A, G") 'dieser
Case "G"
Console.WriteLine("G")
End Select
Console.ReadLine()
End Sub
End Module
End Namespace
2.9.3 Gültigkeitsbereich einer Variablendeklaration
Variablen, die in einer If- oder Select-Case-Kontrollstruktur deklariert werden, sind nur innerhalb der Kontrollstruktur bekannt. Jeder Zugriff außerhalb der Kontrollstruktur erzeugt einen Compilerfehler. Auch ist eine Deklaration derselben Variablen in der gleichen Prozedur untersagt. Die Fehler in den folgenden Zeilen treten analog in einer Select-Case-Anweisung auf:
If Now.Second > 30
Dim j, k As Integer
' Anweisungen
Next
j = 12 ' Compilerfehler!!
Dim k As Integer ' Compilerfehler!!
2.9.4 Entscheidungsfunktionen
Oft möchte man aufgrund einer Bedingung einen Wert wählen und diesen direkt verwenden, zum Beispiel IIf(Now.Hour<13, "vor", "nach").ToString() & "mittags". Für solche Aufgaben stellt Visual Basic drei Funktionen bereit, die alle Object als Rückgabetyp haben. Ebenso sind alle Parameter außer Ausdruck und Index vom Typ Object (kursive Teile müssen Sie Ihren Bedürfnissen anpassen).
- IIf(<Ausdruck>, <True-Parameter>, <False-Parameter>) Wenn der Ausdruck wahr (True) ist, wird der True-Parameter zurückgegeben, sonst der False-Parameter.
- Choose(<Index>,<Wahl 1> [,<Wahl 2>,...,[<Wahl n>)]]) Es wird der Parameter Wahl Index zurückgegeben. Wenn kein zu Index passender Parameter existiert, ist das Ergebnis Nothing.
- Microsoft.VisualBasic.Switch( _ <Ausdruck 1>, <True-Parameter 1> [, ... <Ausdruck n>, <True-Parameter n>)]) Der True-Parameter hinter dem ersten Ausdruck, der wahr ist (True), wird zurückgegeben. Ist kein Ausdruck wahr, ist das Ergebnis Nothing.
Da alle diese Konstrukte Funktionen sind, werden immer alle ihre Parameter ausgewertet. Das nächste Codefragment definiert Funktionen für wahr und falsch, die, wenn sie ausgewertet werden, eine Ausgabe erzeugen.
' ...\Sprachsyntax\Kontrollstrukturen\Kontrollstrukturen.vb |
Option Strict On
Namespace Sprachsyntax
Module Kontrollstrukturen
...
Function Nein() As Boolean
Console.Write("falsch ")
Return False
End Function
Function Ja() As Boolean
Console.Write("wahr ")
Return True
End Function
Sub KontrolleDurchFunktionen()
If True Then Ja() Else Nein()
Console.WriteLine("If Null")
Console.WriteLine("IIf {0}", IIf(True, Ja(), Nein()))
Console.WriteLine("Switch {0}", _
Microsoft.VisualBasic.Switch(False, Nein(), True, Ja()))
Console.WriteLine("Choose {0}", Choose(2, Nein(), Ja()))
Console.ReadLine()
End Sub
End Module
End Namespace
Die Ausgabe bestätigt, dass alle Parameter der Entscheidungsfunktionen ausgewertet werden:
wahr If Null
wahr falsch IIf True
falsch wahr Switch True
falsch wahr Choose True
Hinweis |
Die Entscheidungsfunktionen werten alle ihre Parameter aus und sind daher ungeeignet für Fälle, in denen nicht gebrauchte Zweige nicht ausgeführt werden dürfen, zum Beispiel um eine Division durch null zu vermeiden. |
2.9.5 If-Operator
In Visual Basic 2008 gibt es einen If-Operator, der wie die IIf-Funktion des vorigen Abschnitts einen Wert zurückliefert, jedoch seine Argumente wie das If-Else-End If-Konstrukt auswertet: Nur ein Zweig wird ausgeführt (kursive Teile müssen Sie Ihren Bedürfnissen anpassen).
If(<Bedingung>, <Wahr-Zweig>, <Falsch-Zweig>) |
Das folgende Codefragment testet die einfache Auswertung und benutzt den Rückgabewert für eine Variablenzuweisung:
' ...\Sprachsyntax\Kontrollstrukturen\Kontrollstrukturen.vb |
Option Strict On
Namespace Sprachsyntax
Module Kontrollstrukturen
...
Function Nein() As Boolean
Console.Write("falsch ")
Return False
End Function
Function Ja() As Boolean
Console.Write("wahr ")
Return True
End Function
Sub IfOperator()
Console.WriteLine("If {0}", If(True, Ja(), Nein()))
Console.WriteLine("If {0}", If(False, Ja(), Nein()))
Dim int As Integer = 77 \ If(False, 0, 2)
Console.ReadLine()
End Sub
End Module
End Namespace
Die Ausgabe zeigt, dass nur der nötige Teil ausgewertet wird:
wahr If True
falsch If False
Es gibt noch eine Variante mit zwei Argumenten (kursive Teile müssen Sie Ihren Bedürfnissen anpassen):
If(<Wert1>, <Wert2>) |
die bis auf die nur einmalige Auswertung von Wert1 äquivalent ist zu:
If(<Wert1> IsNot Nothing, <Wert1>, <Wert2>) |
2.9.6 Bedingte Kompilierung
Bevor der Compiler seine Arbeit aufnimmt, verarbeitet ein Präprozessor den Quellcode. Dies ermöglicht es, Teile des Quellcodes, abhängig von Bedingungen, von der Kompilierung auszuschließen. Das Konstrukt ähnelt sehr stark der If-Anweisung und hat folgende Syntax (kursive Teile müssen Sie Ihren Bedürfnissen anpassen):
#If <Bedingung1> |
Die Anweisung, die in einer entsprechenden If-Anweisung ausgeführt würde, wird als Teil des Quellcodes kompiliert. Alle anderen Teile des #If-Konstrukts werden vom Compiler ignoriert, als wären sie gar nicht vorhanden.
Die Bedingungen dürfen mit #Const <Bezeichner> oder von der Entwicklungsumgebung definierte Konstanten und die Operatoren +, -, *, /, \, Mod, ^, =, <>, <, >, <=, >=, &, Not, And, Or, Xor, AndAlso, OrElse, << und >> enthalten.
Eine weitere Möglichkeit, Anweisungen in Abhängigkeit von Konstanten zu unterdrücken, bietet System.Diagnostics.ConditionalAttribute.
Wahrscheinlich werden Sie die Direktiven, wenn überhaupt, erst bei komplexeren Projekten brauchen, zum Beispiel um parallel verschiedene Versionen eines Programms zu pflegen.
2.9.7 Zusammenfassung
- Zur Prüfung von Bedingungen bietet sich zuerst die If-Anweisung an. Die zu prüfende Bedingung muss einen booleschen Wert zurückliefern.
- Mehrzeilige If-Anweisungen werden, im Gegensatz zur einzeiligen Variante, mit End If abgeschlossen.
- Anstelle einer aufwendig strukturierten If-Anweisung kann, wenn immer derselbe Ausdruck geprüft werden soll, alternativ ein Select-Case benutzt werden.
- Variablen, die in einer Kontrollstruktur deklariert werden, sind nur dort gültig. Eine weitere Variable in derselben Prozedur oder Funktion mit gleichem Namen ist verboten.
- Mit der Switch-, Choose- und IIf-Funktion stehen Alternativen zu If und Select-Case zur Verfügung. Sie erlauben einen kürzeren Code, werten aber alle ihre Teile immer aus.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.