How to handle infinite loop caused by invalid input (InputMismatchException) using Scanner

前端 未结 5 1973
南方客
南方客 2020-11-21 06:30

So, I\'m getting stuck with this piece of code:

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

public class ConsoleReader {

    Scanner         


        
相关标签:
5条回答
  • 2020-11-21 07:01

    What I would do is read in the whole line using Scanner.nextLine(). Then create another scanner that reads the returned string.

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

    This would make your sample function something like this:

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

    This way you have one scanner that gets the input and one that validates it so you don't have to worry about reader caring if they input the correct form of input.

    0 讨论(0)
  • 2020-11-21 07:03

    As per the javadoc for Scanner:

    When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.

    That means that if the next token is not an int, it throws the InputMismatchException, but the token stays there. So on the next iteration of the loop, reader.nextInt() reads the same token again and throws the exception again. What you need is to use it up. Add a reader.next() inside your catch to consume the token, which is invalid and needs to be discarded.

    ...
    } catch (InputMismatchException e) {
        System.out.println("Invalid value!");
        reader.next(); // this consumes the invalid token
    } 
    
    0 讨论(0)
  • 2020-11-21 07:12

    The guard of your while-do is 'loop' variable.

    The exception itself thrown before your code reaches assignment loop = false; To be precise, the exception is thrown in previous statement which is num = reader.nextInt();

    When exception thrown, value of 'loop' variable is 'true' but your code jumps to catch block and then repeats the while-do. This while-do will never stop because next iteration will throw an exception again, jumps to catch block again and so on.

    To terminate this while-do, you need to guard your while-do with another logical thing such as :

    1. Exit when reader gets non-int character
    2. Exit when EOF

    This can be done in catch block or some other lines. But precise solution depends on your specifications.

    0 讨论(0)
  • 2020-11-21 07:16

    You may also try this:

       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 讨论(0)
  • 2020-11-21 07:24
    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;
    
        }
    
    }
    

    Personally i use BufferedReader and InputStreamReader to read String and check if is a number or not, but with scanner is less code. The code is checked and run ok.

    0 讨论(0)
提交回复
热议问题