Wenn ich ...

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.

if

Die Struktur dazu sieht so aus:

Eine nachfolgende Anweisung Einfach-Auswahl

    if (<Bedingung>) 
        <Anweisung>

Mehrere nachfolgende Anweisungen2)

    if (<Bedingung>) {
        <Anweisungsblock>
    }

oder mit einem sonst-Teil:

mit else Alternativ Auswahl

    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!

Verschachteltes if

Verschachtelte AuswahlSo, wie bekomme ich jetzt ifs 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?

Bedingungen kombinieren

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!");
        }
    }
}

Dangling-Else-Problem

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?");
            }
        }
    }
}

Darstellung der if-Bedingung in einem Struktogramm

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.

switch(...) ... case: ...

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:

Fallauswahl

Dieses Programm gibt eine Zeichenkette aus, die der eingegebenen Zensur (Zahl) entspricht. D.h. es wird die eingegebene Zahl überprüft:

  • Wenn sie 1 ist, wird "sehr gut"
  • Wenn sie 2 ist, wird "gut"
  • Wenn sie 3 ist, wird "befriedigend
  • Wenn sie 4 ist, wird "ausreichend"
  • Wenn sie 5 ist, wird "mangelhaft"
  • Wenn sie 6 ist, wird "ungenügend"
  • bei allen anderen Zahlen wird "ungültig"

…ausgegeben.

Aufgabe 1

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.

Die switch/case Ablaufsteuerung

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:

FIXME

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.

Struktur der switch/case Anweisung

Fallauswahl

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.

  • Der Ausdruck ausdruck wird vollständig ausgewertet.
  • Wir eine Übereinstimmung mit case ausdruck_i gefunden, dann wird bei dieser Anweisung die Abarbeitung fortgesetzt.
  • Achtung! Es werden bei Zutreffen eines case-Ausdrucks alle folgenden Anweisungen der restlichen case-Ausdrücke ebenfalls ausgeführt. Sollte dies nicht erwünscht sein, muss man den switch-case-Block mit der break-Anweisung unterbrechen (siehe letzter Punkt).
  • Wird keine Übereinstimmung gefunden, wird bei default: fortgefahren.
  • Gibt es kein default:, wird der Anweisungsteil der switch-Anweisung ignoriert.
  • Sowohl der Ausdruck ausdruck als auch die konstanten Ausdrücke müssen ganzzahlig (byte, char, short oder int) sein.
  • Die Reihenfolge der case- oder default-Anweisung ist beliebig.
  • Durch den Befehl break wird die switch-Anweisung sofort verlassen.


  • Es sind nur Vergleiche mit primitiven Datentypen möglich.
  • Es können keine größeren primitiven Typen (long, float, double) oder Objekte benutzt werden.
  • Es kann abgesehen von Gleichheit keine Beziehung geprüft werden. Verschachtelte if- Anweisungen sind dagegen auf jede Art der Prüfung und auf jeden Datentyp anwendbar.

Aufgabe 2

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…

Fragen

Verständnisfragen:

  1. Welche Möglichkeiten stehen in Java für Bedingte Verzweigung (conditional branching) zur Verfügung?
  2. Erkläre die einzelnen Syntaxen!
  3. Wie kann man verschachtelt verzweigen? Ist das erlaubt?
  4. Finde (ohne zu programmieren) heraus, was das Programm bei den Belegungen 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!");
  5. Schreib ein Programm, das nach dem Alter fragt. Unterscheide dabei folgende Kategorien:
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.

1) conditional branching
2) ein Anweisungsblock
3) kommt an die Stelle von FIXME (s.o.) ;-)
start/info/11if/05_ablaufsteuerung.txt · Zuletzt geändert: 13.04.2018 08:41 von epunkta
www.chimeric.de Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0