This question already has answers here:
Error catching with try-catch and while loop [duplicate]
(1 answer)
How to handle infinite loop caused by invalid input (InputMismatchException) using Scanner
(5 answers)
Closed 7 years ago.
Hi I´m newbie in programming and I have this problem. I want to get input from user , using scanner. Program is supposed to try if input is valid, then call a function to do the job. Problem is I want program to repeat aking for input from user, if input is not valid. So I have try block in a while loop. The problem is on the first iteration of while loop everything is ok but when I insert invalid input and while loop is forced to iterate second time, try block is not executed and boolean which is condition of while loop is not set to false. So while loop runs for ever. Plz be kind.
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
boolean isRunning = true;
int input;
while(isRunning) {
System.out.println("insert a number:");
try {
input = scanner.nextInt();
inputToString(input);
isRunning = false;
} catch(InputMismatchException e) {
System.out.println("input musi byt cele cislo");
isRunning = true;
}
}
}
public static void inputToString(int input) {
System.out.println(input);
}
You need to consume invalid number from Scanner before asking for new one since nextInt didn't consume it, but thrown exception.
} catch (InputMismatchException e) {
System.out.println("input musi byt cele cislo");
scanner.next();//consume
isRunning = true;
}
But you should not use exceptions and try-catch sections as main part of control logic. Scanner provides hasNextInt() method to test if user provided valid input. So your code should be like
System.out.print("give me the money:");//ask user of integer
while(!scanner.hasNextInt()){//test is provided value is valid integer
String token = scanner.next();//consume incorrect value
//inform that value is not correct and ask for new one
System.our.println(token + " is not considered as valid number");
System.our.print("please try again:");
}
//here we know that user provided valid integer
value = scanner.nextInt();
The problem with your approach is that when the input is not a valid int you leave it in the input buffer. The next loop will see exactly the same input, and it would repeat exactly the same actions (throw, catch, continue with the loop).
What you should do is to drop the incorrect input from the scanner when you see that it does not match what you expect. You could do it in your catch block, like this:
try {
input = scanner.nextInt();
inputToString(input);
isRunning = false;
} catch(InputMismatchException e) {
System.out.println("input musi byt cele cislo");
isRunning = true;
scanner.nextLine(); // Drop input from the scanner's buffer
}
A better approach would be to not rely on try/catch in the scanning code at all. Scanner provides a convenient way for you to avoid exceptions: calling hasNextInt before you call nextInt lets you find out ahead of time if the exception would be thrown or not, and clean the wrong data from the buffer:
while(isRunning) {
System.out.println("insert a number:");
if (scanner.hasNextInt()) {
input = scanner.nextInt();
inputToString(input);
isRunning = false;
} else {
System.out.println("input musi byt cele cislo");
isRunning = true;
scanner.nextLine(); // Drop input from the scanner's buffer
}
}
you should reinitialize Scanner reference before scanning input
public static void main(String args[]) {
Scanner scanner = null;
boolean isRunning = true;
int input;
while (isRunning) {
System.out.println("insert a number:");
try {
scanner = new Scanner(System.in);
input = scanner.nextInt();
inputToString(input);
isRunning = false;
} catch (InputMismatchException e) {
System.out.println("input musi byt cele cislo");
isRunning = true;
}
}
}
public static void inputToString(int input) {
System.out.println(input);
}
this works
Related
I'm confused while using an Java program I created.
public static void main(String[] args) {
Scanner scanner1 = new Scanner(System.in);
int input1 = 0;
boolean Input1Real = false;
System.out.print("Your first input integer? ");
while (!Input1Real) {
String line = scanner1.nextLine();
try {
input1 = Integer.parseInt(line);
Input1Real = true;
}
catch (NumberFormatException e) {
System.out.println("Use an integer! Try again!");
System.out.print("Your first input integer? ");
}
}
System.out.println("Your first input is " + input1);
}
Initially, when a user Ctrl+D during the input, it will promptly end the program and display an error in the form of this,
Your first input integer? ^D
Class transformation time: 0.0073103s for 244 classes or 2.9960245901639343E-5s per class
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651);
at Playground.Test1.main(Test1.java:13)
Doing a bit of research I note that Ctrl+D terminates the input of sort. Therefore, I tried add few more lines to my codes to prevent the error from appearing again and instead printing a simple "Console has been terminated successfully!" and as far as my skills can go.
public static void main(String[] args) {
Scanner scanner1 = new Scanner(System.in);
int input1 = 0;
boolean Input1Real = false;
System.out.print("Your first input integer? ");
while (!Input1Real) {
String line = scanner1.nextLine();
try {
try {
input1 = Integer.parseInt(line);
Input1Real = true;
}
catch (NumberFormatException e) {
System.out.println("Use an integer! Try again!");
System.out.print("Your first input integer? ");
}
}
catch (NoSuchElementException e) {
System.out.println("Console has been terminated successfully!");
}
}
System.out.println("Your first input is " + input1);
}
In the end, I still got the same error.
Got it!, the code hasNext() will ensure that the error will not appear. This method is to check whether there is another line in the input of the scanner and to check if its filled or empty. I am also using null to check my statement after passing the loop so the program stops if the input value is still null while keeping the function of Ctrl+D.
public static void main(String[] args) {
Integer input1 = null;
System.out.println("Your first input integer? ");
Scanner scanner1 = new Scanner(System.in);
while(scanner1.hasNextLine()) {
String line = scanner1.nextLine();
try {
input1 = Integer.parseInt(line);
break;
}
catch (NumberFormatException e) {
System.out.println("Use an integer! Try again!");
System.out.println("Your first input integer? ");
}
}
if (input1 == null) {
System.out.println("Console has been terminated successfully!");
System.exit(0);
}
System.out.println(input1);
}
This solution is not prefect of course but I would appreciate if there were much simpler options.
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!
...
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
}
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.
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 :
Exit when reader gets non-int character
Exit when EOF
This can be done in catch block or some other lines. But precise solution depends on your specifications.
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;
}
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.
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!
...
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
}
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.
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 :
Exit when reader gets non-int character
Exit when EOF
This can be done in catch block or some other lines. But precise solution depends on your specifications.
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;
}
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.
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!
...
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
}
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.
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 :
Exit when reader gets non-int character
Exit when EOF
This can be done in catch block or some other lines. But precise solution depends on your specifications.
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;
}
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.
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!
...
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
}
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.
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 :
Exit when reader gets non-int character
Exit when EOF
This can be done in catch block or some other lines. But precise solution depends on your specifications.
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;
}
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.