I want to ask the user to enter a String, and four integer values, and i want the program to keep asking the user for integer value if the user input a type mismatch, why the code keep looping forever and never wait for the user input if the user inserted a wrong type ?
import java.util.InputMismatchException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String sessionName;
int pomoInterv, breakInterv, terminalBreakInterv;
System.out.println("Please, Enter the session name: ");
sessionName = scanner.nextLine();
while (true) {
try {
System.out.println("Please, Enter the Pomodoro interval: ");
pomoInterv = scanner.nextInt();
break;
} catch (InputMismatchException ex) {
System.out.println(ex.getMessage());
}
}
while (true) {
try {
System.out.println("Please, Enter the break interval: ");
breakInterv = scanner.nextInt();
break;
} catch (InputMismatchException ex) {
System.out.println(ex.getMessage());
}
}
while (true){
try {
System.out.println("Please, Enter the terminal break interval ");
terminalBreakInterv = scanner.nextInt();
break;
} catch (InputMismatchException ex) {
System.out.println(ex.getMessage());
}
}
System.out.println("Done!");
System.out.println(sessionName);
System.out.println(pomoInterv);
System.out.println(breakInterv);
System.out.println(terminalBreakInterv);
}
}
According to scanner oracle docs :
https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
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.
So when you entered anything other than an integer, the scanner.nextInt() will not parse it to integer and throw InputMismatchException and the scanner will not move to the next token and tried to read again and again the same token.
To solve this, you can either change the loop or use hasNextInt() method or use scanner.next() in the catch block so that the scanner can move to the next token.
I always use do-while loop when checking for correct Input from the user.
See if the following works:
Scanner scanner = new Scanner(System.in);
String sessionName;
int pomoInterv = -1, breakInterv = -1, terminalBreakInterv = -1;
System.out.println("Please, Enter the session name: ");
sessionName = scanner.nextLine();
boolean isPomoInterv = false;
do {
System.out.println("Please, Enter the Pomodoro interval: ");
String temp = scanner.nextLine();
try {
if (Integer.parseInt(temp) > 0) {
pomoInterv = Integer.parseInt(temp);
isPomoInterv = true;
}
} catch (NumberFormatException e) {
System.out.println("Try again");
}
} while (!isPomoInterv);
boolean isBreakInterv = false;
do {
System.out.println("Please, Enter the break interval: ");
String temp = scanner.nextLine();
try {
if (Integer.parseInt(temp) > 0) {
breakInterv = Integer.parseInt(temp);
isBreakInterv = true;
}
} catch (NumberFormatException e) {
System.out.println("Try again");
}
} while (!isBreakInterv);
boolean isTerminalBreakInterv = false;
do {
System.out.println("Please, Enter the terminal break interval ");
String temp = scanner.nextLine();
try {
if (Integer.parseInt(temp) > 0) {
terminalBreakInterv = Integer.parseInt(temp);
isTerminalBreakInterv = true;
}
} catch (NumberFormatException e) {
System.out.println("Try again");
}
} while (!isTerminalBreakInterv);
System.out.println("Done!");
System.out.println(sessionName);
System.out.println(pomoInterv);
System.out.println(breakInterv);
System.out.println(terminalBreakInterv);
The comment on your question by scary-wombat is correct. i have used his comment to code the above.
I actually solved it, i just had to add a (scanner.next();) in the catch statement as below, it's because how the Scanner class works, see the code below,
import java.util.InputMismatchException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String sessionName;
int pomoInterv, breakInterv, terminalBreakInterv;
System.out.println("Please, Enter the session name: ");
sessionName = scanner.nextLine();
while (true) {
try {
System.out.println("Please, Enter the Pomodoro interval: ");
pomoInterv = scanner.nextInt();
break;
} catch (InputMismatchException ex) {
scanner.next();
System.out.println(ex.getMessage());
}
}
while (true) {
try {
System.out.println("Please, Enter the break interval: ");
breakInterv = scanner.nextInt();
break;
} catch (InputMismatchException ex) {
scanner.next();
System.out.println(ex.getMessage());
}
}
while (true){
try {
System.out.println("Please, Enter the terminal break interval ");
terminalBreakInterv = scanner.nextInt();
break;
} catch (InputMismatchException ex) {
scanner.next();
System.out.println(ex.getMessage());
}
}
System.out.println("Done!");
System.out.println(sessionName);
System.out.println(pomoInterv);
System.out.println(breakInterv);
System.out.println(terminalBreakInterv);
}
}
check this answer
https://stackoverflow.com/a/47852703/12565862
Because you don't have a break; in catch block. When there is exception, you print the message. But once it comes out of catch block, while loop still satisfies its condition and execute again. Try adding break; inside catch block too.
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.
Is it possible to repeat more than one try-catch statements in one block without creating another (nested) while loop or having to repeat the whole loop again?
For example:
while(true) {
//try-catch 1: if the user input is correct continue, or ask him to repeat this input
//try-catch 2: if the user input is correct continue, or ask him to repeat this input
break; //after it's done
}
Another Ex:
import java.util.InputMismatchException;
import java.util.Scanner;
public class Example {
public static void main(String[] args) {
while (true) {
Scanner scan1 = new Scanner(System.in);
Scanner scan2 = new Scanner(System.in);
try {
System.out.print("Enter a number: ");
scan1.next();
} catch (InputMismatchException e) {
//do something to repeat this task
}
try {
System.out.println("Enter another number: ");
scan2.next();
} catch (InputMismatchException e) {
//do something to repeat this task
}
break;
}
}
}
The flow you are describing doesn't require nested loops, but it does require two separate loops.
I think you want something like this:
Scanner scan1 = new Scanner(System.in);
Scanner scan2 = new Scanner(System.in);
while (true) {
try {
System.out.print("Enter a number: ");
scan1.next();
break;
} catch (InputMismatchException e) {
System.out.println("Error! That wasn't a number!");
// didn't reach a break statement, will repeat.
}
}
while (true) {
try {
System.out.print("Enter another number: ");
scan2.next();
break;
} catch (InputMismatchException e) {
System.out.println("Error! That wasn't a number!");
// didn't reach a break statement, will repeat.
}
}
Notice that this is a lot of repeated code, so you could improve it by extracting a method to call - something like:
private static int getNumber(String prompt, Scanner scan) {
while (true) {
try {
System.out.print(prompt);
return scan.nextInt();
} catch (InputMismatchException e) {
System.out.println("Error! Try again.");
}
}
}
public static void main(String[] args) {
Scanner scan1 = new Scanner(System.in);
Scanner scan2 = new Scanner(System.in);
int num1 = getNumber("Enter a number: ", scan1);
int num1 = getNumber("Enter another number: ", scan2);
}
Disclaimer: my Java is rusty, so the above code may not be exactly right, but I hope you get the idea.
Here is a simple example where the application will not continue unless there is a valid number supplied.
public class TestInput
{
public static boolean validInput(Scanner scan)
{
System.out.print("Enter a number: ");
try
{
String stringNumber = scan.next();
try
{
int myInt = Integer.parseInt(stringNumber);
}
catch (NumberFormatException e)
{
System.out.println("No I meant a Number; " + stringNumber + " is not a number");
return false;
}
}
catch (InputMismatchException e)
{
return false;
}
return true;
}
public void doTheWork()
{
Scanner scan = new Scanner(System.in);
if (!validInput(scan))
{
doTheWork();
}
System.out.println("All Good");
}
public static void main(String[] args)
{
TestInput testInput = new TestInput();
testInput.doTheWork();
}
}
Here is a simple example to reuse a method to get multiple inputs
public class TestInput
{
public static int getNumberInput(String message)
{
Scanner scan = new Scanner(System.in);
try
{
System.out.print(message);
String stringNumber = scan.next();
try
{
return Integer.parseInt(stringNumber);
}
catch (NumberFormatException e)
{
return getNumberInput("No I meant a Number; " + stringNumber + " is not a number");
}
}
catch (InputMismatchException e)
{
//do something to repeat this task
}
return getNumberInput(message);
}
public void doTheWork()
{
int oneParam = getNumberInput("Enter a number: ");
int twoParam = getNumberInput("Enter another number: ");
System.out.println("Your first input is " + oneParam);
System.out.println("Your second input is " + twoParam);
}
public static void main(String[] args)
{
TestInput testInput = new TestInput();
testInput.doTheWork();
}
}