38

So, I'm getting stuck with this piece of 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;
    }
}

and here is my output:

Insert a integer number:
Invalid value!
Insert a integer number:
Invalid value!
...

gparyani
  • 1,872
  • 3
  • 24
  • 35
mateusmaso
  • 6,033
  • 6
  • 36
  • 54
  • Do consider getting rid of the variables loop and num and instead use `while (true) { try { ....; return reader.nextInt(); } catch {....} }` – Miserable Variable Aug 26 '10 at 05:33

5 Answers5

66

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
} 
samitgaur
  • 5,211
  • 2
  • 24
  • 33
  • 4
    +1 Note to readers: depending on the circumstance, you may want to use `nextLine()` instead of `next()` so that input like `this has spaces in it` doesn't trigger multiple exceptions. – MarredCheese Sep 06 '17 at 17:06
0
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

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.

cohensh
  • 477
  • 5
  • 10
0

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.

Hendra Jaya
  • 1,428
  • 10
  • 15
0

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;
    }
jerjer
  • 8,482
  • 27
  • 36