This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
I keep getting my code caught in an infinite while loop.
It is nothing to advanced, but i can not figure it out for the life of me!
Someone Please help
I have purplosely just re created the specific error without all of the if statements i have in my actual program.
package bs;
import java.util.InputMismatchException;
import java.util.Scanner;
public class bs {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
boolean continueVar = true;
while (continueVar) {
try {
System.out.println("Enter Something");
int input = sc.nextInt();
} catch (InputMismatchException i) {
System.out.println("What the f***?");
continueVar = true;
}
}
}
}
The infinite loop occurs when the Input mismatch exception is caught. I would think that it would atleast ask the user to re enter their input but instead of doing that it just continues in the loop as so:
run:
Enter Something
df
What the f***?
Enter Something
What the f***?
Enter Something
What the f***?
It acts like it is just ignoring the scanner object sc?!
No the scanner is not skipped, it's just starting at the beginning of the input. From the JavaDoc:
If the translation is successful, the scanner advances past the input that matched.
This means if the conversion isn't successfull the scanner won't advance. You'd thus have to manually skip the incorrect input using just next().
Edit: you might want to check for hasNextInt() before trying to read the input.
you loop while continueVar is true, but you never set to to false, so the loop never exits.
I think you want to set continueVar to false in the exception handler.
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.
The token that caused the mismatch is still in the scanner's buffer. You need to clear it before trying to scan again.
You can do that by calling next() in your catch block, like this:
catch (InputMismatchException i) {
System.out.println("What the f***?");
sc.next();
}
Also, you don't need to set continueVar to true again. You never set it to false, so it will stay true. Guessing that's an artifact of you removing this into a mini program.
Scanner does not advance when bad token is found. Look at Scanner.java, lines 2095-2096:
catch (NumberFormatException nfe) {
position = matcher.start(); // don't skip bad token
Related
This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
I am currently working on some Java code in Eclipse and trying to use a try-catch statement inside of a do-while statement. My current code is as follows:
import java.util.Scanner;
import java.util.InputMismatchException;
import java.util.Random;
public class GG_HighLowInvalid{
public static void main(String[] args){
Scanner cg = new Scanner(System.in);
//Assign and define variables
int guess, rand;
guess = 0;
rand = 10;
//Create loop
do
try{
guess = 0;
//Ask for a guess
System.out.print("Enter your guess: ");
//Record the guess
guess = cg.nextInt();
}
catch(InputMismatchException exception){
System.out.println("Your guess must be an integer.");
}
while (guess != rand);
}
}
When I put in any number, the code works fine and will loop to ask for another input and when 10 is entered, the code stops as it is supposed to (because guess becomes equal to rand). However, if I put in anything that is not an integer (such as "No"), an infinite loop occurs where the output prints the following:
"Your guess must be and integer."
"Enter your Guess: Your guess must be an integer."
"Enter your Guess: Your guess must be an integer."
"Enter your Guess: Your guess must be an integer."
repeating forever until the program is externally terminated.
Since the while statement is (guess != rand), why is a non-integer causing this infinite loop? Shouldn't the manual input under the try-statement be called again? Any assistance in understanding this would be greatly appreciated. Also, I am pretty new to Java, so sorry in advance if I am having simple issues.
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.
Currently, your Scanner is not moving ahead to read the next input but reading the same continuously. You have to explicitly call some method which can read this incorrect value which was not expected. For example, scanner.next() call in catch block can avoid this infinite loop.
Use the following code:
catch(InputMismatchException exception){
cg.next();
System.out.println("Your guess must be an integer.");
}
After you have unsuccessfully read buffer its value isn't emptied and next time when it came to cg.nextInt() it tries to read same wrong value, and you went to loop. You need "to empty buffer", so next time it will read correct value.
You dont need to use a try catch statement. You just have to check if it is an integer or not with the hasNextInt() method of your object scanner. This is an example, it will solve your problem:
public static void main(String[] args) {
Scanner cg = new Scanner(System.in);
boolean valid = false;
//Assign and define variables
int guess, rand;
guess = 0;
rand = 10;
//Create loop
do{
System.out.println("Enter your guess: ");
if(cg.hasNextInt()){
guess = cg.nextInt();
valid = true;
}else{
System.out.println("Your guess must be an integer.");
cg.next();
}
}while (!valid || guess != rand);
}
Try resetting your variable "guess = 0" in catch block.
This question already has answers here:
Endless while loop problem with try/catch
(2 answers)
Closed 7 years ago.
Below code,
import java.util.Scanner;
public class Dummy {
static Scanner sc = new Scanner(System.in);
public static int getIntegerInput(String prompt){
int choice = 0;
for(;;){
System.out.print(prompt);
try{
choice = sc.nextInt();
break;
}catch(java.util.InputMismatchException ex){
System.out.print("What??? ");
}
}
return choice;
}
public static void main(String[] args) {
int choice = getIntegerInput("Enter a number: ");
} //end main
}
does not stop for next user input, if the first user input raised an exception.
How do I understand this problem in the above code? placing sc.next() in catch resolves the problem. But I'm still not clear what is going on under the hood? What is the right approach to resolve this problem?
When nextXYZ() fails to consume a token it leaves it in the InputStream. Here, you are looping over the same input endlessly - each iteration, you attempt to consume this token, throw an exception if it isn't an integer, catch it, and try reading it again - forever.
EDIT:
In order to work around this, you could use next() to consume that token and move on to the next one:
for(;;) {
System.out.print(prompt);
try{
choice = sc.nextInt();
break;
} catch(java.util.InputMismatchException ex) {
sc.next(); // here
}
}
The problem with Scanner next() are they will not advances if the match is not found. And the character for which it failed remain in the stream. Hence its very important to advance the scanner if you found non intended character.
You can use next() method which actually consumes any character or you can use skip method passing skip pattern.
Use hasNext() to know whether a valid match is present or not. If not then consume that character using above said methods.
If it doesnt find an int on the next like, it throws an error. This error is then caught by your program, so the break is never hit because the error jumps over it whenever a non-int (including nothing) is found.
I have a question regarding data validation and scanners.The following piece of code checks userinput.Anything other than an integer is not allowed and the user is asked to re-enter a value.My question is that the code works only if the scanner is declared within the while loop.The program executes infinitely if the scanner is declared outside.Why is that?Thanks.
int UserInp;
boolean dataType=false;
while(dataType==false)
{
Scanner sc=new Scanner(System.in);
try
{
System.out.print("\nEnter a number: ");
UserInp=sc.nextInt();
dataType=true;
}
catch(Exception JavaInputMismatch)
{
System.out.println("Option not available.Try again.");
}
}
Interesting problem!
What happens is that the Scanner attempts to translate the non-integer to an integer, and realizes it can't -- so it throws an InputMismatchException. However, it only advances past the token if the translation was successful.
Meaning, the invalid string is still in the input buffer, and it will fail the translation every single time you loop and try to call nextInt(). You never set dataType to true, and so you loop infinitely.
To see this in action, you can grab the arbitrary content in your catch block and print it out:
catch(Exception JavaInputMismatch){
System.out.println( sc.next() );
System.out.println("Option not available.Try again.");
}
Indeed, after invalid input, we get the following:
Enter a number: hello
hello
Option not available.Try again.
Enter a number:
And we don't loop infinitely. This is because the call to next() grabbed the value from the input buffer and advanced the scanner's pointer into that buffer to the next slot, which is now empty. So nextInt() will wait for input in that case.
Oh, and the reason it works fine if you initialize in the loop is that the scanner will always start reading input fresh; scanners don't share state across instances, so the "hello" that was in the buffer for the previous iteration isn't in the buffer for the next one due to the reinitialization.
Technically, it's still in the standard input buffer, but the scanner's pointer into that buffer is beyond the invalid string because it will start reading any new input, not existing input.
To add to Purag's answer, you could alternatively use nextLine() to advance the Scanner past the current line.
So your catch block will look like this:
catch(Exception JavaInputMismatch)
{
System.out.println("Option not available.Try again.");
sc.nextLine();
}
Tricky question.
You may get it!
The answer is simple. The Scanner object is kept live till the end of the execution as it is declared outside the while loop. Look this problem in the memory level.
The Scanner object is kept live so while entering the loop next time still the value(String value) will be there in Scanner object and it doesn't listens keyboard as the exception is already thrown.So the loop keeps going.
Note : The next() method in Scanner class will accept all the types of keyboard input but not the rest of the methods such as nextInt(), nextFloat() etc..,
This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
I am writing a simple java console game. I use the scanner to read the input from the console. I am trying to verify that it I ask for an integer, I don't get an error if a letter is entered. I tried this:
boolean validResponce = false;
int choice = 0;
while (!validResponce)
{
try
{
choice = stdin.nextInt();
validResponce = true;
}
catch (java.util.InputMismatchException ex)
{
System.out.println("I did not understand what you said. Try again: ");
}
}
but it seems to create an infinite loop, just printing out the catch block. What am I doing wrong.
And yes, I am new to Java
nextInt() won't discard the mismatched output; the program will try to read it over and over again, failing each time. Use the hasNextInt() method to determine whether there's an int available to be read before calling nextInt().
Make sure that when you find something in the InputStream other than an integer you clear it with nextLine() because hasNextInt() also doesn't discard input, it just tests the next token in the input stream.
Try using
boolean isInValidResponse = true;
//then
while(isInValidResponse){
//makes more sense and is less confusing
try{
//let user know you are now asking for a number, don't just leave empty console
System.out.println("Please enter a number: ");
String lineEntered = stdin.nextLine(); //as suggested in accepted answer, it will allow you to exit console waiting for more integers from user
//test if user entered a number in that line
int number=Integer.parseInt(lineEntered);
System.out.println("You entered a number: "+number);
isInValidResponse = false;
}
//it tries to read integer from input, the exceptions should be either NumberFormatException, IOException or just Exception
catch (Exception e){
System.out.println("I did not understand what you said. Try again: ");
}
}
Because of common topic of avoiding negative conditionals https://blog.jetbrains.com/idea/2014/09/the-inspection-connection-issue-2/
Here's some sample code:
import java.util.Scanner;
class In
{
public static void main (String[]arg)
{
Scanner in = new Scanner (System.in) ;
System.out.println ("how many are invading?") ;
int a = in.nextInt() ;
System.out.println (a) ;
}
}
If I run the program and give it an int like 4, then everything goes fine.
On the other hand, if I answer too many it doesn't laugh at my funny joke. Instead I get this(as expected):
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:819)
at java.util.Scanner.next(Scanner.java:1431)
at java.util.Scanner.nextInt(Scanner.java:2040)
at java.util.Scanner.nextInt(Scanner.java:2000)
at In.main(In.java:9)
Is there a way to make it ignore entries that aren't ints or re prompt with "How many are invading?" I'd like to know how to do both of these.
You can use one of the many hasNext* methods that Scanner has for pre-validation.
if (in.hasNextInt()) {
int a = in.nextInt() ;
System.out.println(a);
} else {
System.out.println("Sorry, couldn't understand you!");
}
This prevents InputMismatchException from even being thrown, because you always make sure that it WILL match before you read it.
java.util.Scanner API
boolean hasNextInt(): 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.
String nextLine(): Advances this scanner past the current line and returns the input that was skipped.
Do keep in mind the sections in bold. hasNextInt() doesn't advance past any input. If it returns true, you can advance the scanner by calling nextInt(), which will not throw an InputMismatchException.
If it returns false, then you need to skip past the "garbage". The easiest way to do this is just by calling nextLine(), probably twice but at least once.
Why you may need to do nextLine() twice is the following: suppose this is the input entered:
42[enter]
too many![enter]
0[enter]
Let's say the scanner is at the beginning of that input.
hasNextInt() is true, nextInt() returns 42; scanner is now at just before the first [enter].
hasNextInt() is false, nextLine() returns an empty string, a second nextLine() returns "too many!"; scanner is now at just after the second [enter].
hasNextInt() is true, nextInt() returns 0; scanner is now at just before the third [enter].
Here's an example of putting some of these things together. You can experiment with it to study how Scanner works.
Scanner in = new Scanner (System.in) ;
System.out.println("Age?");
while (!in.hasNextInt()) {
in.next(); // What happens if you use nextLine() instead?
}
int age = in.nextInt();
in.nextLine(); // What happens if you remove this statement?
System.out.println("Name?");
String name = in.nextLine();
System.out.format("[%s] is %d years old", name, age);
Let's say the input is:
He is probably close to 100 now...[enter]
Elvis, of course[enter]
Then the last line of the output is:
[Elvis, of course] is 100 years old
In general I really, really dislike using the same library call for both reading and parsing. Language libraries seem to be very inflexible and often just can't be bent to your will.
The first step that pulls data from System.in should not be able to fail, so have it read it as a string into a variable, then convert that string variable to an int. If the conversion fails, great--print your error and continue.
When you wrap your stream with something that can throw an exception, it gets kind of confusing just what state the whole mess leaves your stream in.
It's always a benefit to have your application throw an error when an error occurs opposed to ways to keep it from happening.
One alternative is to wrap the code inside a try {...} catch {...} block for InputMismatchException.
You might also want to wrap the code inside a while loop to have the Scanner keep prompting until a specific condition is met.