studyklar
GdI 2 · Übungsblatt 8 · Aufgabe 2

Taschenrechner: falsche Eingaben mit try-catch abfangen

Ein Taschenrechner für zwei Kommazahlen, der bei einem Tippfehler nicht abstürzt. Er meldet den Fehler und fragt noch einmal. Rechts steht das fertige Programm, die Zeilen zum aktuellen Schritt sind hervorgehoben. Mit Weiter geht es Schritt für Schritt voran.

Die Aufgabe

Aufgabe 2

Erstellen Sie ein Programm zur Berechnung der Summe, der Differenz, des Produktes und des Quotienten zweier Fließkommazahlen (double).

Es soll folgendermaßen funktionieren: Der Benutzer gibt auf der Konsole zunächst die erste Zahl ein, anschließend gibt er das Rechenzeichen (+, -, * oder /) ein, und schließlich die zweite Zahl. Dann gibt das Programm das Ergebnis der Berechnung aus.

Wird beim Eingeben einer der beiden Zahlen etwas Ungültiges eingegeben (z. B. Buchstaben oder ein Punkt anstatt eines Kommas als Dezimal-Trenner, wie es in der Konsole erforderlich ist), so wird der Benutzer darauf hingewiesen, und er kann die Zahl erneut eingeben.

Ebenso soll beim Einlesen des Rechenzeichens überprüft werden, ob es sich um eines der vier angegebenen Rechenzeichen handelt. Ansonsten wird auch hier auf die fehlerhafte Eingabe hingewiesen, und man kann das Rechenzeichen erneut eingeben.

Erstellen Sie für das Einlesen der Zahlen eine eigene Methode, in der überprüft wird, ob eine InputMismatchException geworfen wurde. Der Benutzer wird solange eine um eine erneute Eingabe gebeten, bis eine gültige Zahl eingegeben wurde.

Bei der Überprüfung der Rechenzeichen-Eingabe wird keine Exception benötigt.

Wichtig: Beachten Sie, dass Sie bei der Verwendung der Klasse Scanner nach dem Einlesen einer Zahl zunächst scanner.nextLine( ) aufgerufen werden muss, bevor man einen String einlesen kann. Am Besten machen Sie dies nach dem try-catch-Block (wenn Sie es direkt nach dem Einlesen der Zahl im Teil „try“ machen, müssen Sie es im catch-Teil auch noch einmal machen).

Testen Sie, ob Ihr Programm mit korrekten Eingaben und mit Fehleingaben richtig umgeht.

Das Programm liest eine Zahl, ein Rechenzeichen und noch eine Zahl ein und gibt das Ergebnis aus. Neu ist der Umgang mit falschen Eingaben. Tippt man bei einer Zahl abc oder 2.5 mit Punkt, bricht nextDouble mit einer Ausnahme (englisch Exception) ab. Eine Ausnahme ist eine Fehlermeldung, die Java während des Laufs auslöst. Diese Ausnahme soll das Programm abfangen und neu fragen.

Merke: Mit try und catch kann ein Programm auf eine Ausnahme reagieren, statt abzubrechen. Das heißt Ausnahmebehandlung.
  1. Eine Methode, die eine Zahl einliest und bei Fehlern wiederholt (try-catch).
  2. Eine Methode, die ein gültiges Rechenzeichen einliest (ohne Exception).
  3. Eine Methode, die rechnet, und main, die alles verbindet.
  4. Mit richtigen und falschen Eingaben testen.

Ein Scanner für alle Methoden

