This is the program
public class bInputMismathcExceptionDemo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean continueInput = true;
do {
try {
System.out.println("Enter an integer:");
int num = input.nextInt();
System.out.println("the number is " + num);
continueInput = false;
}
catch (InputMismatchException ex) {
System.out.println("Try again. (Incorrect input: an integer is required)");
}
input.nextLine();
}
while (continueInput);
}
}
I know nextInt() only read the integer not the "\n", but why should we need the input.nextLine() to read the "\n"? is it necessary?? because I think even without input.nextLine(), after it goes back to try {}, the input.nextInt() can still read the next integer I type, but in fact it is a infinite loop.
I still don't know the logic behind it, hope someone can help me.
The reason it is necessary here is because of what happens when the input fails.
For example, try removing the input.nextLine() part, run the program again, and when it asks for input, enter abc and press Return
The result will be an infinite loop. Why?
Because nextInt() will try to read the incoming input. It will see that this input is not an integer, and will throw the exception. However, the input is not cleared. It will still be abc in the buffer. So going back to the loop will cause it to try parsing the same abc over and over.
Using nextLine() will clear the buffer, so that the next input you read after an error is going to be the fresh input that's after the bad line you have entered.
but why should we need the input.nextLine() to read the "\n"? is it necessary??
Yes (actually it's very common to do that), otherwise how will you consume the remaining \n? If you don't want to use nextLine to consume the left \n, use a different scanner object (I don't recommend this):
Scanner input1 = new Scanner(System.in);
Scanner input2 = new Scanner(System.in);
input1.nextInt();
input2.nextLine();
or use nextLine to read the integer value and convert it to int later so you won't have to consume the new line character later.
Also you can use:
input.nextInt();
input.skip("\\W*").nextLine();
or
input.skip("\n").nextLine();
if you need whitespaces before line
Related
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);
}
I have been using the following code in c and c++ for looping till user feeds the correct value till the program comes out of it:
while((scanf("%d",&num)==1)//same way in for loop
{
//some code
}
Can i some how use the same way to accept and loop the program till i keep entering let's say an integer and floating or a char or a special character breaks it.
Use :
Scanner sc = new Scanner(System.in); // OR replace System.in with file to read
while(sc.hasNext()){
//code here
int x = sc.nextInt();
//...
}
There are different variants of hasNext() for specific expected input types: hasNextFloat(), hasNextInt()..
Same goes for next() method so you can find nextInt(), nextFloat() or even nextLine()
You can go to Java doc for more info.
As proposed in comments, you can use the Scanner class.
Note you need to read the in buffer with a nextLine() when it is not an int.
public static void main(String[] args) {
try (Scanner in = new Scanner(System.in)) {
System.out.println("Enter an int: ");
while (!in.hasNextInt()) {
System.out.println("That's not an int! try again...");
in.nextLine();
}
int myInt = in.nextInt();
System.out.println("You entered "+myInt);
}
}
This is the program
public class bInputMismathcExceptionDemo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean continueInput = true;
do {
try {
System.out.println("Enter an integer:");
int num = input.nextInt();
System.out.println("the number is " + num);
continueInput = false;
}
catch (InputMismatchException ex) {
System.out.println("Try again. (Incorrect input: an integer is required)");
}
input.nextLine();
}
while (continueInput);
}
}
I know nextInt() only read the integer not the "\n", but why should we need the input.nextLine() to read the "\n"? is it necessary?? because I think even without input.nextLine(), after it goes back to try {}, the input.nextInt() can still read the next integer I type, but in fact it is a infinite loop.
I still don't know the logic behind it, hope someone can help me.
The reason it is necessary here is because of what happens when the input fails.
For example, try removing the input.nextLine() part, run the program again, and when it asks for input, enter abc and press Return
The result will be an infinite loop. Why?
Because nextInt() will try to read the incoming input. It will see that this input is not an integer, and will throw the exception. However, the input is not cleared. It will still be abc in the buffer. So going back to the loop will cause it to try parsing the same abc over and over.
Using nextLine() will clear the buffer, so that the next input you read after an error is going to be the fresh input that's after the bad line you have entered.
but why should we need the input.nextLine() to read the "\n"? is it necessary??
Yes (actually it's very common to do that), otherwise how will you consume the remaining \n? If you don't want to use nextLine to consume the left \n, use a different scanner object (I don't recommend this):
Scanner input1 = new Scanner(System.in);
Scanner input2 = new Scanner(System.in);
input1.nextInt();
input2.nextLine();
or use nextLine to read the integer value and convert it to int later so you won't have to consume the new line character later.
Also you can use:
input.nextInt();
input.skip("\\W*").nextLine();
or
input.skip("\n").nextLine();
if you need whitespaces before line
I have the following code:
Scanner inputSide = new Scanner(System.in);
double side[] = new double[3];
int i = 0;
do{
try{
System.out.println("Enter three side lengths for a triangle (each followed by pressing enter):");
side[i] = inputSide.nextDouble();
i++;
}
catch(Exception wrongType){
System.err.println(wrongType);
System.out.println("Please enter a number. Start again!!");
i=0;
}
}
while(i<3);
It works fine and does what it's meant to if I don't enter a wrong data type but if I enter something other than a double then it loops over and over, printing everything in both try and catch blocks instead of waiting for me to enter another double.
Any help as to why it's doing this - as I can't seem to understand why - would be appreciated.
Thank you :)
The problem is that, you have used input.nextDouble method, which reads only the next token in the input, thus skipping the newline at the end. See Scanner.nextDouble
Now, if you enter wrong value first time, then it will consider the newline as the next input. Which will also be invalid.
You can add an empty input.nextLine in the catch block.
catch(Exception wrongType){
System.err.println(wrongType);
System.out.println("Please enter a number. Start again!!");
i=0;
input.nextLine(); // So that it consumes the newline left over
}
Now, your nextLine() will read the linefeed left over, and linefeed will not be taken as input to your nextDouble next time. In which case, it will fail, even before you giving any input.
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.