Fallunterscheidung: Unterschied zwischen den Versionen
Marius (Diskussion | Beiträge) |
(→Lösung) |
||
(8 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
− | Eine Fallunterscheidung ist eine häufig in Programmiersprachen implementierte Kontrollstruktur, | + | Eine '''Fallunterscheidung''' ist eine häufig in [[Programmiersprache|Programmiersprachen]] implementierte [[Kontrollstruktur]]. Sie dient dazu, das Notieren von verschiedenen [[Alternative|bedingten Anweisungen]] zu erleichtern. Dabei springt der Programmfluss vom Kopf der Fallunterscheidung zu einem spezifizierten Fall und setzt von da an die Ausführung fort. |
− | In Java wird eine Fallunterscheidung durch das [[Schlüsselwort]] | + | In [[Java]] wird eine Fallunterscheidung durch das [[Schlüsselwort]] '''switch''' für den Kopf der Fallunterscheidung und '''case''' für die einzelnen Fälle deklariert. Da ein Fall nur eine Sprungmarke für den Programmfluss ist und ''keine'' sonstige Programmflusskontrolle vorgenommen wird, ist es speziell in diesen sogenannten '''switch-case'''-Anweisungsblöcken notwendig, mit der '''break'''-Anweisung manuell aus der Fallunterscheidung herauszuspringen, wenn man einen Fall abgearbeitet hat. |
= Syntaxdiagramm = | = Syntaxdiagramm = | ||
Zeile 7: | Zeile 7: | ||
[[Datei:switch_statement.png]] | [[Datei:switch_statement.png]] | ||
− | (Aktuell noch teilweise | + | (Aktuell noch teilweise fehlerhaft) |
= Verwendung = | = Verwendung = | ||
+ | |||
+ | '''Fallunterscheidungen''' werden verwendet, wenn man mehrere fest definierbare Fälle überprüfen möchte, anstatt eine Verschachtelung von [[Alternative|bedingten Anweisungen]] zu erstellen. | ||
+ | |||
+ | Das Wichtigste dabei ist, dass nur Konstanten als Fälle verwendet werden können. Zwei Variablen können also nicht miteinander verglichen werden. Da die eintretbaren Fälle diskret voneinander zu unterscheiden sein müssen, sind nur [[byte]], [[char]], [[short]], [[int]], [[String]] und [[Aufzählungskonstante]]n erlaubt. Man kann also keine Fallunterscheidungen für die [[Datentypen]] [[long]], [[float]] und [[double]] verwenden. | ||
+ | |||
== Kopf == | == Kopf == | ||
+ | |||
+ | Der '''Kopf''' besteht aus dem Schlüsselwort '''switch''', gefolgt von einem in Klammern notierten Term, über den die Fallunterscheidung getroffen werden soll. | ||
+ | |||
+ | <source lang="java"> | ||
+ | switch(x){ | ||
+ | // Rumpf | ||
+ | } | ||
+ | </source> | ||
== Rumpf == | == Rumpf == | ||
− | == break; == | + | Der '''Rumpf''' einer Fallunterscheidung wird durch einen [[Block]] eingeleitet. Im Rumpf können die einzelnen Fälle mit einer '''Sprungmarke''' markiert werden. Diese geschieht durch das Schlüsselwort '''case''', gefolgt von einem '''konstanten''' Wert, der für den entsprechenden Fall steht, und einem Doppelpunkt. |
+ | |||
+ | <source lang="java"> | ||
+ | switch(x){ | ||
+ | case 1: //... | ||
+ | case 2: //... | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Zusätzlich kann durch das Schlüsselwort '''default''' ein Standardfall deklariert werden, der ausgeführt werden soll, wenn kein anderer Fall passt. Dieser wird entsprechend meistens am Ende der Fallunterscheidung notiert: | ||
+ | |||
+ | <source lang="java"> | ||
+ | switch(x){ | ||
+ | case 1: //... | ||
+ | case 2: //... | ||
+ | default: //... | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | == break == | ||
+ | |||
+ | ===Problematik=== | ||
+ | |||
+ | Da die einzelnen '''case'''- und '''default'''-Schlüsselwörter nur Sprungmarken repräsentieren und '''keine Kontrollstruktur''' aufbauen, würde der Programmfluss nach Abarbeiten eines Falls in die nächste Zeile wandern und, ungeachtet der Sprungmarke oder des eingetretenen Falls, weiterarbeiten: | ||
+ | |||
+ | <source lang="java" title="Fallunterscheidung ohne break"> | ||
+ | switch(x){ | ||
+ | case 1: i++; | ||
+ | case 2: i++; | ||
+ | default: i++; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Hier würde also im Fall von ''x ist 1'' der Wert von '''i''' dreimal, im Fall von ''x ist 2'' der Wert von '''i''' zweimal und in allen anderen Fällen der Wert von '''i''' einmal erhöht werden. Dies ist in den meisten Fällen jedoch nicht gewünscht. | ||
+ | |||
+ | ===Lösung=== | ||
+ | |||
+ | Am Ende jeder Fallbehandlung bzw. vor der Sprungmarke eines nächsten Falles muss eine Anweisung mit dem Schlüsselwort '''break''' verwendet werden, um aus dem Rumpfblock der Fallunterscheidung herauszuspringen: | ||
+ | |||
+ | <source lang="java" title="Fallunterscheidung mit break"> | ||
+ | switch(wochentag){ | ||
+ | case 1: System.out.println("Montag"); | ||
+ | break; | ||
+ | case 2: System.out.println("Dienstag"); | ||
+ | break; | ||
+ | case 3: System.out.println("Mittwoch"); | ||
+ | break; | ||
+ | case 4: System.out.println("Donnerstag"); | ||
+ | break; | ||
+ | case 5: System.out.println("Freitag"); | ||
+ | break; | ||
+ | case 6: System.out.println("Samstag"); | ||
+ | break; | ||
+ | case 7: System.out.println("Sonntag"); | ||
+ | break; | ||
+ | default: System.out.println("Kein Wochentag"); | ||
+ | } | ||
+ | </source> | ||
+ | Die break-Anweisungen sorgen hier dafür, dass immer nur eine Anweisung ausgeführt wird, anstatt die Liste vom zutreffenden Fall bis zum Ende durchzulaufen. | ||
+ | |||
+ | |||
+ | Natürlich kann man sich diese Eigenschaft auch zunutze machen, um mehrere Fälle mit der gleichen Routine zu behandeln: | ||
+ | <source lang="java" title="Gleiche Ausgabe für mehrere Fälle"> | ||
+ | switch(monat){ | ||
+ | case 1: case 2: case 3: System.out.println("Erstes Quartal"); | ||
+ | break; | ||
+ | case 4: case 5: case 6: System.out.println("Zweites Quartal"); | ||
+ | break; | ||
+ | case 7: case 8: case 9: System.out.println("Drittes Quartal"); | ||
+ | break; | ||
+ | case 10: case 11: case 12: System.out.println("Viertes Quartal"); | ||
+ | break; | ||
+ | default: System.out.println("Kein Monat"); | ||
+ | } | ||
+ | </source> | ||
+ | Hier werden jeweils drei Fälle mit der gleichen Ausgabe behandelt, indem drei Sprungmarken die gleiche Codezeile markieren. | ||
+ | |||
+ | = Beispiel = | ||
+ | |||
+ | <source lang="java"> | ||
+ | int x; | ||
+ | int i = 0; | ||
+ | [...] | ||
+ | switch(x){ | ||
+ | case 2: i+=1; | ||
+ | case 3: i+=1; | ||
+ | break; | ||
+ | case 4: i+=1; | ||
+ | break; | ||
+ | default: i=10; | ||
+ | } | ||
+ | </source> | ||
+ | Wenn man davon ausgeht, dass die Variable i den Wert 0 bis zur Fallunterscheidung behält, wird, wenn x den Wert 2 hat, der Wert der Variablen i zweimal um 1 erhöht, da am Ende der Fallbehandlung case 2 kein '''break''' steht. Wenn sie hingegen den Wert 3 oder 4 hat, wird diese Anweisung jeweils nur einmal ausgeführt. Ist der Wert von x weder 2, 3 noch 4, so erhält i den Wert 10. | ||
− | = | + | =Verwendete Schlüsselwörter= |
*switch | *switch | ||
*case | *case | ||
*break | *break |
Aktuelle Version vom 26. Juli 2016, 12:35 Uhr
Eine Fallunterscheidung ist eine häufig in Programmiersprachen implementierte Kontrollstruktur. Sie dient dazu, das Notieren von verschiedenen bedingten Anweisungen zu erleichtern. Dabei springt der Programmfluss vom Kopf der Fallunterscheidung zu einem spezifizierten Fall und setzt von da an die Ausführung fort.
In Java wird eine Fallunterscheidung durch das Schlüsselwort switch für den Kopf der Fallunterscheidung und case für die einzelnen Fälle deklariert. Da ein Fall nur eine Sprungmarke für den Programmfluss ist und keine sonstige Programmflusskontrolle vorgenommen wird, ist es speziell in diesen sogenannten switch-case-Anweisungsblöcken notwendig, mit der break-Anweisung manuell aus der Fallunterscheidung herauszuspringen, wenn man einen Fall abgearbeitet hat.
Inhaltsverzeichnis
Syntaxdiagramm
(Aktuell noch teilweise fehlerhaft)
Verwendung
Fallunterscheidungen werden verwendet, wenn man mehrere fest definierbare Fälle überprüfen möchte, anstatt eine Verschachtelung von bedingten Anweisungen zu erstellen.
Das Wichtigste dabei ist, dass nur Konstanten als Fälle verwendet werden können. Zwei Variablen können also nicht miteinander verglichen werden. Da die eintretbaren Fälle diskret voneinander zu unterscheiden sein müssen, sind nur byte, char, short, int, String und Aufzählungskonstanten erlaubt. Man kann also keine Fallunterscheidungen für die Datentypen long, float und double verwenden.
Kopf
Der Kopf besteht aus dem Schlüsselwort switch, gefolgt von einem in Klammern notierten Term, über den die Fallunterscheidung getroffen werden soll.
switch(x){ // Rumpf }
Rumpf
Der Rumpf einer Fallunterscheidung wird durch einen Block eingeleitet. Im Rumpf können die einzelnen Fälle mit einer Sprungmarke markiert werden. Diese geschieht durch das Schlüsselwort case, gefolgt von einem konstanten Wert, der für den entsprechenden Fall steht, und einem Doppelpunkt.
switch(x){ case 1: //... case 2: //... }
Zusätzlich kann durch das Schlüsselwort default ein Standardfall deklariert werden, der ausgeführt werden soll, wenn kein anderer Fall passt. Dieser wird entsprechend meistens am Ende der Fallunterscheidung notiert:
switch(x){ case 1: //... case 2: //... default: //... }
break
Problematik
Da die einzelnen case- und default-Schlüsselwörter nur Sprungmarken repräsentieren und keine Kontrollstruktur aufbauen, würde der Programmfluss nach Abarbeiten eines Falls in die nächste Zeile wandern und, ungeachtet der Sprungmarke oder des eingetretenen Falls, weiterarbeiten:
switch(x){ case 1: i++; case 2: i++; default: i++; }
Hier würde also im Fall von x ist 1 der Wert von i dreimal, im Fall von x ist 2 der Wert von i zweimal und in allen anderen Fällen der Wert von i einmal erhöht werden. Dies ist in den meisten Fällen jedoch nicht gewünscht.
Lösung
Am Ende jeder Fallbehandlung bzw. vor der Sprungmarke eines nächsten Falles muss eine Anweisung mit dem Schlüsselwort break verwendet werden, um aus dem Rumpfblock der Fallunterscheidung herauszuspringen:
switch(wochentag){ case 1: System.out.println("Montag"); break; case 2: System.out.println("Dienstag"); break; case 3: System.out.println("Mittwoch"); break; case 4: System.out.println("Donnerstag"); break; case 5: System.out.println("Freitag"); break; case 6: System.out.println("Samstag"); break; case 7: System.out.println("Sonntag"); break; default: System.out.println("Kein Wochentag"); }
Die break-Anweisungen sorgen hier dafür, dass immer nur eine Anweisung ausgeführt wird, anstatt die Liste vom zutreffenden Fall bis zum Ende durchzulaufen.
Natürlich kann man sich diese Eigenschaft auch zunutze machen, um mehrere Fälle mit der gleichen Routine zu behandeln:
switch(monat){ case 1: case 2: case 3: System.out.println("Erstes Quartal"); break; case 4: case 5: case 6: System.out.println("Zweites Quartal"); break; case 7: case 8: case 9: System.out.println("Drittes Quartal"); break; case 10: case 11: case 12: System.out.println("Viertes Quartal"); break; default: System.out.println("Kein Monat"); }
Hier werden jeweils drei Fälle mit der gleichen Ausgabe behandelt, indem drei Sprungmarken die gleiche Codezeile markieren.
Beispiel
int x; int i = 0; [...] switch(x){ case 2: i+=1; case 3: i+=1; break; case 4: i+=1; break; default: i=10; }
Wenn man davon ausgeht, dass die Variable i den Wert 0 bis zur Fallunterscheidung behält, wird, wenn x den Wert 2 hat, der Wert der Variablen i zweimal um 1 erhöht, da am Ende der Fallbehandlung case 2 kein break steht. Wenn sie hingegen den Wert 3 oder 4 hat, wird diese Anweisung jeweils nur einmal ausgeführt. Ist der Wert von x weder 2, 3 noch 4, so erhält i den Wert 10.
Verwendete Schlüsselwörter
- switch
- case
- break