Java Error Handling - Is this the best way to do this? - java

I have an error in a console program I'm making, in which I can't seem to handle an error.
If a user enters an incorrect input type (such as an float where an int goes), they are reprimanded, and the program functions (even though the program shuts down, it does it my way):
while(!scanner.hasNextLong()){
System.out.println("You entered something bad.. Why do you hurt me?");
System.out.println("*Calcumatastic dies, and I hope you feel remorseful*");
try {
Thread.sleep(4000);
} catch (InterruptedException f) {
f.printStackTrace();
}
System.exit(0);
}
If a user enters, for example, a zero as a variable that cannot equal zero (due to division of zero), the user is reprimanded, and life still goes on, and the program still functions:
while (b == 0) {
System.out.println("Did you even read the instructions?? You cannot divide by zero!");
System.out.println();
System.out.println("Second Integer: ");
b = scanner.nextLong();
}
However, if a user attempts to divide by zero, THEN enters an incorrect input type, the program crashes. What am I doing wrong? I've tried entering a try/catch- while loop as I did in other instances, but it doesn't seem to do the trick:
System.out.println("Second Integer: ");
while(!scanner.hasNextLong()){
System.out.println("You entered something bad.. Why do you hurt me?");
System.out.println("*Calcumatastic dies, and I hope you feel remorseful*");
try {
Thread.sleep(4000);
} catch (InterruptedException f) {
f.printStackTrace();
}
System.exit(0);
}
b = scanner.nextLong();
while (b == 0) {
System.out.println("Did you even read the instructions?? You cannot divide by zero!");
System.out.println();
System.out.println("Second Integer: ");
b = scanner.nextLong();
}

Your issue is that your input validation appears to be consecutive. That is, you check for invalid input and then you check for zero values. You probably want to do both every time there is input.
You probably want to check for all error cases in a single loop. Something like:
System.out.println("Second Integer: ");
// a loop wrapping your other validation checks
while(scanner.hasNext()){ // while there is input:
while(!scanner.hasNextLong()){ // check for non-long input
System.out.println("You entered something bad.. Why do you hurt me?");
System.out.println("*Calcumatastic dies, and I hope you feel remorseful*");
try {
Thread.sleep(4000);
} catch (InterruptedException f) {
f.printStackTrace();
}
System.exit(0);
}
b = scanner.nextLong();
while (b == 0) { // check for non-zero input
System.out.println("Did you even read the instructions?? You cannot divide by zero!");
System.out.println();
System.out.println("Second Integer: ");
b = scanner.nextLong();
}
}

If you try to perform a division by zero, an java.lang.ArithmeticException is thrown and when you try to read a long and user enters something that can't be parsed, InputMismatchException is thrown (possibly what you call a "crash").
Error is occurring because you are using b = scanner.nextLong(); when user enters 0 without checking if user entered a valid long value.
Here is your code adjusted:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long b = 0;
do {
System.out.println("Second Integer: ");
b = readLong(scanner);
if (b == 0) {
System.out.println("Did you even read the instructions?? You cannot divide by zero!");
System.out.println();
}
} while (b == 0);
}
private static long readLong(Scanner scanner) {
if (!scanner.hasNextLong()) {
System.out.println("You entered something bad.. Why do you hurt me?");
System.out.println("*Calcumatastic dies, and I hope you feel remorseful*");
try {
Thread.sleep(4000);
} catch (InterruptedException f) {
f.printStackTrace();
}
System.exit(0);
}
return scanner.nextLong();
}

Related

JavaFX is working but the try-catch-finally code isn't

