My program has an endless loop, when I use try and catch block in a while loop.
import java.util.*;
class Try
{
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
while(true)
{
try {
System.out.println("Enter a no ");
int s=sc.nextInt();
} catch(Exception e) {
System.out.println("Invalid input try again");
}
}
}
}
When I input an integer, it runs fine and asks for another input, but when I input a char, it goes for endless loop. Why is this so?
Your program enters an infinite loop when an invalid input is encountered because nextInt() does not consume invalid tokens. So whatever token that caused the exception will stay there and keep causing an exception to be thrown the next time you try to use nextInt().
This can be solved by putting a nextLine() call inside the catch block to consume whatever input was causing the exception to be thrown, clearing the input stream and allowing the user to continue trying.
You did not break the loop. To end the loop you need to insert
break;
wherever you would like the loop to end.
In order to solve this, you need to clear the input stream otherwise same exception already caught causes make an infinite loop. By adding nextLine() inside the catch block cause to consume whatever input was causing the exception to be thrown.As a best practice like this situation it good to use hasNextInt() for checking the user input before calling the nextInt()
import java.util.*;
class Try {
public static void main(String args[]) {
Scanner scanner=new Scanner(System.in);
while(true) {
try {
System.out.println("Enter a Number");
int num=scanner.nextInt();
} catch(Exception e) {
System.out.println("Invalid input try again");
scanner.nextLine(); // cause to consume already caught Exception
}
}
}
}
Scanning an int does not consume the newline charackter (pressing enter). Therefor it reads the newline charackter every time and throws an InputMismatchException.
You can consume it by simply calling next() or nextLine() after your make your input.
Note: next() does only work on unix since it reads only one byte and Windows ends a line with two charackters (\r\n).
The problem is that when you call nextInt you will screw the Scanner and so it cannot be used once nextInt caused in exception. That Scanner is not valid anymore. To get around this, you should read the content as string and cast it, when the cast operation fails, you don't have to worry about anything.
I would do it like this:
import java.util.*;
class Try
{
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
while(true)
{
try{
System.out.println("Enter a no ");
int s=Integer.parseInt(sc.next()); // or sc.nextLine() if you wish to get multi digit numbers
}catch(Exception e)
{
System.out.println("Invalid input try again");
}
}
}
}
Related
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.
This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
If I type in letter for the first Scanner statement i get "error!!" and "enter a number" but cannot input another number.I am a beginner and do not know whether an input statement can be used within a catch statement
import java.util.InputMismatchException;
import java.util.Scanner;
public class excep {
public static void main(String args[]){
int n;
Scanner input=new Scanner(System.in);
try{
System.out.println("ENTER A NUMBER: ");
n=input.nextInt();
}
catch(InputMismatchException e){
System.out.println("ERROR!!! \nENTER A NUMBER :");
n=input.nextInt();
}
}
}
You must have to eat or remove characters from the buffer before you restart input. For the sake of simplicity, your code should look alike :
while(true) {
Scanner input=new Scanner(System.in);
try {
System.out.println("ENTER A NUMBER: ");
n=input.nextInt();
break;
}catch(InputMismatchException e) {
System.out.println("ERROR!!! \nENTER A NUMBER :");
input.next(); // eat some chars
}
}
The biggest problem with your approach is that if nextInt() fails because the user did not enter a valid integer, the scanner does not advance. The scanner has a pointer that points to the next character to read from the input. When you use nextInt(), if the next "token" is an integer, the scanner will advance the pointer past the integer. But if it isn't an integer, an exception is thrown--and the pointer stays in the same place as before. So when you catch the exception, then call nextInt(), the scanner tries to read the same invalid integer that it just tried to read last time.
To skip over the bad integer, you can say input.next() to skip over one token, or input.nextLine() to skip over the entire remainder of the input line, before trying to read another integer. (Both of these return String results, but you can discard the result since it's not important to you).
However, this is not really a good way to use try/catch. If the user is having a bad day and enters another invalid integer, the scanner will throw an exception, and it will not be caught, since you are not in the try when the second exception is thrown. catch doesn't loop back and catch it again. The best idiom for this is a loop:
boolean validIntegerEntered = false;
System.out.println("ENTER A NUMBER: ");
while (!validIntegerEntered) {
try {
n=input.nextInt();
validIntegerEntered = true; // will not get here if nextInt()
// throws an exception
}
catch (InputMismatchException e) {
input.nextLine(); // let the scanner skip over the bad input
System.out.println("ERROR!!! \nENTER A NUMBER :");
// don't call nextInt() here; loop back, and nextInt() will be called
// in the try statement
}
}
Syntactically, Yes you can but you shouldn't use it. Why?
input.nextInt(); can throw InputMismatchException or NoSuchElementException or IllegalStateException if the scanner is closed.
If any of those exceptions occur within the catch block, you are not handling them. You should probably look at how to implement a retry catch
You are using the input.nextInt(), means it can only accepts int values.If you want to enter string values then better to use input.nextine().
In your code in catch block you are using again input.nextInt() but scanner has already wrong input in it that why it throw the exception.If you want to take input inside catch block then try the below code:
catch(InputMismatchException e){
System.out.println("ERROR!!! \nENTER A NUMBER :");
Scanner input1=new Scanner(System.in);
n=input1.nextInt();
System.out.println("Inside catch:"+n);
}
Does anyone see a problem with this? First input works fine, but after the first loop, it doesn't ask to enter a value again. How do I fix this?
int value;
while(true)
{
Scanner scan = new Scanner(System.in);
System.out.println("Enter a value");
try
{
value = scan.nextInt();
System.out.println("value provided is: " + value);
scan.nextLine(); // consumes "\n" character in buffer
}
catch(InputMismatchException e) // outputs error message if value provided is not an integer
{
System.out.println("Incorrect input type. Try again.");
continue; // restarts while loop to allow for re-entering of a valid input
}
scan.close();
}
Move scan.close(); to outside the while loop.
Also you don't have to construct a new Scanner on each iteration. Move the declaration to outside the loop as well.
When close the Scanner, this closes the System.in input stream.
So now when you try to instantiate it again, it doesn't find any opened stream and you'll get that exception.
At the end of the while loop you have written scan.close(). This will close the scanner preventing any further scans. Removing that statement would ensure your while loop keeps asking you for the number(will be an infinite loop in your case)
Also, scan.nextInt() in effect ignores all new line and waits till you actually input a number and hit enter. So, scan.nextLine() can be omitted. You need that only in case where you use scan.nextLine() to fetch the value entered. In that case, the new line character is also read as an input, as a result of which you need an extra nextLine() call to consume it.
When you do scan.close(), it closes the underlying System.in stream. So in the next iteration it will not have anything to read.
For example:
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int value;
while (true) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a value");
try {
value = scan.nextInt();
System.out.println("value provided is: " + value);
scan.nextLine(); // consumes "\n" character in buffer
} catch (InputMismatchException e) // outputs error message if value
// provided is not an integer
{
System.out.println("Incorrect input type. Try again.");
continue; // restarts while loop to allow for re-entering of a
// valid input
}
scan.close();
try {
int x = System.in.read();
System.out.println(x);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
OUTPUT:
Enter a value
10
value provided is: 10
Enter a value
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:206)
at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
at Main.main(Main.java:24)
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:907)
at java.util.Scanner.next(Scanner.java:1530)
at java.util.Scanner.nextInt(Scanner.java:2160)
at java.util.Scanner.nextInt(Scanner.java:2119)
at Main.main(Main.java:12)
Check this question for more:
Is it safe not to close a Java Scanner, provided I close the underlying readable?
import java.util.*;
public class June16{
public static void main(String[] args){
Scanner kb = new Scanner(System.in);
double b=0;
boolean checkInput = true;
do{
try{
System.out.println("Input b : ");
b = kb.nextDouble();
checkInput = false;
}catch(InputMismatchException ime){
}
}while(checkInput);
}
}
After InputMismatchException is thrown, why my program not prompt for input? :D
From the documentation:
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.
This is why you end up in an infinite loop if you don't enter a valid double. When you handle the exception, move to the next token with kb.next().
Because if the Scanner.nextDouble() failes it leaves the token on the queue, (which is then read again and again causing it to fail over and over again).
Try the following:
try {
// ...
} catch (InputMismatchException ime) {
kb.next(); // eat the malformed token.
}
ideone.com demo illustrating working example
This is due to the fact that nextDouble will take the decimal number you entered, but there is still a carriage return that you enter that was not read by the scanner. The next time it loops it reads the input, but wait! there is a carriage return there, so... no need to scan anything. It just processes the carriage return. Of course, the program finds that it is not a double, so you get an exception.
How do you fix it? Well, have something that scans whatever leftovers were left by the nextDouble (namely a next()) and then scan the next double again.
I'm working on a Serpinski triangle program that asks the user for the levels of triangles to draw. In the interests of idiot-proofing my program, I put this in:
Scanner input= new Scanner(System.in);
System.out.println(msg);
try {
level= input.nextInt();
} catch (Exception e) {
System.out.print(warning);
//restart main method
}
Is it possible, if the user punches in a letter or symbol, to restart the main method after the exception has been caught?
You can prevent the Scanner from throwing InputMismatchException by using hasNextInt():
if (input.hasNextInt()) {
level = input.nextInt();
...
}
This is an often forgotten fact: you can always prevent a Scanner from throwing InputMismatchException on nextXXX() by first ensuring hasNextXXX().
But to answer your question, yes, you can invoke main(String[]) just like any other method.
See also
(Java) Opinion: Preventing Exceptions vs. Catching Exceptions
How do I keep a scanner from throwing exceptions when the wrong type is entered? (java)
Note: to use hasNextXXX() in a loop, you have to skip past the "garbage" input that causes it to return false. You can do this by, say, calling and discarding nextLine().
Scanner sc = new Scanner(System.in);
while (!sc.hasNextInt()) {
System.out.println("int, please!");
sc.nextLine(); // discard!
}
int i = sc.nextInt(); // guaranteed not to throw InputMismatchException
Well, you can call it recursively: main(args), but you'd better use a while loop.
You much better want to do this:
boolean loop = true;
Scanner input= new Scanner(System.in);
System.out.println(msg);
do{
try {
level= input.nextInt();
loop = false;
} catch (Exception e) {
System.out.print(warning);
//restart main method
loop = true;
}
while(loop);