web-dev-qa-db-fra.com

Comment gérer une boucle infinie causée par une entrée non valide (InputMismatchException) à l'aide de Scanner

Donc, je suis coincé avec ce morceau de code:

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

et voici ma sortie:

Insérer un nombre entier:
Valeur invalide!
Insérer un nombre entier:
Valeur invalide!
...

28
mateusmaso

Selon le javadoc pour Scanner:

Lorsqu'un scanneur lève une exception InputMismatchException, le scanneur Ne transmettra pas le jeton qui a causé comme exception, de sorte qu'il puisse être récupéré ou ignoré via un autre méthode.

Cela signifie que si le prochain jeton n'est pas une int, il jette le InputMismatchException, mais le jeton y reste. Donc, à la prochaine itération de la boucle, reader.nextInt() lit à nouveau le même jeton et lève à nouveau l'exception. Ce dont vous avez besoin, c'est de l'utiliser. Ajoutez une reader.next() dans votre catch pour utiliser le jeton, qui est invalide et doit être supprimé.

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

Ce que je ferais, c'est de lire toute la ligne en utilisant Scanner.nextLine (). Créez ensuite un autre scanner qui lit la chaîne renvoyée.

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

Cela donnerait à votre exemple une fonction semblable à celle-ci:

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

De cette façon, vous avez un scanner qui reçoit l’entrée et un qui le valide, de sorte que vous n’ayez pas à vous soucier de l’intérêt du lecteur s’il saisit le bon format d’entrée. 

0
cohensh

La garde de votre while-do est une variable 'en boucle'.

L'exception elle-même levée avant que votre code n'atteigne affectation loop = false; Pour être précis, l'exception est levée dans l'instruction précédente num = reader.nextInt ();

Quand une exception est levée, la valeur de la variable 'loop' est 'true', mais votre code saute pour attraper un bloc, puis répète l'opération while-do. Cela ne s'arrêtera jamais parce que la prochaine itération lèvera une exception, sautera pour attraper le bloc encore et ainsi de suite.

Pour mettre fin à ce travail, vous devez protéger votre travail avec une autre opération logique telle que:

  1. Quitter lorsque le lecteur obtient un caractère non-int
  2. Quitter quand EOF

Cela peut être fait dans catch block ou quelques autres lignes. Mais la solution précise dépend de vos spécifications.

0
Hendra Jaya

Vous pouvez aussi essayer ceci:

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

    }

}

Personnellement, j'utilise BufferedReader et InputStreamReader pour lire String et vérifier si est un nombre ou non, mais avec scanner, c'est moins de code. Le code est vérifié et fonctionne correctement.

0
user3220849