import java.util.InputMismatchException;import java.util.Scanner; public class Rechner {     private static Scanner scanner = new Scanner(System.in);

Das Programm liest an drei Stellen ein, in verschiedenen Methoden. Deshalb steht der Scanner nicht in main, sondern als Attribut der Klasse in Zeile 6. Er ist static wie die Methoden, die ihn benutzen. So greifen alle auf denselben Scanner zu.

Neu ist der zweite Import: InputMismatchException ist der Name der Ausnahme, die wir gleich abfangen. Sie liegt wie der Scanner im Paket java.util.

Aus Blatt 1, Aufgabe 1 („Lohnrechner: Eingabe mit Scanner und Runden auf zwei Stellen“): Scanner scanner = new Scanner(System.in); liest von der Tastatur, scanner.nextDouble() eine Kommazahl. Auf einem deutschen System erwartet sie das Komma: 2,5, nicht 2.5.
Aus Blatt 4, Aufgabe 2 („Lager für Quietsche-Enten: Bestand mit Methoden verwalten“): Ein static-Attribut gehört der Klasse; alle static-Methoden der Klasse können es benutzen.

Was bei einer falschen Eingabe passiert

    private static double liesZahlEin() {        double zahl = scanner.nextDouble();        scanner.nextLine();        return zahl;    }
Erste Zahl: abc
Exception in thread "main" java.util.InputMismatchException
	at java.base/java.util.Scanner.throwFor(Scanner.java:977)
	at java.base/java.util.Scanner.next(Scanner.java:1632)
	at java.base/java.util.Scanner.nextDouble(Scanner.java:2603)
	at Rechner.liesZahlEin(Rechner.java:20)
	at Rechner.main(Rechner.java:10)

Zuerst sehen wir, warum wir eine Ausnahmebehandlung brauchen. Zum Vergleich liest eine Methode die Zahl nur mit nextDouble(), ohne Schutz. Tippt man abc, kann nextDouble daraus keine Zahl machen. Java löst eine InputMismatchException aus („Eingabe passt nicht“).

Fängt niemand die Ausnahme ab, bricht das Programm sofort ab. Die Konsole zeigt den Stack-Trace: die Kette der Methodenaufrufe bis zum Fehler. Die letzten beiden Zeilen gehören zu unserem Programm: Zeile 20 in liesZahlEin, aufgerufen aus Zeile 10 in main. Die Zeilen darüber liegen im Scanner selbst.

Diese Zeilennummern gehören zur Vergleichsfassung hier links, nicht zum fertigen Programm rechts.

Aus Vorlesung 8, Folie 2 („Ausnahme (Exception)“): Eine nicht behandelte Exception beendet das Programm. Der Stack-Trace nennt Methoden, Klassen und Zeilennummern.
Noch 8 Schritte bis zum Ergebnis
Den ganzen Lösungsweg sehen Studierende und Lehrende der HS KL. Registriere dich mit deiner Adresse @stud.hs-kl.de oder @hs-kl.de, dann geht es hier direkt weiter.

Das Programm Rechner

mit Ausnahmebehandlung

Abbildung 1Das Programm Rechner

mit Ausnahmebehandlung

import java.util.InputMismatchException;import java.util.Scanner; public class Rechner {     private static Scanner scanner = new Scanner(System.in);     public static void main(String[] args) {        System.out.print("Erste Zahl: ");        double z1 = liesZahlEin();        System.out.print("Rechenzeichen (+, -, *, /): ");        String rechenzeichen = liesRechenzeichenEin();        System.out.print("Zweite Zahl: ");        double z2 = liesZahlEin();        double ergebnis = berechne(z1, z2, rechenzeichen);        System.out.println(z1 + " " + rechenzeichen + " " + z2 + " = " + ergebnis);    }     private static double liesZahlEin() {        double zahl = 0.0;        boolean erfolg = false;        while (!erfolg) {            try {                zahl = scanner.nextDouble();                erfolg = true;            } catch (InputMismatchException e) {                System.out.print("Geben Sie eine gültige Zahl ein (Komma als "                        + "Dezimaltrenner): ");            }            scanner.nextLine();        }        return zahl;    }     private static String liesRechenzeichenEin() {        String rechenzeichen = "+";        boolean erfolg = false;        while (!erfolg) {            rechenzeichen = scanner.nextLine();            erfolg = istGueltigesRechenzeichen(rechenzeichen);            if (!erfolg) {                System.out.print("Geben Sie +, -, * oder / ein: ");            }        }        return rechenzeichen;    }     private static boolean istGueltigesRechenzeichen(String rechenzeichen) {        return rechenzeichen.equals("+")                || rechenzeichen.equals("-")                || rechenzeichen.equals("*")                || rechenzeichen.equals("/");    }     private static double berechne(double z1, double z2, String rechenzeichen) {        double ergebnis = switch (rechenzeichen) {            case "+" -> z1 + z2;            case "-" -> z1 - z2;            case "*" -> z1 * z2;            case "/" -> z1 / z2;            default -> 0;        };        return ergebnis;    }}
LegendeDas ganze Programm.