Java Infinite Loop with Scanner Input [duplicate] - 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

Java - How to handle Exception Handling in a Looping Switch Statement [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.

NoSuchElementException infinite loop vs. pmd DD-anomaly

I'm kinda new to programming and very new to gradle and the pmd-plugin, so please have mercy.
If the user enters a number, scanner.nextLine() will throw a NoSuchElementException in every iteration thus creating an infinite loop.
public class Console {
public int readInteger(String line) {
Integer x = null;
while(x == null) {
try(Scanner scanner = new Scanner(System.in) {
System.out.print(line);
x = scanner.nextInt();
} catch(InputMismatchException exc) {
//error message
} catch(InvalidStateException exc) {
//error message
} catch(NoSuchElementException exc) {
//error message
}
}
return x;
}
}
I will appreciate every helping hand.
Edit: Realized, that my problem occurs in conjuction with the Scanner.nextLine() method. The order doesn't matter, my loop is still an infinite loop with the same NoSuchElementException.
Just change the
x = scanner.nextLine();
to
x = scanner.nextInt();
Also no it will not enter infinite loop because you use wrong method it simply will not work .
Here's the complete (compilable) example:
import java.util.Scanner;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
public class Console {
public int readInteger(String line) {
Integer x = null;
while(x == null) {
try(Scanner scanner = new Scanner(System.in)) {
System.out.print(line);
x = scanner.nextInt();
} catch(InputMismatchException exc) {
//error message
} catch(IllegalStateException exc) {
//error message
} catch(NoSuchElementException exc) {
//error message
}
}
return x;
}
public static void main(String[] args) {
Console c = new Console();
int age = c.readInteger("How old are you? ");
System.out.printf("You are %d years old.%n", age);
}
}
Note: InvalidStateException doesn't exist, it is IllegalStateException.
Save this code snippet in Console.java and run it with java 11+ like java Console.java.
If you are entering eg. 42 it works. The "endless loop" starts, if you don't enter an integer, e.g. very old. Now we need to actually handle the exceptions. In that case, InputMismatchException will be thrown. But the wrong input is not consumed and is still in the scanner - so trying again with nextInt() will throw the same exception again. We'll have to read the wrong token first before the user can enter new data. We can read the data with nextLine(), but therefore we need to have access to the scanner, so we need to open the scanner instance earlier - and have the loop and error handling inside the outer try-with-resources.
If the user closes the input stream (with Ctlr+Z under Windows or Cltr+D under Linux), then NoSuchElementException will be thrown, so we'll need to handle that case as well. IllegalStateException will be thrown, if the Scanner instance itself is closed.
Here's a fixed complete example:
import java.util.Scanner;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
public class Console {
public int readInteger(String line) {
Integer x = null;
try (Scanner scanner = new Scanner(System.in)) {
while(x == null) {
try {
System.out.print(line);
x = scanner.nextInt();
} catch(InputMismatchException exc) {
String wrongInput = scanner.nextLine();
System.out.printf("The input '%s' is not a number. Please try again.%n", wrongInput);
} catch(NoSuchElementException exc) {
// no input provided
System.exit(1);
}
}
}
return x;
}
public static void main(String[] args) {
Console c = new Console();
int age = c.readInteger("How old are you? ");
System.out.printf("You are %d years old.%n", age);
}
}

How to work with catching errors

I refreshing my Java skills, say we've got this code
public class HelloWorld extends Exception {
public static int tenMultiplication(int x) {
for (int i = 2; i < 11; i++) {
System.out.println(x * i);
}
return x;
}
public static String scanExpression() {
Scanner scan = new Scanner(System.in);
String exp = "";
do {
System.out.println("Please enter a number:");
try {
exp = scan.nextLine();
int result = Integer.parseInt(exp);
tenMultiplication(result);
} catch (NumberFormatException e) {
System.out.println("Please enter a number: ");
}
} while (exp.matches("-?\\d+") || exp == "exit");
return exp;
}
public static void main(String args[]) throws Exception {
scanExpression();
}
}
Program logic: Program asks for an input, and draws a row of multiplication table till 10; any time you can exit by typing "exit", everything else is an error.
Every time I write an incorrect number, it will simply catch an error and exit the program. What is the best way with going about iteratively catching errors if you consecutively type non-Ints and not "exit" to exit the program? I tried putting
exp = scan.nextLine();
int result = Integer.parseInt(exp);
tenMultiplication(result);
But when trying to write an error here, it throws the error again, which defeats the point of my try { } catch blocks.
You need to re-read the input in case NumberFormatException is caught, you can do it in a recursive way by by calling your function again
public static void scanExpression(Scanner scan) {
System.out.println("Please enter a number:");
try {
String exp = scan.nextLine();
if(exp.equals("exit"))
System.exit(0);
int result = Integer.parseInt(exp);
tenMultiplication(result);
} catch (NumberFormatException e) {scanExpression(scan);}
}
public static void main(String args[]) throws Exception {
Scanner scan = new Scanner(System.in);
scanExpression(scan);
}
After the catch block executes the program continues and goes to check the condition in the while statement. The while statement returns false for that condition so your program terminates. Plus you need to compare exp like this: exp.equals("exit").
Here are some changes I made to your loop.
do {
System.out.println("Please enter a number:");
try {
exp = scan.nextLine();
int result = Integer.parseInt(exp);
tenMultiplication(result);
} catch (NumberFormatException e) {
}
} while (!exp.equals( "exit") );
I made your catch block empty. The reasoning is that if it does catch invalid input from the user, "Please enter a number:" would print twice.
Also, I modified your while loop condition. Previously you had exp == "exit". This doesn't work the way you expect it to work. When comparing String values, always use `String1.equals(String2) to see if String1 and String2 are equal.

java try-catch inputMismatchException [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 Statement Infinite Loop [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.

Categories