Handling InputMismatchException in a While-Loop - java

So I have a while-loop where you have 3 options to choose from and you choose them by inserting a number on standard input using a scanner, my code is like this:
int option;
String request;
Scanner input2 = new Scanner(System.in);
System.out.println("Choose an option:\n" + "1-Get camera information\n" + "2-Submit Data\n"
+ "3-Exit");
while(true){
try {
option = input2.nextInt();
if (option == 1) {
System.out.println("Camera name:");
request = input2.nextLine();
while (request.length() < 3 || request.length() > 15) {
System.out.println("Name has to be between 3 and 15 characters, insert a new one:");
request = input2.nextLine();
}
CamInfoRequest info_request = CamInfoRequest.newBuilder().setName(request).build();
if (stub.camInfo(info_request).getReturn() != 0) {
System.out.println("Camera does not exist");
} else {
System.out.println(stub.camInfo(info_request).getLatitude() + " " + stub.camInfo(info_request).getLongitude());
}
} else if (option == 2) {
System.out.println("submit");
} else if(option ==3){
break;
} else{
System.out.println("Invalid option.");
}
}catch(InputMismatchException e){
System.out.println("Invalid input");
}
}
So the way this is the code enters in an infinite loop when it catches the exception where it keeps printing "Invalid input", I tried using input2.next() at the catch but then he waits for another input I don't want, I can't use input2.close() either. What can I do?

I can't use input2.close() either.
You should never close the Scanner instance for System.in as it also closes the System.in.
I tried using input2.next() at the catch but then he waits for another
input I don't want
Use Scanner::nextLine instead of Scanner::next, Scanner::nextInt etc. Check Scanner is skipping nextLine() after using next() or nextFoo()? to learn why.
Also, try to use do...while wherever you need to ask the user to enter the data again in case of an invalid entry.
Given below is a sample code incorporating these points:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int option;
boolean valid;
Scanner input2 = new Scanner(System.in);
do {
valid = true;
System.out.println("Choose an option:\n" + "1-Get camera information\n" + "2-Submit Data\n" + "3-Exit");
try {
option = Integer.parseInt(input2.nextLine());
if (option < 1 || option > 3) {
throw new IllegalArgumentException();
}
// ...Place here the rest of code (which is based on the value of option)
} catch (IllegalArgumentException e) {
System.out.println("This is an invalid entry. Please try again.");
valid = false;
}
} while (!valid);
}
}
A sample run:
Choose an option:
1-Get camera information
2-Submit Data
3-Exit
abc
This is an invalid entry. Please try again.
Choose an option:
1-Get camera information
2-Submit Data
3-Exit
6
This is an invalid entry. Please try again.
Choose an option:
1-Get camera information
2-Submit Data
3-Exit
2
Feel free to comment in case of any further doubt/issue.