I just started my lesson about exception handling and I'm unsure of what I did wrong in my code -- what I'm aiming to do is to create a UI that asks the user how many pets they own, and checks if the input is an integer. Can anyone point out what's wrong?
I've already tried using label.setText() for my message, and I've also changed the exception I used (I tried NumberFormat).
Here's the block I used (this is the first time I encountered EH, so I find this topic kind of confusing)
String value = input.getText();
int intval = 0;
intval = Integer.parseInt(value);
try {
if (0 >= intval) {
throw new IllegalArgumentException();
}
else
throw new InputMismatchException();
}
catch(IllegalArgumentException e)
{
String outputMessage = "The number must be an integer no less than 0!";
label1.setText(outputMessage);
}
catch(InputMismatchException i) {
System.out.println("Please enter an integer.");
System.out.println("You entered: " + intval);
}
finally
{
System.out.println("You own " + intval + " pets.");
}
The exceptions I want to include are if the user entered another number type instead of an integer, and if the user entered a negative integer instead of a positive one or 0. My code runs, but the try-catch block doesn't really work.
Looks like there are lot of defects in this code! First of all you shouldn't have taken the input as String if you would have taken the input as integer you could have raised the InputMismatchException by which you could have easily told the user saying "enter only integer value", by taking input as the string you will not be able to do that.
Don't use finally block, because no matter how many exceptions are throw by your code the finally block will get executed. Even if you entered -1 at last(while executing the code) it will show "you have -1 pets:" message, as finally block gets executed not matter what happens!
I refactored the code to make it work the same way
Scanner input = new Scanner(System.in);
boolean exceptionHit = false;
int value = 0;
try {
value = input.nextInt();
if (value <= 0) {
throw new IllegalArgumentException();
}
}
catch (IllegalArgumentException e) {
String outputMessage = "The number must be an integer no less than 0!";
label1.setText(outputMessage);
exceptionHit = true;
} catch (InputMismatchException i) {
System.out.println("Please enter an integer.");
exceptionHit = true;
}
if (exceptionHit == false)
System.out.println("You have " + value + " pets");
I have removed finally block so the last message will not be displayed every time! I have added a boolean value instead of it which will be set to true if any exception is hit.

Write a program that will give the use prompt to enter two doubles value

Professor requires us to write a program that will give the user prompt to enter two float (or double) values. If the values inputted are correct then display the inputted two values. If user enters characters instead of numbers or if they enter invalid numbers then the program will display the error message and ask the user to re-enter the correct values again. It only exits when the correct input is received and displayed.
However, I wrote a program that will only work if the user input the two right doubles. Can someone helps me to change the line about catching errors? Thanks.
import java.util.Scanner;
public class FiveSecond {
static void printMenu() {
System.out.println("Welcome to get two doubles program:");
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
boolean valid = false;
double first = 0;
double second = 0;
printMenu();
while(!valid) {
System.out.print("Enter two doubles, seperate by space ");
try {
first = Double.parseDouble(scan.next());
second = Double.parseDouble(scan.next());
} catch (NumberFormatException e) {
System.out.println("Try again");
}
valid = true;
}
System.out.println("You entered valid choice: " + first + " " +second);
System.out.println("Thank you for giving your choice.");
scan.close();
}
}
Try this:
catch (NumberFormatException e) {
System.out.println("Try again");
continue;
}
In addition to the previous comments, you have to be careful, because the scanner will 'remember' a previously correct double if you don't reset it :
EDITED: Thanks to #Stultuske comment
while (!valid) {
System.out.print("Enter two doubles, seperate by space ");
try {
first = Double.parseDouble(scan.next());
second = Double.parseDouble(scan.next());
valid = true;
}
catch (NumberFormatException e) {
System.out.println("Try again");
scan.nextLine(); // <------- Important line
}
}

How to create a proper custom exception class?

