Как обрабатывать бесконечный цикл, вызванный неправильным вводом (InputMismatchException), используя Scanner - PullRequest
31 голосов
/ 26 августа 2010

Итак, я застреваю с этим фрагментом кода:

import java.util.InputMismatchException;
import java.util.Scanner;

public class ConsoleReader {

    Scanner reader;

    public ConsoleReader() {
        reader = new Scanner(System.in);
        //reader.useDelimiter(System.getProperty("line.separator"));
    }

    public int readInt(String msg) {
        int num = 0;
        boolean loop = true;

        while (loop) {
            try {
                System.out.println(msg);
                num = reader.nextInt();

                loop = false;
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");
            } 
        }
        return num;
    }
}

и вот мой вывод:

Введите целое число:
Неверное значение!
Введите целое число:
Неверное значение!
...

Ответы [ 5 ]

54 голосов
/ 26 августа 2010

Согласно javadoc для сканера:

Когда сканер генерирует исключение InputMismatchException, сканер не пропустит токен, вызвавший исключение, чтобы его можно было извлечьили пропущен другим способом.

Это означает, что если следующий токен не является int, он выбрасывает InputMismatchException, но токен остается там.Поэтому на следующей итерации цикла reader.nextInt() снова читает тот же токен и снова выдает исключение.Что вам нужно, это использовать его.Добавьте reader.next() внутри вашего catch, чтобы использовать токен, который является недействительным и должен быть отброшен.

...
} catch (InputMismatchException e) {
    System.out.println("Invalid value!");
    reader.next(); // this consumes the invalid token
} 
0 голосов
/ 23 июля 2014
package nzt.nazakthul.app;

import java.util.*;

public class NztMainApp {

    public static void main(String[] args) {
    ReadNumber readObj = new ReadNumber();
    readObj.readNumber();
    }

}

class ReadNumber {
int no;

    int readNumber() {
    Scanner number = new Scanner(System.in);
    int no=0;
    boolean b=true;
    do {

        try {
            System.out.print("Enter a number:\t");
            no = number.nextInt();
        } catch (InputMismatchException e) {
            System.out.println("No Number");
            //e.printStackTrace();

            b=false;
        }

    }

    while (b);
    return no;

    }

}

Лично я использую BufferedReader и InputStreamReader, чтобы прочитать строку и проверить, является ли число или нет, но со сканером меньше кода.Код проверен и работает нормально.

0 голосов
/ 26 августа 2010

Вы также можете попробовать это:

   public int readInt(String msg) {
        int num = 0;
        try {
            System.out.println(msg);
            num = (new Scanner(System.in)).nextInt();
        } catch (InputMismatchException e) {
            System.out.println("Invalid value!");
            num = readInt(msg);
        } 
        return num;
    }
0 голосов
/ 26 августа 2010

Защитой вашего while-do является переменная 'loop'.

Само исключение, сгенерированное до того, как ваш код достигает присвоения loop = false;Если быть точным, исключение выдается в предыдущем выражении: num = reader.nextInt ();

Когда выброшено исключение, значение переменной 'loop' равно 'true', но ваш код переходит на перехват блока, а затемповторяет пока-делай.Это while-do никогда не остановится, потому что следующая итерация снова выдаст исключение, снова перейдет к перехвату блока и т. Д.

Чтобы завершить это while-do, вам нужно защитить свою while-do другой логической вещьюнапример:

  1. Выход, когда читатель получает не-int символ
  2. Выход при EOF

Это можно сделать в блоке перехвата или в некоторых других строках.Но точное решение зависит от ваших спецификаций.

0 голосов
/ 26 августа 2010

Что бы я сделал, это прочитал всю строку, используя Scanner.nextLine (). Затем создайте другой сканер, который читает возвращенную строку.

String line = reader.nextLine();
Scanner sc = new Scanner(line);

Это сделает вашу функцию семпла примерно такой:

  public int readInt(String msg) {
        int num = 0;
        boolean loop = true;

        while (loop) {
            try {
                System.out.println(msg);
                String line = reader.nextLine();
                Scanner sc = new Scanner(line);
                num = sc.nextInt();   
                loop = false;
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");

            } 
        }
        return num;
    }

Таким образом, у вас есть один сканер, который получает ввод, и один, который проверяет его, так что вам не нужно беспокоиться о том, что читатели будут заботиться о том, правильно ли они вводят данные.

...