Try/catch с InputMismatchException создает бесконечный цикл - программирование
Подтвердить что ты не робот

Try/catch с InputMismatchException создает бесконечный цикл

Итак, я создаю программу, которая принимает ints от пользовательского ввода. У меня есть, кажется, очень простой блок try/catch, который, если пользователь не вводит int, должен повторять блок до тех пор, пока это не произойдет. Здесь соответствующая часть кода:

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


public class Except {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        boolean bError = true;
        int n1 = 0, n2 = 0, nQuotient = 0;

        do {
            try {
                System.out.println("Enter first num: ");
                n1 = input.nextInt();
                System.out.println("Enter second num: ");
                n2 = input.nextInt();
                nQuotient = n1/n2;
                bError = false;
            } 
            catch (Exception e) {
                System.out.println("Error!");
            }
        } while (bError);

        System.out.printf("%d/%d = %d",n1,n2, nQuotient);
    }
}

Если я введу 0 для второго целого числа, то try/catch делает именно то, что он предположил, и заставляет меня снова вставить его. Но, если у меня есть InputMismatchException, например, введя 5.5 для одного из чисел, оно просто показывает мое сообщение об ошибке в бесконечном цикле. Почему это происходит, и что я могу с этим поделать? (Кстати, я попытался явно ввести InputMismatchException в качестве аргумента для catch, но это не устранило проблему.

4b9b3361

Ответ 1

Вам нужно позвонить next();, когда вы получите сообщение об ошибке. Также рекомендуется использовать hasNextInt()

       catch (Exception e) {
            System.out.println("Error!");
           input.next();// Move to next other wise exception
        }

Перед чтением целочисленного значения вам нужно убедиться, что у сканера есть один. И вам не нужна обработка исключений.

    Scanner scanner = new Scanner(System.in);
    int n1 = 0, n2 = 0;
    boolean bError = true;
    while (bError) {
        if (scanner.hasNextInt())
            n1 = scanner.nextInt();
        else {
            scanner.next();
            continue;
        }
        if (scanner.hasNextInt())
            n2 = scanner.nextInt();
        else {
            scanner.next();
            continue;
        }
        bError = false;
    }
    System.out.println(n1);
    System.out.println(n2);

Javadoc Scanner

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

Ответ 2

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

   do {
        try {
            System.out.println("Enter first num: ");
            n1 = Integer.parseInt(input.next());

            System.out.println("Enter second num: ");
            n2 = Integer.parseInt(input.next());

            nQuotient = n1/n2;

            bError = false;
        } 
        catch (Exception e) {
            System.out.println("Error!");
            input.reset();
        }
    } while (bError);

Ответ 3

другой вариант - определить ввод сканера = новый сканер (System.in); внутри блока try это создаст новый объект каждый раз, когда вам нужно повторно ввести значения.

Ответ 4

Чтобы следить за ответом debobroto das, вы также можете поставить

input.reset();
input.next(); 

У меня была такая же проблема, и когда я это пробовал. Он полностью его исправил.

Ответ 5

Поскольку оператор bError = false никогда не был достигнут в try block, а оператор поражен введенным вводом, он сохраняет печать в бесконечном цикле.

Попробуйте использовать его таким образом, используя hasNextInt()

catch (Exception e) {
            System.out.println("Error!");
           input.hasNextInt();         
        }

Или попробуйте использовать nextLine() в сочетании с Integer.parseInt() для ввода ввода.

Scanner scan = new Scanner(System.in);

int num1 = Integer.parseInt(scan.nextLine());
int num2 = Integer.parseInt(scan.nextLine());

Ответ 6

Чтобы дополнить ответ AmitD:

Просто скопируйте/вставьте свою программу и получите этот результат:

Error!
Enter first num: 
.... infinite times ....

Как вы можете видеть, инструкция:

n1 = input.nextInt();

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

Ответ 7

@Limp, ваш ответ прав, просто используйте .nextLine(), читая ввод. Пример кода:

    do {
        try {
            System.out.println("Enter first num: ");
            n1 = Integer.parseInt(input.nextLine());
            System.out.println("Enter second num: ");
            n2 = Integer.parseInt(input.nextLine());
            nQuotient = n1 / n2;
            bError = false;
        } catch (Exception e) {
            System.out.println("Error!");
        }
    } while (bError);

    System.out.printf("%d/%d = %d", n1, n2, nQuotient);

Прочитайте описание причины этой проблемы в приведенной ниже ссылке. Найдите ответ, который я написал для этой темы в деталях. Проблема ввода пользовательских домашних заданий Java

Хорошо, я кратко опишу его. Когда вы читаете ввод с помощью nextInt(), вы просто читаете номер, но символ ENDLINE все еще находится в потоке. Это была главная причина. Теперь посмотрим на код выше, все, что я сделал, это прочитать всю строку и проанализировать ее, она по-прежнему выбрасывает исключение и работает так, как вы ожидали, что он будет работать. Остальная часть кода работает нормально.