I am trying to create a custom exception class and I'm having a lot of trouble. Can someone help me out! I just started programming very recently and i'm hoping to get some pointers.
import java.util.Random;
import java.util.Scanner;
import java.util.InputMismatchException;
public class GuessingGame {
public static void main(String[]args) throws BadGuessException
{
int min = 1;
int max = 10;
Random rand = new Random();
int numberToGuess = rand.nextInt((max - min) + 1) + min;
Scanner input = new Scanner(System.in);
int guess;
boolean win = false;
int numberOfTries = 0;
while (!win)
{
System.out.println("Guess a number between 1 and 10: ");
try
{
guess = input.nextInt();
numberOfTries++;
if (guess == numberToGuess)
{
win = true;
System.out.println("YOU GOT IT!");
System.out.println("It took you " + numberOfTries + " tires.");
}
else
{
throw new BadGuessException();
}
}
catch(InputMismatchException e)
{
e.getMessage();
}
}
}
}
import java.util.*;
public class BadGuessException extends Exception {
String message = "Sorry, that was an invalid guess!";
//Default Constructor
public BadGuessException()
{
super();
}
//Parameterized Constructor
public BadGuessException(Throwable cause)
{
super(cause);
}
}
I'm supposed to create 2 constructors, one default and one parametrized. If the user enters a number between 1-10, i should catch it in a catch block and print the message "invalid guess" And if they enter a letter or something, the output should be something like "Invalid input" ( Should I catch invalid input in BadGuessException and then pass it to InputMismmatch? If so, how do I do that?)
Right now, when I run this code, if I enter a letter, it doesn't crash, but the while loop iterates continuously and I'm not able to enter anymore inputs. It just keeps repeating "Guess a number between 1-10."
I'm assuming it's because once the try block executes once, it doesn't execute again? How do I fix this? Sorry for any confusion, happy to clarify! any help is much appreciated.
Also, I'm not sure how to catch 2 different exceptions at the same time. One for invalid guess and one for invalid input. :/
Exceptions should be used for handling errors, invalid input, illegal, unusual situations. If not guessing the correct number is an error, that sounds like not being a mind reader is an error. So BadGuessException is misused here.
For a better use case, how about throwing this exception for non-sense input? For example, since the program asks the user to input a number between 1 and 10, inputting -3 or 99 would be clearly an error.
The loop in the middle can be corrected accordingly:
while (!win) {
System.out.println("Guess a number between 1 and 10: ");
try {
guess = input.nextInt();
numberOfTries++;
if (guess == numberToGuess) {
win = true;
System.out.println("YOU GOT IT!");
System.out.println("It took you " + numberOfTries + " tires.");
} else if (guess < 1 || guess > 10) {
throw new BadGuessException();
}
} catch (InputMismatchException e) {
input.nextLine();
}
}
As for creating a custom exception class, you already did that. It's written a bit messy way, cleaning it up (removing unnecessary stuff) it becomes:
public class BadGuessException extends Exception {
private static final String message = "Sorry, that was an invalid guess!";
public BadGuessException() {
super(message);
}
}
UPDATE
I fixed another bug in your code: if you enter non-integer input, a InputMismatchException will be thrown. Repeatedly. Forever.
This is because the input.nextInt() doesn't consume the input if it's not valid. So the invalid input stays there, and input.nextInt() will keep failing, putting your program in an infinite loop.
To fix that, you must consume the bad input somehow, for example by reading the line:
} catch (InputMismatchException e) {
input.nextLine();
}
I think what you want is if they make a guess and it is incorrect, that your loop should run again, right? In that case, you should adjust your loop, as I've shown below. Also, where you are catching the InputMismatchException, you are swallowing the exception without printing it or handling it: This is VERY BAD PRACTICE. I've updated this too for you.
while (!win)
{
System.out.println("Guess a number between 1 and 10: ");
try
{
guess = input.nextInt();
numberOfTries++;
win=true;
if (guess == numberToGuess)
{
win = true;
System.out.println("YOU GOT IT!");
System.out.println("It took you " + numberOfTries + " tires.");
}
else
{
throw new BadGuessException();
}
}
catch(InputMismatchException e)
{
System.out.println("Please input a number betwee 1 and 10!");
}
catch(BadGuessException ex) {
System.out.println("Sorry, you guessed the wrong number!");
}
}
You never catch the BadGuessException so it will be thrown out of the while loop and program will exit. You must catch the exception inside the loop if you want to continue.
I agree with janos comment that this is not a good use of exceptions. Guessing wrong is part of the normal game flow, no?
But doing it for the practice, I'd for example pull all logic inside the loop into a new private method, let it throw this exception, and catch it in the loop. You can catch multiple exceptions in a row like this.
while (!win) {
try {
win = makeGuess();
} catch (InputMismatchException e) {
e.getMessage();
} catch (BadGuessException e) {
System.out.println("Wrong guess");
}
}
private boolean makeGuess() throws BadGuessException, InputMismatchException {
...
}

