Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Infinite loop using Scanner in.hasNextInt()

Tags:

I am using the following code:

while (invalidInput) {     // ask the user to specify a number to update the times by     System.out.print("Specify an integer between 0 and 5: ");      if (in.hasNextInt())     {         // get the update value         updateValue = in.nextInt();          // check to see if it was within range         if (updateValue >= 0 && updateValue <= 5)          {              invalidInput = false;          }          else          {             System.out.println("You have not entered a number between 0 and 5. Try again.");         }     } else     {         System.out.println("You have entered an invalid input. Try again.");     } } 

However, if I enter a 'w' it will tell me "You have entered invalid input. Try Again." and then it will go into an infinite loop showing the text "Specify an integer between 0 and 5: You have entered an invalid input. Try again."

Why is this happening? Isn't the program supposed to wait for the user to input and press enter each time it reaches the statement:

if (in.hasNextInt()) 
like image 620
Tomek Avatar asked Nov 25 '09 02:11

Tomek


People also ask

What does hasNextInt () do in Java?

hasNextInt() method returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. The scanner does not advance past any input.

Can we use Scanner in for loop in Java?

You don't need to initialize the Scanner multiple times. Just create one instance and pass it around (keep using it). Also, for(int i=0; i < this.

What value does hasNextInt () return if a Scanner has reached the end of a file?

The hasNextInt() method returns true if the next set of characters in the input stream can be read in as an int . If they can't be read as an int , or they are too big for an int or if the end of the file has been reached, then it returns false.


2 Answers

In your last else block, you need to clear the 'w' or other invalid input from the Scanner. You can do this by calling next() on the Scanner and ignoring its return value to throw away that invalid input, as follows:

else {       System.out.println("You have entered an invalid input. Try again.");       in.next(); } 
like image 65
Kaleb Brasee Avatar answered Oct 13 '22 23:10

Kaleb Brasee


The problem was that you did not advance the Scanner past the problematic input. From hasNextInt() documentation:

Returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. The scanner does not advance past any input.

This is true of all hasNextXXX() methods: they return true or false, without advancing the Scanner.

Here's a snippet to illustrate the problem:

    String input = "1 2 3 oops 4 5 6";     Scanner sc = new Scanner(input);     while (sc.hasNext()) {         if (sc.hasNextInt()) {             int num = sc.nextInt();             System.out.println("Got " + num);         } else {             System.out.println("int, please!");             //sc.next(); // uncomment to fix!         }     } 

You will find that this program will go into an infinite loop, asking int, please! repeatedly.

If you uncomment the sc.next() statement, then it will make the Scanner go past the token that fails hasNextInt(). The program would then print:

Got 1 Got 2 Got 3 int, please! Got 4 Got 5 Got 6 

The fact that a failed hasNextXXX() check doesn't skip the input is intentional: it allows you to perform additional checks on that token if necessary. Here's an example to illustrate:

    String input = " 1 true foo 2 false bar 3 ";     Scanner sc = new Scanner(input);     while (sc.hasNext()) {         if (sc.hasNextInt()) {             System.out.println("(int) " + sc.nextInt());         } else if (sc.hasNextBoolean()) {             System.out.println("(boolean) " + sc.nextBoolean());         } else {             System.out.println(sc.next());         }     } 

If you run this program, it will output the following:

(int) 1 (boolean) true foo (int) 2 (boolean) false bar (int) 3 
like image 38
polygenelubricants Avatar answered Oct 13 '22 23:10

polygenelubricants