Langsam geht’s los, was? Nachfolgend werden wir bedingte Anweisungen1) behandeln. Was heißt das überhaupt? Naja, so eine Art "Wenn das, dann dies, sonst jenes…" und so ähnlich. Dafür gibt es Bedingungen, und wenn diese erfüllt werden, dann werden bestimmte Anweisungen ausgeführt, sonst wird etwas anderes ausgeführt.
Dafür gibt es in Java zwei Arten: Eine mit if … else
, die andere mit switch … case
.
Die Struktur dazu sieht so aus:
if (<Bedingung>) <Anweisung>
Mehrere nachfolgende Anweisungen2)
if (<Bedingung>) { <Anweisungsblock> }
oder mit einem sonst-Teil:
if (<Bedingung>) <Anweisung-if> else <Anweisung-else>
mit else und Anweisungen
if (<Bedingung>) { <Anweisung-if> } else { <Anweisung-else> }
Jetzt könnte man fragen: Wie entscheidet Java diesen Prozess? Wenn die Bedingung in den runden Klammern nach dem if
erfüllt wird, dann wird der Block { … }
– direkt unter dem if
– ausgeführt, ansonsten der Block { … }
nach dem else
. Wenn wir eine Struktur wie bei dem ersten Beispiel haben – d.h. kein else
Block – wird die Ausführung des Programms nach der schließenden geschweiften }
fortgesetzt. Dazu können wir den unten stehenden Code näher anschauen:
if (counter<10) { counter++; //gleichbedeutend: counter = counter + 1 System.out.println(counter); } System.out.println("Fertig");
Wenn die Variable counter
einen Wert kleiner 10 hat, werden die Befehle zwischen den geschweiften Klammer {
und}
ausgeführt. Wenn der Wert größer oder gleich 10 ist, wird dieser Block übersprungen und nach dem }
fortgesetzt. Das bedeutet, dass dann der Befehl System.out.println("Fertig");
ausgeführt wird.
Aber nicht missverstehen: Selbst wenn die Variable counter
einen Wert kleiner als 10 hat, wird – nachdem die Befehle im Block solange ausgeführt wurden, bis der Wert 10 erreicht hat - im Programm fortgesetzt, sprich: System.out.println("Fertig");
wird ausgeführt. Und wie sieht's aus, wenn man einen else
-Block hinzufügt? So wie oben, aber (natürlich) mit kleinen Unterschieden. Guck dir dazu die Beispiele an und führe sie aus. Dazu kannst du verschieden Zahlen eingeben und sehen, wie's funktioniert.
import Prog1Tools.IOTools; public class If1 { public static void main(String args[]) { int i = IOTools.readInteger("Gib eine Zahl i ein: "); if (i <= 10) { System.out.println("Das wird nur ausgeführt, wenn i <= 10 ist."); System.out.println("Oder man lässt den {...} Block weg,"); System.out.println("falls nur eine Anweisung darin ist (siehe If2)."); } System.out.println("Das wird immer ausgeführt."); } }
import Prog1Tools.IOTools; public class If2 { public static void main(String args[]) { int i = IOTools.readInteger("Gib eine Zahl i ein: "); if (i <= 10) System.out.println("Das wird nur ausgeführt, wenn i <= 10 ist."); System.out.println("Das wird immer ausgeführt."); } }
import Prog1Tools.IOTools; public class If3 { public static void main(String args[]) { int i = IOTools.readInteger("Gib eine Zahl i ein: "); if (i <= 10) System.out.println("Das wird nur ausgeführt, wenn i <= 10 ist."); else System.out.println("Das wird ausgeführt, wenn i > 10 ist."); System.out.println("Das wird immer ausgeführt."); } }
import Prog1Tools.IOTools; public class If4 { public static void main(String args[]) { int i = IOTools.readInteger("Gib eine Zahl i ein: "); if (i <= 10) { System.out.println("Das wird nur ausgeführt, wenn i <= 10 ist."); System.out.println("Ja, man kann {...} Blöcke auch im else Teil benutzen!"); } else System.out.println("Das wird ausgeführt, wenn i > 10 ist."); System.out.println("Das wird immer ausgeführt."); } }
import Prog1Tools.IOTools; public class If5 { public static void main(String args[]) { int i = IOTools.readInteger("Gib eine Zahl i ein: "); if (i <= 10) { System.out.println("Das wird nur ausgeführt, wenn i <= 10 ist."); System.out.println("Ja, man kann {...} Blöcke auch im else Teil benutzen!"); } else { System.out.println("Das wird ausgeführt, wenn i > 10 ist."); System.out.println("Siehste!"); } System.out.println("Das wird immer ausgeführt."); } }
Eine Empfehlung möchte ich an dieser Stelle jedoch noch loswerden:
Bitte macht (auch wenn es syntaktisch korrekt ist) dennoch die geschweiften Klammern! Damit werden Fehlerquellen drastisch minimiert!
So, wie bekomme ich jetzt
if
s innerhalb eines if
?
Auch das ist kein Problem, solange man nicht vergisst einen {..}-Block drumherum zu legen (wenn mehr als zwei Anweisungen darin sind).
Hier ist ein Beispiel:
if (i < 10) { System.out.println("i ist größer als 10."); if (j == 3) { // Gleichheit wird mit "==" überprüft! // "=" ist eine Zuweisung! (ist immer true) System.out.println("j ist 3."); } }
Jut, jut! Man kann auch if
innerhalb des {..}-Blocks nach dem else
benutzen. Warum probierst du es nicht einfach mal aus?
Java gibt uns gar die Möglichkeit Bedingungen zu kombinieren. Sagen wir, ein Verkäufer gilt als qualifiziert, wenn er mehr als 7000 Einheiten eines Produkts verkauft und mindestens 3 Jahre Berufserfahrung hat. Das ist das Beispiel:
if ((verkaufteProdukte > 7000) && (erfahrungsjahre >= 3)) { qualifiziert; }
Klar, das kann nicht ausgeführt werden. Es kommt im Moment nur darauf an, die logischen Operatoren &&
und ||
einzuführen.
&&
(und / Konjunktion) heißt, dass die Bedingungskombination nur zutrifft (also wahr ist), wenn beide Bedingungen zutreffen.
||
(oder / Disjunktion) heißt, dass mindestens eines der Bedingungen zutreffen muss, um die Anweisungen in dem {…}-Block ausführen zu können.
!
(nicht / Negation) heißt, dass nur bei nicht-Zutreffen der Bedingung der {…}-Block ausgeführt wird. Wenn also die Bedingung wahr (true
) ist, wird sie zu falsch (false
) und umgekehrt. Schau dir jetzt folgende Beispiele an:
import Prog1Tools.IOTools; public class If6 { public static void main(String args[]) { int i = IOTools.readInteger("Gib einen Wert für i ein: "); int j = IOTools.readInteger("Gib einen Wert für j ein: "); if ((i > 3) && (j>4)) { System.out.println("Das wird nur ausgeführt, wenn i>3 und j>4."); System.out.println("Jetzt ändere '&&' zu '||' um und benutze '!'."); } } }
import Prog1Tools.IOTools; public class If7 { public static void main(String args[]) { int i = IOTools.readInteger("Gib einen Wert für i ein: "); if (!(i > 3)) { System.out.println("Das wird ausgegeführt, wenn i NICHT größer als 3 ist."); System.out.println("Comprende?"); } } }
Wie sieht's aus, wenn wir mehr als 2 Anweisungen haben? Kein Problem! So wie in der Mathematik Punkt- vor Strichrechnung geht, so geht bei den boolschen Operatoren die Konjunktion (und) vor der Disjunktion (oder). Sonst muss man entsprechend einklammern - eingeklammerte Bedingungen werden dann zuerst ausgewertet. Folgendes Beispiel
import Prog1Tools.IOTools; public class If8 { public static void main(String args[]) { int i = IOTools.readInteger("Gib einen Wert für i ein: "); int j = IOTools.readInteger("Gib einen Wert für j ein: "); int k = IOTools.readInteger("Gib einen Wert für k ein: "); if ( ((i > 3) && (j > 4)) || (k > 5) ){ System.out.println("Treffer!!"); System.out.println("Jetzt ändere einmal die Klammerung!"); } } }
Bei Verzweigungen mit else
gibt es ein bekanntes Problem, das Dangling-Else-Problem genannt wird. Zu welcher Anweisung gehört das folgende else?
import Prog1Tools.IOTools; public class If9 { public static void main(String args[]) { int i = IOTools.readInteger("Gib einen Wert für i ein: "); int j = IOTools.readInteger("Gib einen Wert für j ein: "); if (i>3) if (j>4) System.out.println("Treffer!"); else System.out.println("Kann ich über i oder j eine Aussage treffen?"); } }
Die Einrückung suggeriert, dass das else
die Alternative zur ersten if
-Anweisung ist. Dies ist aber nicht richtig. Das else
gegört zum innersten if
. Daher lässt sich nur der Programmiertipp geben, die Blöcke der if
- und else
-Anweisungen zu klammern:
import Prog1Tools.IOTools; public class If10 { public static void main(String args[]) { int i = IOTools.readInteger("Gib einen Wert für i ein: "); int j = IOTools.readInteger("Gib einen Wert für j ein: "); if (i>3) { if (j>4) { System.out.println("Treffer!"); } else { System.out.println("Kann ich über i oder j eine Aussage treffen?"); } } } }
In einem Struktogramm wird eine Struktur "visualisiert".
So richtig wirksam werden Struktogramme, wenn man komplexere Algorithmen "überschaubar" formulieren will.
Rechts das Beispiel für die if
-Bedingung.
Ihr alle kennt schon Nassi-Shneidermann-Diagramme.
Für die Fallauswahl gibt es auch ein Diagramm. Hierzu sei nun ein Algorithmus mit diesem Diagramm gegeben:
Dieses Programm gibt eine Zeichenkette aus, die der eingegebenen Zensur (Zahl) entspricht. D.h. es wird die eingegebene Zahl überprüft:
…ausgegeben.
Schreibe dieses Programm nun mit Hilfe von Java und den bisher gelernten if
-Bedingungen; baue zusätzlich eine Sperre ein, die eine Fehlermeldung ausgibt, wenn die eingegebene Zahl größer als 6 oder kleiner als 1 ist.
Am Nassi-Shneidermann-Diagramm erkennt man, dass hiermit eine neue Regel mit einer neuen Syntax eingeführt wird: Die switch-case
-Anweisung.
Warum überhaupt eine switch-case
-Anweisung, die ja theoretisch völlig überflüssig ist, da es ja die if-else
-Anweisungen gibt.
Das erkennt man, wenn man obige Aufgabe mit switch-case
löst:
Praktisch gibt es in der Programmierung öfters Situationen oder Probleme, wo man eine Vielzahl von verschachtelten if-else
-Anweisungen brauchen würde (s.o.) und ein Programm kann dadurch schnell sehr unübersichtlich werden und unnötig lang.
Um diesen Aufwand zu umgehen oder zu vermindern, wurde die switch-case-Ablaufsteuerung in Java und anderen höheren Programmiersprachen eingeführt.
switch (ausdruck){ case ausdruck_1: anweisung_1; case ausdruck_2: anweisung_2; case ausdruck_3: anweisung_3; ... ... case ausdruck_n: anweisung_n; default: anweisungen }
Das sieht auf den ersten Blick ziemlich kompliziert aus, ist aber leichter als es scheint.
ausdruck
ist immer ein primitiver Datentyp, also eine Variable.
ausdruck
wird vollständig ausgewertet.case ausdruck_i
gefunden, dann wird bei dieser Anweisung die Abarbeitung fortgesetzt.break
-Anweisung unterbrechen (siehe letzter Punkt).default:
fortgefahren.default:
, wird der Anweisungsteil der switch
-Anweisung ignoriert.ausdruck
als auch die konstanten Ausdrücke müssen ganzzahlig (byte
, char
, short
oder int
) sein.case
- oder default
-Anweisung ist beliebig.switch
-Anweisung sofort verlassen.
long
, float
, double
) oder Objekte benutzt werden.if
- Anweisungen sind dagegen auf jede Art der Prüfung und auf jeden Datentyp anwendbar.
Schreibe nun das gleiche Programm nochmal3), benutze dieses Mal aber die switch-case
-Ablaufsteuerung.
Das sollte soweit reichen. Jetzt noch einige kleinere Übungen zum Rest der Seite…
Verständnisfragen:
noteInfo = 1
und noteMathe = 3
im folgenden Programmauszug ausgibt:if (noteInfo>2) System.out.println("Brauche mehr Erfahrung ..."); else { System.out.println("Ja, du hast´s drauf!"); System.out.println(); if (noteMathe >= 3) System.out.println("Ich würde aber bessere bevorzugen."); else System.out.println("Hervorragend!"); System.out.println("Gratulation!"); } System.out.println("Vielen Dank, dass du dieses Programm benutzt hast!");
Alter | Kommentar |
---|---|
< 2 | Du bist ein Baby! |
>= 2 und < 12 | Du bist ein Kind! |
>=12 und < 18 | Du bist ein Jugendlicher! |
>=18 und < 24 | Du bist ein junger Erwachsener! |
>=24 und < 40 | Du bist ein Erwachsener! |
>=40 und < 55 | Du bist im mittleren Alter! |
>=55 und < 65 | (eigener Kommentar) |
>=65 | (eigener Kommentar) |
6. Schreib ein Programm das den BMI4) ausrechnet.