Как обрабатывать бесконечный цикл, вызванный недопустимым вводом (InputMismatchException) с помощью сканера

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

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;
    }
}

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

Вставьте целое число:
Недопустимое значение!
Вставьте целое число:
Недопустимое значение!
...


person mateusmaso    schedule 26.08.2010    source источник
comment
Подумайте о том, чтобы избавиться от цикла переменных и num и вместо этого использовать while (true) { try { ....; return reader.nextInt(); } catch {....} }   -  person Miserable Variable    schedule 26.08.2010


Ответы (5)


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

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

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

...
} catch (InputMismatchException e) {
    System.out.println("Invalid value!");
    reader.next(); // this consumes the invalid token
} 
person samitgaur    schedule 26.08.2010
comment
+1 Примечание для читателей: в зависимости от обстоятельств вы можете использовать nextLine() вместо next(), чтобы ввод типа this has spaces in it не вызывал множественных исключений. - person MarredCheese; 06.09.2017

Что бы я сделал, это прочитать всю строку, используя 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;
    }

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

person cohensh    schedule 26.08.2010

Охранник вашего while-do - это переменная 'loop'.

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

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

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

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

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

person Hendra Jaya    schedule 26.08.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;
    }
person jerjer    schedule 26.08.2010

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 для чтения строки и проверки, является ли число или нет, но со сканером меньше кода. Код проверен и работает нормально.

person Community    schedule 23.07.2014