web-dev-qa-db-fra.com

try / catch avec InputMismatchException crée une boucle infinie

Je suis donc en train de créer un programme qui prend les entrées des entrées utilisateur. J'ai ce qui semble être un bloc try/catch très simple qui, si l'utilisateur n'entre pas d'int, devrait répéter le bloc jusqu'à ce qu'il le fasse. Voici la partie pertinente du code:

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

Si j'entre un 0 pour le deuxième entier, alors le try/catch fait exactement ce qu'il est censé faire et me fait le réintroduire. Mais, si j'ai une InputMismatchException comme en entrant 5.5 pour l'un des nombres, cela montre juste mon message d'erreur dans une boucle infinie. Pourquoi cela se produit-il et que puis-je faire? (Soit dit en passant, j'ai essayé de taper explicitement InputMismatchException comme argument à intercepter, mais cela n'a pas résolu le problème.

21
limp_chimp

Vous devez appeler next(); lorsque vous obtenez l'erreur. Il est également conseillé d'utiliser hasNextInt()

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

Avant de lire la valeur entière, vous devez vous assurer que le scanner en a une. Et vous n'aurez pas besoin de gérer les exceptions comme ça.

    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 de Scanner

Lorsqu'un analyseur lève une InputMismatchException, l'analyseur ne transmet pas le jeton qui a provoqué l'exception, de sorte qu'il peut être récupéré ou ignoré via une autre méthode.

29
Amit Deshpande

Vous pouvez également essayer les solutions suivantes

   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);
4
Debobroto Das

une autre option consiste à définir l'entrée du scanner = nouveau scanner (System.in); à l'intérieur du bloc try, cela créera un nouvel objet chaque fois que vous devrez ressaisir les valeurs.

2
ron17ro

Pour suivre la réponse de debobroto das, vous pouvez également mettre

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

J'ai eu le même problème et quand j'ai essayé ça. Il l'a complètement corrigé.

2
YoMama420

Comme l'instruction bError = false Est jamais atteinte dans try block, Et que l'instruction est frappée à l'entrée saisie, elle continue d'imprimer le - erreur dans la boucle infinie.

Essayez de l'utiliser de cette façon en utilisant hasNextInt()

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

Ou essayez d'utiliser nextLine() couplée à Integer.parseInt() pour prendre des données ....

Scanner scan = new Scanner(System.in);

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

Pour compléter la réponse AmitD:

Copiez/collez simplement votre programme et obtenez cette sortie:

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

Comme vous pouvez le voir, l'instruction:

n1 = input.nextInt();

Lève continuellement l'exception lorsque votre double numéro est entré, et c'est parce que votre flux n'est pas effacé. Pour le corriger, suivez la réponse AmitD.

1
Hernan Velasquez

@Limp, votre réponse est juste, utilisez simplement .nextLine () lors de la lecture de l'entrée. Exemple de code:

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

Lisez la description des raisons de ce problème dans le lien ci-dessous. Recherchez la réponse que j'ai postée pour le détail dans ce fil. problème de saisie utilisateur Java Homework

Ok, je vais le décrire brièvement. Lorsque vous lisez l'entrée à l'aide de nextInt (), vous lisez simplement la partie numérique mais le caractère ENDLINE était toujours sur le flux. C'était la principale cause. Maintenant, regardez le code ci-dessus, tout ce que j'ai fait est de lire toute la ligne et de l'analyser, il lève toujours l'exception et fonctionne comme vous vous attendiez à ce qu'il fonctionne. Le reste de votre code fonctionne bien.

1
Jimmy