InputMismatch Avoidance with try-catch [duplicate] - java

This question already has answers here:
Why not use exceptions as regular flow of control?
(24 answers)
Closed 10 months ago.
To validate for an int input, I've seen the usage of try-catch using the InputMismatch exception. After inputting a string though, I simply get the catch code block played, then my program exits due to mismatch, but instead I want to allow the user to re-enter input. I implemented a boolean correct while loop after searching around but that still didn't do the trick.
int quantity = 0;
boolean correct = true;
while(correct){
try{
System.out.print("Input Quantity you would like to purchase: ");//Get quantity
quantity = input.nextInt();
}catch(InputMismatchException e){
System.out.println("Input must be a number");
input.nextInt();//Get the input as a string
correct = false;
}
System.out.println("Quantity: " + quantity);
}
I previously just used the Scanner's built in hasNextInt, and that works great, but wanted to test out try-catch. I've heard to use try-catch and not to use try-catch. Why would I avoid using it?

Here is the fix, use input.nextLine(); in catch and don't make the correct=false
while(correct){
try{
System.out.print("Input Quantity you would like to purchase: ");//Get quantity
quantity = input.nextInt();
}catch(InputMismatchException e){
System.out.println("Input must be a number");
input.nextLine();
continue;
}
System.out.println("Quantity: " + quantity);
}
But like others pointed out, try not to use Exceptions for general flow. Use it only for tracking unusual exceptions. So, I am discouraging you to use this code. Use, input.hasNextInt() instead

Related

Java Try-catch block, Catch block does not re-prompt the user for a new value [duplicate]

This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 6 years ago.
I am new to Java and would like to ask you a question.
I have written the below code where "numOfThreads" should be assigned a valid int value by the user through the Console.
However, I would like to achieve a result where if the input is incorrect and we go in the catch block, the user should be re-prompted to enter "numOfThreads" until it is of correct type and range.
For some reason I seem to go into infinite loop. Can you please assist? Thanks :)
import java.util.Scanner;
public class Main {
public static void main(String args[]){
int numOfThreads;
boolean promptUser = true;
Scanner keyboard = new Scanner(System.in);
while (promptUser)
{
try{
numOfThreads = keyboard.nextInt();
promptUser = false;
}
catch(Exception e){
System.out.println("Entry is not correct and the following exception is returned: " + e);
numOfThreads = keyboard.nextInt(); // DOES NOT SEEM TO BE ASKING FOR A NEW INPUT
}
}
}
}
it doesn´t because nextInt tries to consume the last token. When there is an invalid input it can´t consume it. As a result a following nextInt call wont be able to consume it either. write a keyboard.nextLine before numOfThreads = keyboard.nextInt(); and you are fine.
catch(Exception e){
System.out.println("Entry is not correct and the following exception is returned: " + e);
// this consumes the invalid token now
keyboard.nextLine();
numOfThreads = keyboard.nextInt(); // It wasn´t able to get the next input as the previous was still invalid
// I´d still rewrite it a little bit, as this keyboard.nextInt is now vulnerable to throw a direct exception to the main
}

Asking user input for an integer in java

I'm doing a basic java tutorial that is basically a mad libs program. The idea came up in the tutorial to try making sure a user is at least 13, but the example hard coded the age into the program. I wanted to try getting the age from the user, but at this point, my code gives me an error because a "string cannot be converted to an integer." Looking at my code, I don't see why it's giving me this error. Here is what I used:
int age = console.readLine("Enter your age: ");
if (age < 13) {
//enter exit code
console.printf("Sorry but you must be at least 13 to use this program.\n");
System.exit(0);
}
I have looked for other answers, but I didn't see any that I could discern from the specific problems they were trying to fix.
You should use
try{
int age = Integer.parseInt(console.readLine("Enter your age: "));
// do stuff
} catch (NumberFormatException e) {
// User did not enter a number
}
Java doesn't cast between the two automatically. The above method however will throw an exception when you don't enter a number which you will have to handle
You can use
Scanner input = new Scanner(System.in);
int Age = input.nextInt();
input.nextLine();
Okay, I'm not sure if it's cool to answer your own question. I managed to get this to work, so in case someone else encounters the same problem. Here is the code that I used:
String ageAsString = console.readLine("Enter your age: ");
int age = Integer.parseInt(ageAsString);
if (age < 13) {
//enter exit code
console.printf("Sorry but you must be at least 13 to use this program.\n");
System.exit(0);
}

try-catch statement not returning to try block when catching exception

