Advanced Services | Kontrollstrukturen 1 |
if bzw. if/else ist die einfachste Kontrollstruktur. Mit ihr formuliert man eine wenn/dann Entscheidung. Wenn die im Booleschen Ausdruck formulierte Bedingung erfüllt ist (true), dann werden eine oder mehrere Anweisungen ausgeführt. Ist die Bedingung nicht erfüllt (false), so wird keine der Anweisungen ausgeführt.
if ( BoolescherAusdruck ) anweisung ;
if ( BoolescherAusdruck ) { anweisung1 ; anweisung2 ; // beliebig viele Anweisungen }
if ( BoolescherAusdruck ) anweisung1 ; // true-Zweig else anweisung2 ; // false-Zweig
if ( BoolescherAusdruck ) { anweisung1 ; anweisung2 ; // beliebig viele Anweisungen im true-Zweig } else { anweisung1 ; anweisung2 ; // beliebig viele Anweisungen im false-Zweig }
Ist bei der vollständigen Fallunterscheidung die Bedingung erfüllt, so wird der
true-Zweig abgearbeitet, ist die Bedingung nicht erfüllt wird der false-Zweig abgearbeitet.
Beispiele
if (temperatur < -10) Console.WriteLine("saukalt"); if (zahl%2 == 0) Console.WriteLine(zahl+" ist gerade"); else Console.WriteLine(zahl+" ist ungerade");
Die Grundstruktur von if/else ist nicht schwer, da diese jedoch beliebig tief verschachtelt werden kann, können damit sehr komplexe Strukturen aufgebaut werden. Zudem kann der boolesche Ausdruck, also die Bedingung, auch aus mehreren Teilaudrücken zusammengesetzt sein, sodaß auch dadurch schwierig zu durchschauende Abläufe entstehen können.
Am Anfang neigt man dazu, lieber öfters if einzusetzen statt eines vollständigen if/else . Es gibt Situationen, wo einem der Compiler darauf hinweist, daß hier ein logischer Unterschied besteht.
int a, abs ; a = Convert.ToInt32(Console.Readline()); if ( a < 0 ) abs = -a ; if ( a >= 0 ) abs = a ; Console.WriteLine("abs =" + abs);
Hier wird die Variable abs in Abhängigkeit von a belegt und es sieht auf den ersten Blick alles gut aus. Trotzdem erhält man beim compilieren die Fehlermeldung Variable abs might not have been initialized. Dagegen wird die folgende Variante vom Complier nicht beanstandet:
int a, abs ; a = Convert.ToInt32(Console.Readline()); if ( a < 0 ) abs = -a ; else abs = a ; Console.WriteLine("abs =" + abs);
Der Compiler prüft nicht die Bedingungen in if, sondern nur ob eine if-Anweisung logisch vollständig ist. Bei zwei unvollständigen if-Anweisungen kann es durchaus vorkommen, daß die Variable nicht für jeden Fall eine Wertzuweisung erhält, wie die folgende Variante zeigt, bei der b für den Fall, daß a den Wert 0 hat, nicht belegt ist.
int a, b ; a = Console.Readline(); if ( a < 0 ) b = -a ; if ( a > 0 ) b = a ;
verwendet man dagegen if/else, kann so ein Fehler nicht vorkommen.
Bei der Schachtelung von if/else muß man genau darauf achten, welches else zu welchem if gehört und dies durch Einrückung und/oder Klammerung deutlich machen.
if (a <= b) if (b <= c) max = c ; else // b > c max = b ; else // a > b if (c >= a) max = c ; else // c < a max = a ;
Dem Compiler ist es egal, ob man einrückt oder nicht. Er ordnet ein else immer dem nächsten
freien if zu, das er nach oben findet. Nach dieser Regel wird in obigem Beispiel das erste else dem
zweiten if zugeordnet und das zweite else dem dem ersten if und schließich das dritte else dem
dritten if. Will man diese Zuordnung verhindern, muß man Blockklammern setzen, was natürlich
im obigen Beispiel, das das Maximum von drei Zahlen a, b und c bestimmt, nicht sinnvoll ist.
Manchmal ist die automatische Zuordnung des Compilers nicht erwünscht. In diesem Fall setzt
man Blockklammern, um die beabsichtigte Zuordnung zu erreichen, also nicht so :
if ( monat == 12 ) if ( temp > 15) Console.WriteLine("Sehr warm für Dezember") ; else Console.WriteLine("Der Weihnachtsmann kommt nicht") ;
sondern so
if ( monat == 12 ) { if ( temp > 15) Console.WriteLine("Sehr warm für Dezember") ; } else Console.WriteLine("Der Weihnachtsmann kommt nicht") ;
Ein beliebter Fehler sind else-Zweige, die der Compiler keinem if zuordnen kann (else without if). Oft entsteht dieser Fehler dadurch, daß die Blockklammern vergessen wurden. Im folgenden Beispiel ist der true-Zweig mit der ersten Anweiszung zu Ende. Die zweite Anweisung hat nichts mehr mit if zu tun, deswegen findet der Compiler zu else kein if.
if ( ... ) anweisung1 ; anweisung2 ; else anweisung3 ;
Richtig lautet es folgendermaßen
if ( ... ) { anweisung1 ; anweisung2 ; } else anweisung3 ;
Oft muß man else und if direkt hintereinander schachteln. Man erhält dadurch eine ganze Kette von else if Abfolgen.
if ( monat >=1 && monat < 4) Console.WriteLine("naß und kalt") ; else if (monat >=4 && monat < 6) Console.WriteLine("Frühling") ; else if (monat >=6 && monat < 9) Console.WriteLine("Sommer") ; else if (monat >=9 && monat < 12) Console.WriteLine("Herbst") ; else if (monat == 12) Console.WriteLine("Winter") ; else Console.WriteLine("mehr Monate gibt es nicht !") ;
In bestimmten Situationen kann man die else-if Kette ersetzen durch eine Mehrfachverzweigung mit switch.
Bei dieser Mehrfachverzweigung wird ein numerischer Ausdruck mit Konstanten verglichen. Wird eine Übereinstimmung gefunden, so wird die zur Konstanten gehörige Anweisung und sämtliche darauffolgenden Anweisungen ausgeführt. Die Konstanten stehen zwischen dem Schlüsselwort case und einem Doppelpunkt.
switch( numerischer_Ausdruck_oder_String ) { case konstante1 : anweisung ; weitere_anweisung ; break; case konstante2 : anweisung ; weitere_anweisung ; break; // beliebig viele case-Zweige // jede Konstante kann nur einmal vorkommen default : anweisung ; weitere_anweisung ; break; }
Einige wichtige Regeln zu switch
Einfache if/else Verzweigungen kann man oft sehr kurz mit Hilfe eines bedingten Ausdrucks formulieren.
Er hat die Form
BoolescherAusdruck ? trueAusdruck : falseAusdruck
Obwohl die Klammern nicht notwendig sind, setzt man sie wegen der Lesbarkeit gerne.
(BoolescherAusdruck) ? trueAusdruck : falseAusdruck
Da Ausdrücke in C# nicht als Anweisungen verwendet werden dürfen, muß der bedingte Ausdruck zugewiesen werden, also etwa so
var = BoolescherAusdruck ? trueAusdruck : falseAusdruck ;
Man kann den bedingten Ausdruck auch in einen Methodenaufruf stecken, aber da wird er ja auch einer
lokalen Variablen zugewiesen.
So kann man etwa die Bestimmung des Maximums zweier Zahlen
if (a < b) max = b; else max = a;
kürzer und eleganter auch so schreiben:
max = a < b ? b : a ;
Wie if/else, so kann auch der bedingte Ausdruck geschachtelt werden, hier als Beispiel die Bestimmunmg des Vorzeichens einer Zahl zuerst mit if/else, dann mit einem bedingten Ausdruck.
if (x < 0) sgn = -1; else if (x > 0) sgn = 1; else sgn = 0;
Und jetzt mit einem bedingtenm Ausdruck
sgn = x < 0 ? -1 : x > 0 ? 1 : 0 ;
Der bedingte Ausdruck wird mit Hilfe des ternären Operators ?: gebildet. Er steht auf der
zweitniedrigsten Prioritätsstufe.
Welche Typen ?
Wir betrachten noch einmal die am meisten verwendete Form
var = BoolescherAusdruck ? trueAusdruck : falseAusdruck ;
Folgendes gilt es zu beachten:
Beispiel:
Das erste Beispiel ist in Ordnung, das zweite nicht. Überlegen Sie, was falsch ist.
Wochentag zum Datum
Wann ist Ostern