Just Put the Scanner statement inside your try block
while (true) {
try {
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();
if (option == 1) {

Related

Error handling for integer from user isn't working

I'm making a small word game which requires the user to choose from options 1 to 3, 1 and 2 being a game and 3 being exit. I have the error handling set for the correct integer but not sure why the program crashes when the user inputs something thats not an integer.
import java.util.Scanner;
public class Small_Programming_Assignment {
public static void main(String[] args) {
getSelection();
substringProblem();
pointsProblem();
}
public static void getSelection() {
Scanner sc = new Scanner(System.in);
System.out.println("");
System.out.println("Welcome to the Word Games program menu.");
System.out.println("Select from one of the following options.");
System.out.println("1. Substring problem.");
System.out.println("2. Points problem.");
System.out.println("3. Exit.");
System.out.println("Enter your selection: ");
int choice = sc.nextInt();
if (choice == 1) {
substringProblem();
}
else if (choice == 2) {
pointsProblem();
}
else if (choice == 3) {
System.out.println("Goodbye!");
System.exit(0);
}
else if (!sc.hasNextInt() ) {
System.out.println("Invalid option. Try again.");
getSelection();
} else {
System.out.println("Invalid option. Try again.");
getSelection();
}
}
public static void substringProblem() {
System.out.println("Substring Problem");
getSelection();
}
public static void pointsProblem() {
System.out.println("Points Problem");
getSelection();
}
}
I'm trying to uses (!sc.hasNextInt() ) but it seems the program crashes before reaching this.
As far as I see, whenever I type in a value that's not an Integer, the program throws a Runtime Exception called InputMismatchException.
According to Oracle's Java documentation:
Thrown by a Scanner to indicate that the token retrieved does not match the pattern for the expected type, or that the token is out of range for the expected type.
The program doesn't reach your "Invalid option. Try again." statement, because the exception is thrown directly after the user input, which means, you can't provide anything other than an integer through Scanner's nextInt() method.
What you could do, if you still want to use this method, would be placing it in a try/catch statement, something like below:
int choice = 0;
try {
choice = sc.nextInt();
}
catch(InputMismatchException e) {
System.out.println("Invalid option. Try again.");
getSelection();
}
if (choice == 1) {
substringProblem();
}
else if (choice == 2) {
pointsProblem();
}
else if (choice == 3) {
System.out.println("Goodbye!");
System.exit(0);
}
else {
System.out.println("Invalid option. Try again.");
getSelection();
}
This should do the job. Now, whenever a user is typing something that cannot be parsed as an Integer, the runtime exception is thrown, is caught, so the program enters the catch block, outputs "Invalid option. Try again." and "re"-calls getSelection().

why input.nextLine() keeps running the catch block when I'm inputing a value which is not an integer

Why input.nextLine() keeps running the catch block when I'm inputting a value which is not an integer? And why it is not running from input.nextInt when I'm inputting an Int value in input.nextLine()?
import java.util.InputMismatchException;
import java.util.Scanner;
public class ExceptionHandlingEg01 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int num = 0;
do{
try{
num = input.nextInt();
if(num != -1) {
System.out.println("You Entered " + num + "\nEnter -1 to exit: ");
}
else {
System.out.println("Program Exited");
}
} catch (InputMismatchException e) {
e.printStackTrace();
System.out.println("Please Enter a number");
input.nextLine();
}
} while (num != -1);
}
}
Your code moves to the catch block because your code requested an integer, but you didn't enter an integer. This is normal and expected behaviour.
It looks like you may have mis understood how the catch block works. Here is a correctly functioning version of your code that asks for a number at the start of your do/while loop:
Scanner input = new Scanner(System.in);
int num = 0;
do{
//Move the question to the top of the loop
System.out.println("Please Enter a number");
try{
num = input.nextInt();
if(num != -1) {
System.out.println("You Entered " + num + "\nEnter -1 to exit: ");
}
else {
System.out.println("Program Exited");
}
}
//This will only be called if an invalid input is entered
//Once the catch block is complete the loop will run again and ask for another number
catch (InputMismatchException e) {
e.printStackTrace();
//Print the fail message here
System.out.println("That was not a number");
//The below line was removed, this is not the correct place for it. The loop already reads the number at the start
//input.nextLine();
}
} while (num != -1);
Caution: Be very careful when using next methods like nextInt() with nextLine(), your code will not read correct inputs, see here for more information: Scanner is skipping nextLine() after using next() or nextFoo()?

Stop infinite Loop when handling invalid user input - Java [duplicate]

This question already has answers here:
How to handle infinite loop caused by invalid input (InputMismatchException) using Scanner
(5 answers)
Closed 2 years ago.
I'm fairly new to programming and I'm having trouble with my program continuously looping when I try to handle a InputMisMatch exception.
I have a menu which takes in user input and then uses a switch statement to deal with the input. I am trying to make my program handle two exceptions. First is making sure that the input is actually an integer and secondly make sure the integer is within the range for the menu. I used the NextInt() method inside a try block. Inside the try block is the switch statement which uses the default case to deal with the input not being in range
However the catch block for when the user types in an input other than an integer keeps looping over and over. It seems I have not updated the user input inside the loop somewhere but I am confused as to where to update it.
For now, I'm not concerned with what is in the switch cases (although I want to implement the same looping feature inside of them as well), It's just the logic for the outer loop.
Here's my code:
Any guidance would be much appreciated. Thanks!
public class Main {
// set up scanner for user input
public static Scanner keyboard = new Scanner(System.in);
public static void main(String[] args) {
// welcome message
welcome();
//declare user choice variables
int menuSelection;
int discSelection;
boolean isInputValid = true ;
do { // keep looping until user input is valid
try {
/*
We can expect an error from user input
1. Input is not an integer
2. Input is not in range
*/
isInputValid = true;
displayMainMenu();
menuSelection = keyboard.nextInt();
System.out.println(); //print new line
//Menu Logic
switch (menuSelection) {
case 0: { // Exit Application
break;
}
case 1: { // Search
searchDiscMenu(); //Display the search menu
discSelection = keyboard.nextInt(); // get user choice
if (discSelection == 1) {
System.out.println("Disc.Music.searchMusic()");
} else if (discSelection == 2) {
System.out.println("Disc.Game.searchGame()");
}
break;
}
case 2: { // Add
addDiscMenu(); //Display add menu
discSelection = keyboard.nextInt(); // get user choice
if (discSelection == 1) {
System.out.println("Disc.Music.addMusic()");
} else if (discSelection == 2) {
System.out.println("Disc.Game.addGame();");
}
break;
}
case 3: { // Remove
removeDiscMenu(); //Display remove menu
discSelection = keyboard.nextInt(); // get user choice
if (discSelection == 1) {
System.out.println("Disc.Music.removeMusic();");
} else if (discSelection == 2) {
System.out.println("Disc.Game.removeGame();");
}
break;
}
case 4: { // View
viewDiscMenu(); //Display view menu
discSelection = keyboard.nextInt(); // get user choice
if (discSelection == 1) {
System.out.println("Disc.Music.viewMusic();");
} else if (discSelection == 2) {
System.out.println("Disc.Music.viewMusic();");
}
break;
}
case 5: { // Sort
sortDiscMenu(); //Display sort menu
discSelection = keyboard.nextInt(); // get user choice
if (discSelection == 1) {
System.out.println("Disc.Music.viewMusic();");
} else if (discSelection == 2) {
System.out.println("Disc.Music.viewMusic();");
}
break;
}
case 6: { // Write
writeDiscMenu(); //Display write menu
discSelection = keyboard.nextInt(); // get user choice
if (discSelection == 1) {
System.out.println("Disc.Music.viewMusic();");
} else if (discSelection == 2) {
System.out.println("Disc.Game.writeGameFile();");
}
break;
}
case 7: { // Read
readDiscMenu(); //Display read menu
discSelection = keyboard.nextInt(); // get user choice
if (discSelection == 1) {
System.out.println("Disc.Music.readMusicFile();");
} else if (discSelection == 2) {
System.out.println("Disc.Game.readGameFile();");
}
break;
}
default: { // Handle exception
isInputValid = false;
System.out.println("Error: Selection Not In Range"); // If the input is an int but not in range
break;
}
}
} catch (InputMismatchException e) { // Handles user typing in a char, double etc. instead of int
isInputValid = false;
System.out.println("Error: Unrecognised Input");
}
} while (!isInputValid);
// Exit application safely
System.out.println("Finished"); // temporary message
}
This can happen since the nextInt() doesn't consume the new line character inserted in the buffer when pressed enter to type something in the console.
To overcome this you can add keyboard.nextLine() to the catch block so you can consume that new line character inserted in the buffer and clear it to the next input.
As others said you should wrap your input hadling in a method since you have louds of nextInt that won't be catched by your InputMismatchException. Said method should call the nextInt() catch the exception if needed and clear the buffer for new line characteres with the nextLine() if not returns the input by the user.
That way you're guarantee that you will always catching that error.
It would be better if you use a method like this to check your input :
public int rangeInt(int lower_boundary, int upper_boundary) {
int inp = -1;
try {
Scanner in = new Scanner(System.in);
inp = in.nextInt();
in.nextLine();
if (inp < lower_boundary || inp > upper_boundary) {
throw new InputMismatchException();
}
} catch (InputMismatchException e) {
System.err.println("Please enter integer between " + lower_boundary + " and " + upper_boundary);
inp = rangeInt(lower_boundary, upper_boundary);
}
return inp;
}
This method handles InputMismatchException and returns an integer between the to ints you pass

Validating input with try-catch

I am trying to learn try-catch uses and have to validate input so that the user must enter 1 or 2 for the program to continue. I believe I am close, but cannot seem to get the program to continue if the user enters something wrong such as '3' or '2.12'.
Here's what I have:
String input = " ";
try {
Scanner scan = new Scanner(System.in);
input = scan.next();
Integer.parseInt(input);
if (!input.equals("1") && !input.equals("2")) {
System.out.println();
System.out.println("Invalid imput! Please select '1' or '2':");
}
} catch (InputMismatchException a) {
System.out.println();
System.out.println("Invalid imput! Please select '1' or '2':");
}
I don't necessarily see the point of using InputMismatchException for your use case. Instead, if the input doesn't match what you expect, you can log an error and just prompt the user to input again.
But [Integer#parseInt()][1] can throw an exception if the input isn't an actual integer. In your original code you never actually use the result of this call, but I have done so in my answer. In this case, it does potentially make sense to use a try-catch block.
int result;
while (true) {
try {
Scanner scan = new Scanner(System.in);
input = scan.next();
result = Integer.parseInt(input);
} catch(Exception e) {
System.out.println("Could not parse input, please try again.");
continue;
}
if (result != 1 && result != 2) {
System.out.println("Invalid input! Please select '1' or '2':");
}
else {
break;
}
}
You should put in your condition the throw statement in able to your catch statement fetch the error, the code should be like this:
String input = " ";
try {
Scanner scan = new Scanner(System.in);
input = scan.next();
Integer.parseInt(input);
if (!input.equals("1") && !input.equals("2")) {
System.out.println();
System.out.println("Invalid imput! Please select '1' or '2':");
throw new InputMismatchException ();
}
} catch (InputMismatchException a) {
System.out.println();
System.out.println("Invalid imput! Please select '1' or '2':");
}
The code is expecting for positive integers but can input string and loop again until got a positive integer input value.
Scanner scanner = new Scanner(System.in);
Integer expectedOutput = -1;
public Integer getInputNumber(){
boolean valid;
String inputData;
do {
System.out.print("Enter Input Number: \t");
try {
inputData = scanner.nextLine();
// expecting positive integers
if (Integer.parseInt(inputData) > 0) {
expectedOutput = Integer.parseInt(inputData);
valid = true;
} else {
System.out.println("Invalid Input!");
valid = false;
}
} catch (Exception ex){
valid = false;
}
} while(!valid);
return expectedOutput;}

Password checker java program

I am trying to create a program that will check the password of the user. I want the program to end once the user gets it correct but if not I want it to ask only 4 times.
Problem: even if you do get the password correctly the program keeps on asking guess the password. And if you get it wrong it will ask incorrectly. How can I fix this?
import java.util.Scanner;
public class HowToAdd {
public static void main (String [] args){
Scanner input = new Scanner (System.in);
int trys = 0;
String password=null;
do{
System.out.println("Guess the password");
password = input.next();
if(password.equalsIgnoreCase("Password")){
System.out.println("Great job");
}else{
System.out.println("Try again");
input.next();
trys++;
}
}while(trys<2);
System.out.println("Try again later!");
input.close();
}
}
You just need to add a break:
if(password.equalsIgnoreCase("Password")){
System.out.println("Great job");
break;
}
Not only did I add a break to fix the problem of not leaving the loop when correct password is entered but I added a couple of other things to help you out see below:
public static void main (String [] args){
Scanner input = new Scanner (System.in);
int trys = 0;
String password=null;
System.out.println("Guess the password:");
while(trys<2)
{
password = input.next();
if(password.equalsIgnoreCase("Password")){
System.out.println("Great job");
break;
}else{
trys++;
if(trys != 2)
{
System.out.println("Try again:");
}
}
}
if(trys == 2)
{
System.out.println("Try again later!");
}
input.close();
}
Try this it will break out of the loop if it is correct using the break; statement. Also it will only display guess a password the first try then try again after that. Also it won't say try again later if they guessed right because it checks if they guessed wrong twice.
You can fix it with a break keyword, like so :
if(password.equalsIgnoreCase("Password")){
System.out.println("Great job");
break;
}
The break is explained here :
Branching Statements
What you need to implement can be done without using break statements.
Try to look at the flow of my codes.
Scanner scn = new Scanner(System.in);
int tries=0;
String pw = "";
System.out.println("Guess the password");
pw = scn.nextLine();
while(!pw.equalsIgnoreCase("Password") && tries < 3){
tries++;
System.out.println("Try again");
pw = scn.nextLine();
}
if(tries >= 3)
System.out.println("Try again later!");
else
System.out.println("Great job!");
TEST RUN 1:
Guess the password
1st try
Try again
2nd try
Try again
3rd try
Try again
last try
Try again later!
TEST RUN 2:
Guess the password
password
Great job!
Here is another variant of code:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int trys = 0;
String password = null;
// create variable for a number of tries
int numberOfCheks = 4;
do {
System.out.println("Guess the password");
password = input.nextLine();
if (password.equalsIgnoreCase("Password")) {
System.out.println("Great job");
break;
} else if (++trys == numberOfCheks) {
//Break if you've used all your tries
System.out.println("Try again later!");
break;
} else {
System.out.println("Try again");
// input.next(); - Useless. You don't handle it. Removed
}
//There is already tries number check. So 'true' can be used as the condition.
} while (true);
input.close();
}

Categories