Prevent user from inputting value larger than int max?

I have some cool code that takes an int value. I let my little brother test it, and what is the first thing he does? He enters this:
12345678910
And he got this error:
User did not input a number. (Error Code 1)
Well that's not true. Is there a way to give him a different error for "value too large"? Here's my code:
try
{
number = input.nextInt();
}
catch (InputMismatchException e)
{
System.err.println("User did not input a number. (Error Code 1)");
System.exit(1);
}
Thanks!
EDIT
The code that was posted that I used has been modified. This is the code I ended up going with, but the solution is no longer in the comments.
try
{
double intitalinput = input.nextDouble();
if (intitalinput > Integer.MAX_VALUE)
{
System.err.println("User entered a number larger than " + Integer.MAX_VALUE + ". (Error Code 2)");
System.exit(2);
}
else
{
number = (int) intitalinput;
}
}
catch (InputMismatchException e)
{
System.err.println("User did not input a number. (Error Code 1)");
System.exit(1);
}
Thank you to Jay Harris for solving my issue!
EDIT THE SECOND
I added a 'less than zero' check. In case anyone else stumbles upon this question wanting similar help, I'll show the updated code here:
try
{
double intitalinput = input.nextDouble();
if (intitalinput > Integer.MAX_VALUE)
{
System.err.println("User entered a number larger than " + Integer.MAX_VALUE + ". (Error Code 2)");
System.exit(2);
}
else if (intitalinput < 0)
{
System.err.println("User entered a number smaller than 0. (Error Code 3)");
System.exit(3);
}
else
{
number = (int) intitalinput;
}
}
catch (InputMismatchException e)
{
System.err.println("User did not input a number. (Error Code 1)");
System.exit(1);
}
There is plenty of ways to achieve this, for instance check for a larger number and validate it against the max and min size of a Integer using Integer.MAX_VALUE and Integer.MIN_VALUE.
// long userInput = input.nextLong()
// or
double userInput = input.nextDouble();
// expecting an integer but user put a value larger than integer
if (userInput > Integer.MAX_VALUE || userInput < Integer.MIN_VALUE) {
// Throw your error
} else {
// continue your code the number is an int
number = (int) userInput;
}
You could try to get a long instead, but that would only raise the limit, not solve the problem.
The other way would be to get the value as a String and check if its numeric using some regular expression befor trying to convert it. if the conversion fails then the number is to big.
Try using the Scanner.hasNextInt() method:
From http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#hasNextInt()
Returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. The scanner does not advance past any input.
if (input.hasNextInt()) {
number = input.nextInt();
} else {
System.err.println("User did not input a number. (Error Code 1)");
System.exit(1);
}
If you want to detect that a number was entered, but that it might be too large to parse, try this approach:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a number:");
if (input.hasNextInt()) {
int num = input.nextInt();
System.out.println("num is " + num);
} else {
String s = input.next();
boolean isaNumber = true;
for (int i=0; i<s.length(); i++) {
if (!Character.isDigit(s.charAt(i))) {
isaNumber = false;
break;
}
}
if (isaNumber) {
System.out.println("It appears you entered a number, but it canntot "
+ "be read. It might be too large.");
} else {
System.out.println("Error parsing number.");
}
}
}
Here, I simply check if each character in the input is a digit. If so, I assume it is a number. This code could certainly be cleaned-up, and probably is not 100% bullet-proof. I just wanted to illustrate on possible approach to your question.
As shown in this answer, you could store the input in a long instead, and then check if the number is too big. Or, you could just change all your values to a long type.
A large number will not return an exception from the compiler by itself; the error you ran into may be because an int cannot hold values exceeding around 2 billion. Instead you can try declaring number as a long type.
Another solution would be to first grab the input with a string, as #karfau stated. This could be done specifically by using the length() method; if the string exceeds a certain number of characters, you will know that the input is too long.
You could surround it with a try-catch block.
See the 1st answer to this question for more detailed info.

About some simple exception handling in Java

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.

Categories

Resources