Comment gérer une boucle infinie causée par une entrée non valide (InputMismatchException) en utilisant un 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 mon résultat:

insérez un nombre entier:

Valeur non valide!

Insérez un nombre entier:

Valeur non valide!

...

26
demandé sur Pshemo 2010-08-26 08:57:09

5 réponses

selon le javadoc pour Scanner:

Quand un scanner lance une InputMismatchException, le scanner ne pas passer le jeton qui a causé l'exception, de sorte qu'il peut être récupéré ou sauté par un autre méthode.

cela signifie Que si le prochain jeton n'est pas un int, il lance le InputMismatchException, mais le jeton reste là. Donc sur la prochaine itération de la boucle, reader.nextInt() lit à nouveau le même jeton et lance le encore une exception. Ce que vous avez besoin est à l'utiliser. Ajouter un reader.next() à l'intérieur de votre catch pour consommer le jeton, qui est invalide et doit être jeté.

...
} catch (InputMismatchException e) {
    System.out.println("Invalid value!");
    reader.next(); // this consumes the invalid token
} 
48
répondu samitgaur 2010-08-26 05:27:09

ce que je ferais, c'est lire dans toute la ligne à L'aide d'un Scanner.nextLine(). Puis créez un autre scanner qui lit la chaîne retournée.

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

ceci ferait de votre fonction d'échantillon quelque chose comme ceci:

  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 la valide de sorte que vous n'avez pas à vous soucier du lecteur qui se soucie de saisir la forme correcte de l'entrée.

0
répondu cohensh 2010-08-26 05:29:08

la garde de votre while-do est variable 'loop'.

l'exception elle-même lancée avant que votre code atteigne boucle d'assignation = false; Pour être précis, l'exception est lancée dans la déclaration précédente qui est num = reader.nextInt ();

lorsque l'exception est lancée, la valeur de la variable 'loop' est 'true' mais votre code saute pour saisir le bloc et répète ensuite le while-do. Ce while-do ne s'arrêtera jamais parce que la prochaine itération va jeter une exception à nouveau, sauts pour attraper bloc à nouveau et ainsi de suite.

pour mettre fin à ce while-do, vous devez garder votre while-do avec une autre chose logique telle que :

  1. Sortie lorsque le lecteur devient non-int caractère
  2. Sortie lorsque EOF

cela peut être fait dans le bloc catch ou d'autres lignes. Mais une solution précise dépend de vos spécifications.

0
répondu Hendra Jaya 2010-08-26 05:34:00

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
répondu jerjer 2010-08-26 05:34:48
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 la chaîne et vérifier si est un nombre ou non, mais avec le scanner est moins de code. Le code est vérifié et exécuté correctement.

0
répondu 2014-07-23 09:50:16