I have a method that a wrote. This method just scans for a user entered integer input. If the user enters a character value it will throw an input mismatch exception, which is handled in my Try-Catch statement. The problem is that, if the user inputs anything that is not a number, and then an exception is thrown, I need the method to loop back around to ask the user for input again. To my understanding, a Try catch statement automatically loops back to the Try block if an error is caught. Is this not correct? Please advise.
Here is my method (it's pretty simple):
public static int getMask() {
//Prompt user to enter integer mask
Scanner keyboard = new Scanner(System.in);
int output = 0;
try{
System.out.print("Enter the encryption mask: ");
output = keyboard.nextInt();
}
catch(Exception e){
System.out.println("Please enter a number, mask must be numeric");
}
return output;
}//end of getMask method
Here is how the method is implemented into my program:
//get integer mask from user input
int mask = getMask();
System.out.println("TEMP mask Value is: " + mask);
/***********************************/
Here is my updated code. It creates an infinate loop that I can't escape. I don't understand why I am struggling with this so much. Please help.
public static int getMask() {
//Prompt user to enter integer mask
Scanner keyboard = new Scanner(System.in);
int output = 0;
boolean validInput = true;
do{
try {
System.out.print("Enter the encryption mask: ");
output = keyboard.nextInt();
validInput = true;
}
catch(InputMismatchException e){
System.out.println("Please enter a number, mask must be numeric");
validInput = false;
}
}while(!(validInput));
return output;
/********************/FINAL_ANSWER
I was able to get it finally. I think I just need to study boolean logic more. Sometimes it makes my head spin. Implementing the loop with an integer test worked fine. My own user error I suppose. Here is my final code working correctly with better exception handling. Let me know in the comments if you have any criticisms.
//get integer mask from user input
int repeat = 1;
int mask = 0;
do{
try{
mask = getMask();
repeat = 1;
}
catch(InputMismatchException e){
repeat = 0;
}
}while(repeat==0);
To my understanding, a Try catch statement automatically loops back to the Try block if an error is caught. Is this not correct?
No this is not correct, and I'm curious as to how you arrived at that understanding.
You have a few options. For example (this will not work as-is but let's talk about error handling first, then read below):
// Code for illustrative purposes but see comments on nextInt() below; this
// is not a working example as-is.
int output = 0;
while (true) {
try{
System.out.print("Enter the encryption mask: ");
output = keyboard.nextInt();
break;
}
catch(Exception e){
System.out.println("Please enter a number, mask must be numeric");
}
}
Among others; your choice of option usually depends on your preferred tastes (e.g. fge's answer is the same idea but slightly different), but in most cases is a direct reflection of what you are trying to do: "Keep asking until the user enters a valid number."
Note also, like fge mentioned, you should generally catch the tightest exception possible that you are prepared to handle. nextInt() throws a few different exceptions but your interest is specifically in an InputMismatchException. You are not prepared to handle, e.g., an IllegalStateException -- not to mention that it will make debugging/testing difficult if unexpected exceptions are thrown but your program pretends they are simply related to invalid input (and thus never notifies you that a different problem occurred).
Now, that said, Scanner.nextInt() has another issue here, where the token is left on the stream if it cannot be parsed as an integer. This will leave you stuck in a loop if you don't take that token off the stream. To that end you actually want to use either next() or nextLine(), so that the token is always consumed no matter what; then you can parse with Integer.parseInt(), e.g.:
int output = 0;
while (true) {
try{
System.out.print("Enter the encryption mask: ");
String response = keyboard.next(); // or nextLine(), depending on requirements
output = Integer.parseInt(response);
break;
}
catch(NumberFormatException e){ // <- note specific exception type
System.out.println("Please enter a number, mask must be numeric");
}
}
Note that this still directly reflects what you want to do: "Keep asking until the user enters a valid number, but consume the input no matter what they enter."
To my understanding, a Try catch statement automatically loops back to the Try block if an error is caught. Is this not correct?
It is indeed not correct. A try block will be executed only once.
You can use this to "work around" it (although JasonC's answer is more solid -- go with that):
boolean validInput = false;
while (!validInput) {
try {
System.out.print("Enter the encryption mask: ");
output = keyboard.nextInt();
validInput = true;
}
catch(Exception e) {
keyboard.nextLine(); // swallow token!
System.out.println("Please enter a number, mask must be numeric");
}
}
return output;
Further note: you should NOT be catching Exception but a more specific exception class.
As stated in the comments, try-catch -blocks don't loop. Use a for or while if you want looping.

try/catch infinite loop? [duplicate]

This question already has answers here:
How to handle infinite loop caused by invalid input (InputMismatchException) using Scanner
(5 answers)
Closed 5 years ago.
Help, I am completely new to java and I am trying to create a loop that will ask for an input from the user which is to be a number. If the user enters anything other than a number I want to catch the exception and try again to get the correct input. I did this with a while loop however it does not give the opportunity after the error for the user to type in anything it loops everything else but that. Please help me to see understand what is wrong and the correct way to do this... Thank you. This is what I have:
import java.util.Scanner;
import java.util.InputMismatchException;
public class simpleExpressions {
public static void main (String[] args) {
Scanner keyboard = new Scanner(System.in);
while ( true ) {
double numOne;
System.out.println("Enter an Expression ");
try {
numOne = keyboard.nextInt();
break;
} catch (Exception E) {
System.out.println("Please input a number only!");
} //end catch
} //end while
} //end main
while ( true )
{
double numOne;
System.out.println("Enter an Expression ");
try {
numOne = keyboard.nextInt();
break;
}
catch (Exception E) {
System.out.println("Please input a number only!");
}
This suffers from several problems:
numOne hasn't been initialized in advance, so it will not be definitely assigned after the try-catch, so you won't be able to refer to it;
if you plan to use numOne after the loop, then you must declare it outside the loop's scope;
(your immediate problem) after an exception you don't call scanner.next() therefore you never consume the invalid token which didn't parse into an int. This makes your code enter an infinite loop upon first encountering invalid input.
Use keyboard.next(); or keyboard.nextLine() in the catch clause to consume invalid token that was left from nextInt.
When InputMismatchException is thrown Scanner is not moving to next token. Instead it gives us opportunity to handle that token using different, more appropriate method like: nextLong(), nextDouble(), nextBoolean().
But if you want to move to other token you need to let scanner read it without problems. To do so use method which can accept any data, like next() or nextLine(). Without it invalid token will not be consumed and in another iteration nextInt() will again try to handle same data throwing again InputMismatchException, causing the infinite loop.
See #MarkoTopolnik answer for details about other problems in your code.
You probably want to use a do...while loop in this case, because you always want to execute the code in the loop at least once.
int numOne;
boolean inputInvalid = true;
do {
System.out.println("Enter an expression.");
try {
numOne = keyboard.nextInt();
inputInvalid = false;
} catch (InputMismatchException ime) {
System.out.println("Please input a number only!");
keyboard.next(); // consume invalid token
}
} while(inputInvalid);
System.out.println("Number entered is " + numOne);
If an exception is thrown then the value of inputInvalid remains true and the loop keeps going around. If an exception is not thrown then inputInvalid becomes false and execution is allowed to leave the loop.
(Added a call to the Scanner next() method to consume the invalid token, based on the advice provided by other answers here.)

Catching an InputMismatchException until it is correct [duplicate]

This question already has answers here:
How to handle infinite loop caused by invalid input (InputMismatchException) using Scanner
(5 answers)
How to use Scanner to accept only valid int as input
(6 answers)
Closed 5 years ago.
I am trying add catch blocks to my program to handle input mismatch exceptions. I set up my first one to work inside of a do while loop, to give the user the opportunity to correct the issue.
System.out.print("Enter Customer ID: ");
int custID=0;
do {
try {
custID = input.nextInt();
} catch (InputMismatchException e){
System.out.println("Customer IDs are numbers only");
}
} while (custID<1);
As it stands, if I try to enter a letter, it goes into an infinite loop of "Customer IDs are numbers only".
How do I make this work properly?
Be aware that 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.
To avoid "infinite loop of "Customer IDs are numbers only".", You need to call input.next(); in the catch statement to to make it possible to re-enter number in Console
From
statement
catch (InputMismatchException e) {
System.out.println("Customer IDs are numbers only");
To
catch (InputMismatchException e) {
System.out.println("Customer IDs are numbers only");
input.next();
}
Example tested:
Enter Customer ID: a
Customer IDs are numbers only
b
Customer IDs are numbers only
c
Customer IDs are numbers only
11
What's happening is that you catch the mismatch, but the number "wrong input" still needs to be cleared and a .next() should be called. Edit: since you also require it to be greater than or equal to 1 per your do/while
boolean valid = false;
while(!valid) {
try {
custID = input.nextInt();
if(custID >= 1) //we won't hit this step if not valid, but then we check to see if positive
valid = true; //yay, both an int, and a positive one too!
}
catch (InputMismatchException e) {
System.out.println("Customer IDs are numbers only");
input.next(); //clear the input
}
}
//code once we have an actual int
Why not use a scanner object to read it with Scanner.readNextInt()?
I got it, this is solution you are looking for:
public class InputTypeMisMatch {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int custID=0;
System.out.println("Please enter a number");
while (!input.hasNextInt()) {
System.out.println("Please enter a number");
input.next();
}
custID = input.nextInt();
}
}

Categories

Resources