How to handle infinite loop caused by invalid input (InputMismatchException) using Scanner - java

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.

Related

Restart the program due to error (Do While) Java [duplicate]

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.

TRY/CATCH Block to prompt the user to input again [duplicate]

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.

Try catch is causing an infinite loop(input.mismatch.Exception) [duplicate]

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.

Infinte loop due to exception handling [duplicate]

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.

What's the easiest way to check if inputed number is a positive integer and re-prompt if not?

The program takes user input which is supposed to be an integer greater than 0. If the user doesn't do this he is notified of the mistake and is reprompted. Once the correct input is entered, the value is returned. What's the best way to do this? The following code is my try but doesn't work. It seems unnecessarily complex for such an easy task.
System.out.println("Please enter an integer greater than 0:");
Scanner scan = new Scanner(System.in);
int red = -1;
do
{
try
{
red = scan.nextInt();
}catch(InputMismatchException e)
{
System.out.println("Number must be an integer");
scan.nextLine();
if(red < 1)
System.out.println("Number must be more than zero");
else
break;
}
}while(true);
return red;
Sometimes I don't know what to put in my question because I already know the code doesn't work - so if there's something else I should tell please let me know.
The basic concept is running in the right direction, beware though, nextInt won't consume the new line, leaving it within the scanner, meaning you will end up with an infinite loop after the first unsuccessful loop.
Personally, I would simply get the input as a String using nextLine, which will consume the new line, causing the next loop to stop at the statement.
Then I would simply parse the String to an int value using Integer.parseInt
For example...
Scanner scan = new Scanner(System.in);
int red = -1;
do {
System.out.print("Please enter an integer greater than 0:");
String text = scan.nextLine();
if (text != null && !text.isEmpty()) {
try {
red = Integer.parseInt(text);
// This is optional...
if (red < 1) {
System.out.println("Number must be more than zero");
}
} catch (NumberFormatException exp) {
// This is optional...
System.out.println("Not a number, try again...");
}
}
} while (red < 1);
I use this class instead of the Scanner or BufferedReader classes to get user input:
import java.io.*;
public class Input{
private static BufferedReader input=new BufferedReader
(new InputStreamReader(System.in));
public static Double getDouble(String prompt){
Double value;
System.out.print(prompt);
try{
value=Double.parseDouble(Input.input.readLine());
}
catch (Exception error){
// error condition
value=null;
}
return value;
}
public static Integer getInteger(String prompt){
Integer value;
System.out.print(prompt);
try{
value=Integer.parseInt(Input.input.readLine());
}
catch (Exception error){
// error condition
value=null;
}
return value;
}
public static String getString(String prompt){
String string;
System.out.print(prompt);
try{
string=Input.input.readLine();
}
catch (Exception error){
// error condition
string=null;
}
return string;
}
}
Now, to answer your question u can write your code like this:
public class InputTest {
public int checkValue() {
int value;
do {
value = Input.getInteger("Enter a value greater than 0: ");
} while (value <= 0);
return value;
}
}

Categories

Resources