I'm trying to process how to use try-catch. I understand it'll 'try' the main code, and if it doesn't work it'll catch it and execute something different. I want to also keep prompting the user to enter a proper value.
I keep getting the inputmismatch exception error, even if I set my catch to have that in its block.
To clarify: The try-catch is going to be there for when I ask the user for ints on how long they plan to stay, and what floor they'd like to be on. Therefore, the errors I'd like to handle involve non-integers and if they are out of bounds of the 'hotel'.
Here is my code:
public class Hotel{
public static void main(String[] args) throws IOException {
int choice = 0;
String guestName = " ";
int stayTime = 0;
int floorPref = 0;
System.out.println("Welcome to the Hotel California.");
Scanner sc = new Scanner(System.in);
Room[][] hotel = new Room[8][20];
for(int i = 0; i< hotel.length; i++){
for(int j = 0; j<hotel[i].length;j++){
hotel[i][j] = new Room(0,false,"none",0.00,0);
int roomNum = ((i+1) * 100) + (j + 1);
hotel[i][j].setRoom(roomNum);
int roomCheck = hotel[i][j].getRoomNumber();
if(roomCheck > 500){
hotel[i][j].setPrice(350.00);
}
else if(roomCheck < 500){
hotel[i][j].setPrice(200.00);
}
}
}
// Guest check-in interface.
do{
System.out.println("What business have you today?");
System.out.println("1. Guest Registration");
System.out.println("2. Guest Checkout");
System.out.println("3. Show me occupied rooms");
System.out.println("4. Exit");
choice = sc.nextInt();
if(choice == 1){
System.out.println("Tell us about yourself.");
System.out.println("Please input your name:");
guestName = sc.next();
System.out.print("How long are you planning to stay?");
try{
stayTime = sc.nextInt();
}
catch(InputMismatchException e){
System.out.println("Please input a valid integer.");
stayTime = sc.nextInt();
}
System.out.println("Great. What floor would you like to be on? Enter a number 1-8, 0 for no preference.");
floorPref = sc.nextInt();
System.out.println("The following rooms are available based on your floor preference (floors 1-8, 0 for no preference: ");
}
if(floorPref > 0){
for(int i = 0; i < hotel[floorPref].length; i++){
if(hotel[floorPref][(i)].getOccupation() == false){
System.out.print("Rooms " + hotel[floorPref-1][i].getRoomNumber() + ", ");
}
}
System.out.println("Are available today.");
}
else if(floorPref == 0){
for(int i = 0; i < hotel.length; i++){
for(int j = 0; j < hotel[i].length; j++){
System.out.print("Room " + hotel[i][j].getRoomNumber() + ", ");
}
}
System.out.println("Is available.");
}
}while(choice != 4);
}
}
The try-catch block you have right now is flawed, because once you get inside the catch block, all the user has to do is enter something that's not an integer to crash your whole program.
Instead, to get stayTime and all the other ints you pull from the Scanner, create a separate function that blocks until the user enters an int:
private static int parseIntFromScanner(Scanner sc) {
while(true) {
try {
int toReturn = sc.nextInt();
return toReturn;
} catch(InputMismatchException ime) {
//Continue back to the top of the loop, ask again for the integer
}
}
}
try to put this at the top of your code
import java.util.InputMismatchException;
import java.util.Scanner;
import java.io.IOException;
and in your public static void throws IOException main delete throws IOException so it only remains public static void main
hope it will works
the following is small piece of code to divide.If user enters zero then it will go to catch and you can also enter number.
Note
the code will go catch only once.I have used depracated methods.This is just an example as per your requirement.
import java.io.DataInputStream;
import java.io.IOException;
public class test1 {
public static void main(String args[]) throws NumberFormatException, IOException
{
DataInputStream d=new DataInputStream(System.in);int x;
try {
x=Integer.parseInt(d.readLine());
int z=8;
System.out.println(z/x);
} catch (Exception e)
{
System.out.println("can not divide by zero");
x=Integer.parseInt(d.readLine());
}
}
}
To answer your question as to why it's still failing: all of the calls to nextInt() can throw InputMistmatchException, not only the one put inside the try part of a try-catch block. And that's what's happening now.
Another issue is calling nextInt a second time inside the catch block. Exceptions thrown inside a catch block require their own handling, separate from the try-catch block to which they belong. So, if nextInt inside the catch block throws an InputMismatchException, it will leave the try-catch block and work its way out from there. In the case of the posted code, that means main will terminate on the exception.
A side point, as musical_coder pointed out, the code needs to loop with the validation. Otherwise, it would end up without setting values if the second attempt to read a value fails.
BTW, see this: Redoing a try after catch in Java, for a tip on scanner use that will lead to more headaches. In fact, it tells why the handling with the try-catch you have now will always end up terminating the program. (it's a matter of how Scanner functions)
Related
I am a Java beginner and I am learning to manage Exceptions and 2D arrays.
I am doing an exercise to plot in a 2D array the result of the sales of different car models.
I have mixed the way to deal with Exception by using a try catch or by throwing a custom Exception. On a custom Exception I have an issue I am not able to solve.
In the Seller class:
In line 16, IDE tells me that the variable "correct" initializer to
false is redundant
In line 26, IDE tells me that the while condition is always false.
I wanted to declare the boolean correct inside the inner loop to check for each value if the input was correct (an integer) or not and then to change the value to true at the end of the try in case the parseInt was successful. By reading the comments from the IDE I understand that the boolean correct is never changed to true even if I select an integer but I do not understand why.
import java.util.Scanner;
public class Sellers {
public static void main(String[] args) throws NumberArrayException {
Scanner myObj = new Scanner(System.in);
int nbrOfSellers = CheckInput.control("Enter the number of sellers = ");
int nbrOfModels = CheckInput.control("Enter the number of models = ");
int[][] sales = new int[nbrOfSellers][nbrOfModels];
String[] nameOfSellers = Characters.construction("seller", nbrOfSellers);
String[] nameOfModels = Characters.construction("model", nbrOfSellers);
for(int i = 0; i < nbrOfSellers; i++) {
for(int j = 0; j < nbrOfModels; j++) {
boolean correct = false;
System.out.print("Enter the sales for the seller " + nameOfSellers[i] + " for the model " + nameOfModels[i] + " = ");
do {
try {
String input = myObj.nextLine();
sales[i][j] = Integer.parseInt(input);
correct = true;
} catch (NumberFormatException e) {
throw new NumberArrayException();
}
}while (!correct) ;
}
}
for(int i = 0; i < nbrOfSellers; i++) {
for(int j = 0; j < nbrOfModels; j++) {
System.out.print(sales[i][j] + " ");
}
System.out.println();
}
}
}
import java.util.Scanner;
public class Characters {
public static String[] construction(String character, int maxSize) {
Scanner myObj = new Scanner(System.in);
String[] myArray = new String[maxSize];
for(int i = 0; i < maxSize; i++) {
System.out.print("Enter the name of the " + character + " ");
myArray[i] = myObj.nextLine();
}
return myArray;
}
}
import java.util.Scanner;
public class CheckInput {
public static int control(String message) {
boolean correct = false;
int number = -1;
Scanner myObj = new Scanner(System.in);
do {
try {
System.out.print(message);
String input = myObj.nextLine();
number = Integer.parseInt(input);
correct = true;
} catch(NumberFormatException e) {
System.out.println("Enter a number");
}
}while(!correct);
return number;
}
}
public class NumberArrayException extends RuntimeException {
public NumberArrayException() {
super();
}
}
There are two ways that this do-while-loop can exit: correct is true or an exception is thrown.
Technically, an exception can only be thrown in the two lines above the statement correct = true. Since you are throwing the NumberArrayException inside the loop, it will either exit because of it, or correct will be set true.
When we reach while (!correct), then correct is always true since it got set. Otherwise we would have exited with an exception. Therefore, this loop never has a second iteration.
To fix it, you can just avoid throwing an exception when the provided input cannot be parsed. The loop will then let the user enter another integer.
do {
try {
String input = myObj.nextLine();
sales[i][j] = Integer.parseInt(input);
correct = true;
} catch (NumberFormatException e) {
// output error message for the user here
}
} while (!correct);
Your code is pretty good and well structured. Actually, you should compare the source of CheckInput.control to see why it does not have the mentioned warnings: you initialize the local variable correct as it should be and no exception is thrown in case of invalid input, thus letting the user to correct it. If you throw an exception from inside do-while loop as in the main method, then the false value of correct is never used.
You should resolve these warnings by reusing existing CheckInput.control when initializing the 2D sales array. Also there's a typo when creating nameOfModels -- nbrOfModels should be passed as an argument.
String[] nameOfSellers = Characters.construction("seller", nbrOfSellers);
String[] nameOfModels = Characters.construction("model", nbrOfModels);
for(int i = 0; i < nbrOfSellers; i++) {
for(int j = 0; j < nbrOfModels; j++) {
sales[i][j] = CheckInput.control("Enter the sales for the seller " + nameOfSellers[i] + " for the model " + nameOfModels[i] + " = ");
}
}
When you throw an exception it exits the function and throws the exception. So instead of throwing the exception in the catch block just print and error message. So that user can understand the error and enter input again.
do {
try {
String input = myObj.nextLine();
sales[i][j] = Integer.parseInt(input);
correct = true;
} catch (NumberFormatException e) {
System.out.println("Wrong input format. Please enter a number");
}
}while (!correct) ;
I want the program to not crash when the user inputs anything other than a number. For example, if someone enters random letters, it should display a message saying, "input not valid, please enter a valid integer". Then prompting them if they would want to continue or not.
public static void main(String[] args) throws IOException {
BufferedWriter out = new BufferedWriter(new FileWriter("outDataFile.txt"));
Scanner input=new Scanner(System.in);
int choice = 0;
String repeat;
//Loop repeats program until user quits
do
{
//Loop repeats until a valid input is found
do
{
//Asks for number and reads value
System.out.print("\nEnter an integer and press <Enter> ");
choice = input.nextInt();
//Prints error if invalid number
if(choice <= 0)
System.out.println("Invalid Input.");
There are multiple ways to achieve that:
First is to catch the exception thrown by the Scanner and flag the loop to carry on when an exception is caught. This is not a good practise since the exception thrown by the Scanner, InputMismatchException, is an unchecked exception. Meaning the cause of this exception can be easily caught by an if/else statement.
In your case, you should try to receive the input as a String, then validate the input if it looks like a number:
Loop per character approach:
String string = scanner.nextLine();
for (int i = 0; i < string; i++) {
char ch = string.charAt(i);
if (!Character.isDigit(ch)) {
System.out.println("Input is not a number");
break; // stop the for-loop
}
}
int input = Integer.parseInt(string);
RegEx approach:
String numericRegex = "[0-9]+";
String string = scanner.nextLine();
if (!string.matches(numericRegex)) {
System.out.println("Input is not a number");
}
int input = Integer.parseInt(string);
These are popular approach to your problem, it is now up to you on how will you control your loops to repeat when an invalid input is encountered.
Use a simple try catch that will catch and a simple recursive method as such:
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test
{
public static void main(String[] args)
{
System.out.println(getUserInput());
}
private static int getUserInput()
{
int choice = 0;
Scanner input = new Scanner(System.in);
System.out.println("Enter a value");
try
{
choice = input.nextInt();
} catch (InputMismatchException exception)
{
System.out.println("Invalid input. Please enter a numeric value");
getUserInput();
}
return choice;
}
}
I am needing to stop the user from entering a string value.
Here is what I've tried so far.
import java.util.InputMismatchException;
import java.util.Scanner;
import java.util.Random;
public class guessinggame
{
public static void main (String[] args)
{
int randomNumber = new Random().nextInt(10);
System.out.println("My number is " + randomNumber + ". ");
System.out.println("I’m thinking of a number between 0 and 9.");
System.out.println("What is your guess:");
Scanner keyboard = new Scanner(System.in);
int guess = keyboard.nextInt();
guess1(guess);
int input = 0;
try{
input = keyboard.nextInt();
}catch (InputMismatchException e){
int guess = keyboard.nextInt();
System.out.println("Invalid.");
}
if (guess < randomNumber) {
System.out.print("your guess was too low.");
}else if (guess > randomNumber){
System.out.print("your guess was too high.");
}else if (guess == randomNumber){
System.out.print("your guess was correct.");
}
}
}
The error I am receiving is: Duplicate local variable guess preventing program from compiling, however I imagine I am also missing bits from making this program do what I want it to.
It needs to only accept integer values as input between 0-9. Anything else (including strings) should return as invalid.
The compiler is giving you the error because you have declared guess twice:
Once at the beginning with int guess = keyboard.nextInt();
Then in the catch clause with int guess = keyboard.nextInt(); again
Also note that you readInt() several times in your code, meaning that you are trying to get user input several times. You should reference guess in your code instead.
If you are often having trouble with compile errors and such, you may want to use an IDE such as Eclipse.
The main error is that you are re-declaring guess in the catch block.
What you really need to do is loop around if invalid data is input
int guess = -1; // some magic number
while (guess <= -1) { // we do not want negative number
try{
guess = keyboard.nextInt();
}catch (InputMismatchException e){
System.out.println("Invalid - try again.");
continue;
}
if (guess >= 0) {
break;
}
System.out.println("We want between 0 and 9 - try again.");
}
// now we have valid value for guess
Edit
As per new requirements
int guess = -1; // some magic number
try{
guess = keyboard.nextInt();
}catch (InputMismatchException e){
// do not need to do anything
}
if (guess < 0) {
System.out.println("Invalid - will exit.");
System.exit(-1);
}
// now we have valid value for guess
int guess = keyboard.nextInt();
should just be
guess = keyboard.nextInt();
I've copied part of the instructions below, and I can code pretty much every part on its own, but getting the control flow together is giving me massive doubts about my ability.
One of my biggest problems is the int gameChanger. Im supposed to immediately verify if it is a integer or not, and loop back if its not. But then Im also supposed to check to see if thebuser ever types "exit". But the input variable for my scanner instance is an integer... So Im stumped. I can use a try catch to check the missmatchexception once the input is being read in, but that doesnt solve the exit issue nor am I able to come up with solid logic to get the try catch to loop back if it indeed isnt an integer. Im thinking a do while loop but I havent gotten it to work.
Instructions:
You can whether the input is a number before attempting to consume it.
int num;
while (true) {
if (scanner.hasNextInt()) {
num = scanner.nextInt();
break;
} else {
// read whatever is there instead.
String line = scanner.nextLine();
if (line.equals("exit"))
System.exit(0);
System.out.println("Please enter a number");
}
}
System.out.println("Number entered " + num);
This gets the job done. Try it out.
import java.util.Scanner;
public class MyCode
{
public static void main(String[] args)
{
String gameInput = ".";
int gameNumber = 0;
boolean inputLoop = true;
Scanner input = new Scanner(System.in);
while(inputLoop == true)
{
try
{
System.out.print("Please enter a valid game number: ");
gameInput = input.next();
if(gameInput.equals("exit"))
{
System.out.println("Program will now end. Goodbye.");
inputLoop = false;
input.close();
}
gameNumber = Integer.parseInt(gameInput);
if(gameNumber >= 20001 && gameNumber <= 21230)
{
System.out.println("You have inputted a valid game number.");
inputLoop = false;
input.close();
}
}
catch(NumberFormatException e)
{
if(!gameInput.equals("exit"))
{
System.err.println("Invalid game number. Please try again.");
}
}
}
}
}
There are several questions I would like to ask, please refer the comment part I have added in the code, Thanks.
package test;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test {
/* Task:
prompt user to read two integers and display the sum. prompt user to read the number again if the input is incorrect */
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean accept_a = false;
boolean accept_b = false;
int a;
int b;
while (accept_a == false) {
try {
System.out.print("Input A: ");
a = input.nextInt(); /* 1. Let's enter "abc" to trigger the exception handling part first*/
accept_a = true;
} catch (InputMismatchException ex) {
System.out.println("Input is Wrong");
input.nextLine(); /* 2. I am still not familiar with nextLine() parameter after reading the java manual, would you mind to explain more? All I want to do is "Clear Scanner Buffer" so it wont loop for the println and ask user to input A again, is it a correct way to do it? */
}
}
while (accept_b == false) {
try {
System.out.print("Input B: ");
b = input.nextInt();
accept_b = true;
} catch (InputMismatchException ex) { /*3. Since this is similar to the above situation, is it possible to reuse the try-catch block to handling b (or even more input like c d e...) exception? */
System.out.println("Input is Wrong");
input.nextLine();
}
}
System.out.println("The sum is " + (a + b)); /* 4. Why a & b is not found?*/
}
}
I am still not familiar with nextLine() parameter after reading the java manual, would you mind to explain more? All I want to do is "Clear Scanner Buffer" so it wont loop for the println and ask user to input A again, is it a correct way to do it?
The use of input.nextLine(); after input.nextInt(); is to clear the remaining content from the input stream, as (at least) the new line character is still in the buffer, leaving the contents in the buffer will cause input.nextInt(); to continue throwing an Exception if it's no cleared first
Since this is similar to the above situation, is it possible to reuse the try-catch block to handling b (or even more input like c d e...) exception?
You could, but what happens if input b is wrong? Do you ask the user to re-enter input a? What happens if you have 100 inputs and they get the last one wrong?You'd actually be better off writing a method which did this for, that is, one which prompted the user for a value and returned that value
For example...
public int promptForIntValue(String prompt) {
int value = -1;
boolean accepted = false;
do {
try {
System.out.print(prompt);
value = input.nextInt();
accepted = true;
} catch (InputMismatchException ex) {
System.out.println("Input is Wrong");
input.nextLine();
}
} while (!accepted);
return value;
}
Why a & b is not found?
Because they've not been initialised and the compiler can not be sure that they have a valid value...
Try changing it something more like.
int a = 0;
int b = 0;
Yes, it's okay. And will consume the non-integer input.
Yes. If we extract it to a method.
Because the compiler believes they might not be initialized.
Let's simplify and extract a method,
private static int readInt(String name, Scanner input) {
while (true) {
try {
System.out.printf("Input %s: ", name);
return input.nextInt();
} catch (InputMismatchException ex) {
System.out.printf("Input %s is Wrong%n", input.nextLine());
}
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int a = readInt("A", input);
int b = readInt("B", input);
System.out.println("The sum is " + (a + b));
}
I have put comment to that question line.
package test;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean accept_a = false;
boolean accept_b = false;
int a=0;
int b=0;
System.out.print("Input A: ");
while (accept_a == false) {
try {
a = input.nextInt(); // it looks for integer token otherwise exception
accept_a = true;
} catch (InputMismatchException ex) {
System.out.println("Input is Wrong");
input.next(); // Move to next other wise exception // you can use hasNextInt()
}
}
System.out.print("Input B: ");
while (accept_b == false) {
try {
b = input.nextInt();
accept_b = true;
} catch (InputMismatchException ex) {
System.out.println("Input is Wrong");
input.next();
}
}
System.out.println("The sum is " + (a + b)); // complier doesn't know wheather they have initialised or not because of try-catch blocks. so explicitly initialised them.
}
}
Check out this "nextLine() after nextInt()"
and initialize the variable a and b to zero
nextInt() method does not read the last newline character.