Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

В соответствии с javadoc для сканера:

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

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

...
} catch (InputMismatchException e) {
    System.out.println("Invalid value!");
    reader.next(); // this consumes the invalid token
} 

Ответ 2

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

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

Ответ 3

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

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

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

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

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

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

Ответ 4

Вы также можете попробовать следующее:

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

Ответ 5

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