I need help Using Exception handling with Wrong User Input. I am creating a text based game that welcomes the User and then goes to the main menu. It then tell the User the options, and then look for User input. For some Reason, whenever I input 1 or 2, It says: "Your input is invalid, please try again" And goes back to the choices. I don't know exactly where I am going wrong, hopefully someone can help me. Also, it won't catch the Mismatch Exception either. Hope you can Help! Thanks, Shandan
public static void main(String[] args) {
System.out.println("Welcome to Spec Ops!");
System.out.println("Please state your name:");
Scanner name = new Scanner(System.in);
String Name = name.next();
System.out.println("Hello "+Name);
mainMenu();
}
public static void mainMenu() {
System.out.println("1. Story Mode");
System.out.println("2. Infinant Combat");
Scanner input = new Scanner(System.in);
Object Selection = input.nextInt();
boolean validOption = true;
Integer x;
try {
x = (Integer)Selection;
} catch(ClassCastException cce){
System.out.println("Your input is invalid, please try again");
validOption = false;
} catch(InputMismatchException ime){
System.out.println("Your input is invalid, please try again");
validOption = false;
}
if(validOption) {
System.out.println("Hello!");
}
else {
mainMenu();
}
}
}
Scanner.nextInt returns ant int, so there is no need to go Object selection = scanner.nextInt(), and then cast to an int, you can merely have int selection = scanner.nextInt() and surround that in a try catch that chatches java.util.InputMismatchException, which is the exception thrown when the user types a letter and not an number
You can temporarily change your code and use the Pokemon exception handling and check the stack trace to see what kind of exception you should implement:
try {
//do something
} catch(Exception e) {
//Gotta catch 'em all!
e.printStackTrace();
}
Once you know the exact exception, put some breakpoints and refactor your code accordingly.
Also, you don't have to control the flow of your program by changing your boolean variable inside the catch blocks:
boolean isValidOption = false;
Integer x;
try {
x = (Integer)Selection;
isValidOption = true;
} catch...
When you read the name in you are using scanner.next(). This does not read in the end of line character, so when you call scanner.nextInt() it reads the new line and fails to parse as an int.
You should change the name reading to scanner.nextLine() and if you want to handle invalid int inputs from the user, the call to nextInt needs to be in your try block and catch the InputMismatchException instead of the ClassCastException.
Related
I want to take input as a string in Java and limit the user to not enter integer by using try catch.
import java.util.*;
public class trycatch {
public static void main(String args[]) {
Scanner sc=new Scanner(System.in);
String a;
System.out.println("\n\nEnter the name");
try {
a=sc.nextLine();
System.out.println("You name is "+a);
}
catch(InputMismatchException b) {
System.out.println("There is problem with your input");
}
}
}
Test to see if it is an int and if not a Exception is thrown
a=sc.nextLine();
Integer.valueOf(a); // throws NumberFormatException
// this is number so go to top of loop
continue;
} catch(NumberFormatException b) {
System.out.println("There is NO problem with your input");
// we can use `a` out side the loop
}
Take a look at this:
Does java have a int.tryparse that doesn't throw an exception for bad data?
Use that technique to try to parse what the user entered as an int. If the conversion succeeds, it means they entered an int, and you should throw an exception because you said you don't want them to enter an int (which I understood to mean you don't want them to enter a sequence of numbers only)
I haven't given you the exact answer/written your code for you because you're clearly learning java and this is an academic exercise. Your university/school isn't interested in teaching/assessing my programming ability, they're interested in yours, so there isn't any value to you in me doing your work for you :)
If you get stuck implementing what I suggest, edit your question to include your improved code and we can help again
As a side note, I suggest you make your error messages better that "there was a problem"
Nothing is more frustrating to a user than being told there was a problem but not what it was or how to fix it.
You should check you string for numbers like this:
a=sc.nextLine();
if (a.matches(".*\\d+.*")) {
throw new InputMismatchException();
}
This problem can be solved best with using Regular expression but since your requirement is to use try catch so you can you use below approach
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String a = null;
System.out.println("\n\nEnter the name");
try {
// try to get Integer if it is number print invalid input(because we
// don't want number)
sc.nextInt();
System.out.println("There is problem with your input");
}
//getting exception means input was not an integer
// if input was not an Integer then try to read that as string and print
// the name
catch (InputMismatchException b) {
a = sc.next();
System.out.println("You name is " + a);
}
}
I have copied the exact same code from another program. Whenever inputting deliberate incorrect results the InputMismatchException still occurs and the program crashes.
import java.util.*;
public class Runner{
public static void main (String args[]){
Scanner sc = new Scanner(System.in);
sc.useDelimiter("\n");
Fixture f = new Fixture();
boolean inputValid = false;
int choice = 0;
do{
do {
System.out.println("\f\t\tFootball Database");
System.out.println("A utility to help make footballing events easier to manage.");
System.out.println("");
System.out.println("\t> Press 1 to manage players ");
System.out.println("\t> Press 2 to manage teams");
System.out.println("\t> Press 3 to manage coaches");
System.out.println("\t> Press 4 to manage fixtures");
System.out.println("\t> Press 5 to save database to file");
System.out.println("\t> Press 6 to load database from file");
System.out.println("\t> Press 7 to terminate program");
System.out.println("");
System.out.println("");
System.out.println("©Thomas Camilleri 2017");
try{
choice = sc.nextInt();
inputValid = true;
}catch(InputMismatchException e){
System.out.println("Invalid input");
inputValid = false;
sc.nextInt();
sc.nextInt();
}
}while(inputValid == false);
Here is the salient part of your code:
try {
choice = sc.nextInt(); // NOT HERE
inputValid = true;
} catch(InputMismatchException e){
System.out.println("Invalid input");
inputValid = false;
sc.nextInt(); // HERE
sc.nextInt();
}
If you look at the stacktrace that you got, and look at the line numbers, you will see that the line in your code where the exception happens is the one I have tagged with // HERE.
(Compile and run the original program and look at the stacktrace to see what I mean. Compare the line numbers in the stack trace with the source code.)
As you can see, that line is NOT in the try { ... } block. It is in the exception handler block.
What has happened is that you have caught the exception that was thrown at the line tagged // NOT HERE, and then you have called sc.nextInt() again (at // HERE). The second call has simply attempted to read the same input characters again.
The behavior of the nextInt method is as follows:
get characters sufficient to form a token
attempt to convert the entire token into an integer (using base-10 integer syntax)
if the conversion succeeds, return the converted integer
if the conversion fails, put all of the characters back and then throw an exception.
I strongly encourage you to carefully read the javadocs for the Scanner class so that you understand what the methods you are using actually do.
So ... as you see ... if you just call nextInt() after a failed nextInt() call, you just get the same failure repeated.
The reason that second exception is not caught is that it has not been thrown within the try { ... } block.
Solution: Instead of calling nextInt() in the handler, you should call a method that is going to just discard the rubbish. In this case, the most sensible thing to do is to throw away everything up to the next end-of-line.
Hint #1: the nextLine() gets everything up to the next end-of-line. Read the javadocs for that method too.
Hint #2: if you understand what I said, you will know where to put your modification.
Try like:
choice = Integer.parseInt(sc.nextLine());
and your program will like this:
try (Scanner sc = new Scanner(System.in)) {
sc.useDelimiter("\n");
// Fixture f = new Fixture();
boolean inputValid = false;
int choice = 0;
// removed outer do..while(); loop
do {
System.out.println("\f\t\tFootball Database");
System.out.println("A utility to help make footballing events easier to manage.");
System.out.println("");
System.out.println("\t> Press 1 to manage players ");
System.out.println("\t> Press 2 to manage teams");
System.out.println("\t> Press 3 to manage coaches");
System.out.println("\t> Press 4 to manage fixtures");
System.out.println("\t> Press 5 to save database to file");
System.out.println("\t> Press 6 to load database from file");
System.out.println("\t> Press 7 to terminate program");
System.out.println("");
System.out.print("Enter your choice : ");
try{
// Always use nextLine() if you mix String and basic Datatype
choice = Integer.parseInt(sc.nextLine());
inputValid = true;
}catch(NumberFormatException e){
System.out.println("Invalid input");
inputValid = false;
// Removed unnecessary two sc.nextInput() lines
}
}while(inputValid == false);
System.out.println("choice is : " + choice);
}
Here is my code for inputting a student number:
When the user inputs the number in a unexpected format I will ask them to reinput by recursion. But it ends up with an infinitive recursion. Why?
private static int inputStudentNumber(){
System.out.println("Enter the student number:");
int studentNum;
try {
//Scanner in initialized before calling this method
studentNum = in.nextInt();
return studentNum;
} catch(Exception e) {
System.out.println("Invalid input, it can only be integer.");
return inputStudentNumber();
}
}
Take a closer look at the javadocs for Scanner.nextInt:
This method will throw InputMismatchException if the next token cannot be translated into a valid int value as described below. If the translation is successful, the scanner advances past the input that matched. (emphasis added)
If it's not successful, the scanner isn't advanced. That means that if you try to invoke nextInt() again, you'll be trying to get an int from the same token as before, and you'll once again get an InputMismatchException.
Your code basically says: try to read the next token as an int. If that fails, recurse to try to read the token as an int again. If that fails, recurse to try to read the token as an int again. If that fails... (and so on, until you get a StackOverflowException from too much recursion).
If you want to use recursion for this, you should probably use next() to skip to the next token. And only catch InputMismatchException, so that you won't also catch NoSuchElementException (which won't happen for System.in, but is good practice in general -- what if you later decide to read from a file, and that file has reached its end?).
} catch(InputMismatchException e) {
System.out.println("Invalid input, it can only be integer.");
in.next(); // skip this token
return inputStudentNumber();
}
An even better approach would be to avoid using the exception to control your logic in the first place. To do this, you'd have to know ahead of time whether nextInt will succeed. Luckily for you, hasNextInt() lets you do exactly that!
private static int inputStudentNumber() {
System.out.println("Enter the student number:");
if (in.hasNextInt()) {
return in.nextInt();
} else {
System.out.println("Invalid input, it can only be integer.");
in.next(); // consume the token
return inputStudentNumber();
}
}
The advantage here -- besides the general "don't use exceptions for control flow" advice -- is that the base case is super clear. If there's an int ready, that's your base case; if not, you have to advance the scanner and try again.
The problem is that if a non-integer is entered as input, then that input is not consumed by the scanner. So you just keep reading it.
You may want to just read the input as a string and then try to convert it separately.
Your problem is probably that in.nextInt() is throwing an Exception. A code smell that I see is that you use:
catch(Exception e) {
....
}
The best practice here is to only catch the specific Exception you are expecting, so it should be:
catch(InputMismatchException e) {
....
}
If you do this, then whatever in.nextInt() is throwing will properly propagate to the top, and you will probably see that in is not initialized or some such problem.
See here for the Exceptions that nextInt() can throw.
http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#nextInt()
try this...
private static int inputStudentNumber(){
System.out.println("Enter the student number:");
int studentNum;
int var = 1;
while(var ==1)´
{
try{
studentNum = in.nextInt();
var=0;
return studentNum;
}catch(Exception e){
System.out.println("Invalid input, it can only be integer.");
var=1;
return inputStudentNumber();
}
}
}
I've been staring at this for hours and unable to think of a solution; I usually handle validation of this type with regex but am trying to use a built-in solution for a change (obviously, I don't do this frequently):
private static double promptUserDecimal(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter a decimal");
try{
double input2 = Double.parseDouble(scan.nextLine());
return input2;
} catch(NumberFormatException e){
System.out.println("Sorry, you provided an invalid option, please try again.");
}
}
The error with this is that the "return" isn't found by the compiler so I get a compile error. If I put the "return" outside of the try/catch I need to declare/initialize "input2" which defeats the purpose of the operation. Any assistance is appreciated...
If you want the user to "please try again", it sounds like you need a loop:
private static double promptUserDecimal(){
final Scanner scan = new Scanner(System.in);
// Ask for input until we get something valid
while (true) { // Terminated by return within
System.out.println("Enter a decimal");
try {
return Double.parseDouble(scan.nextLine());
} catch(NumberFormatException e){
System.out.println("Sorry, you provided an invalid option, please try again.");
// No return, so the loop will run again
}
}
}
You need something like:
double input2;
try{
//read input2
}catch( ... ){
//... log AND assign a value to input2 in case of invalid input
}
return input2;
Throw an exception in the catch section. Wherever you call the promptUserDecimal method, catch any exception and print the message there:
public static void main(String[] args) {
double d = 0.0;
while (double == 0) {
try {
d = promptUserDecimal();
} catch (NumberFormatException e) {
//log the message...
d = 0.0;
}
}
}
private static double promptUserDecimal() throws NumberFormatException {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a decimal");
return Double.parseDouble(scan.nextLine());
}
This would be a better approach because you let the promptUserDecimal cares only about handling reading a double value. You must try to tend to separate each class and method for the specific purpose it was designed for.
Let your method throw an exception or return nan.
You need to return or throw something from (or after the catch). Judging by your output to the user, it looks like you just want to do the same thing again. Just call the method again and return the result.
private static double promptUserDecimal(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter a decimal");
try{
double input2 = Double.parseDouble(scan.nextLine());
return input2;
} catch(NumberFormatException e){
System.out.println("Sorry, you provided an invalid option, please try again.");
return promptUserDecimal();
}
}
You can throw an exception within your catch block. i.e.,
private static double promptUserDecimal() throws OopsException {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a decimal");
try{
double input2 = Double.parseDouble(scan.nextLine());
return input2;
} catch(NumberFormatException e){
System.out.println("Sorry, you provided an invalid option, please try again.");
throw new OopsException();
}
}
Then, every time they give an invalid input, you can catch it and handle it where you call the method from.
private static double promptUserDecimal(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter a decimal");
double input2 = 0.0; // <-- explicit initialization
try{
double input2 = Double.parseDouble(scan.nextLine());
} catch(NumberFormatException e){
System.out.println("Sorry, you provided an invalid option, please try again.");
}
return input2;
}
A few of the solutions listed will solve the compiler issue, but the first step is to take a step back and ask "what do I want to do in the event that a NumberFormatException occurs?"
One option is to propagate the exception by rethrowing the NumberFormatException or wrapping it in a RuntimeException so that it goes unchecked. This means that calling code will have to handle it, or the user will be presented with a stacktrace. If you go this route you don't even need a try catch in your method. You can just declare "throws NumberFormatException" on the method signature and let it get handled up stream.
Another option is to return null, either by using "return null" as the last statement in your catch block, or returning null as the last statement within the method. This is a terrible option because calling code and/or end user won't get the information they need, that "a non-number was entered as input."
I would go with option one, and handle the exception by telling the user that scan.nextline + " is not recognized as a valid double."
normally when I get a user interaction from a keyboard I use class scanner to do so but the problem I noticed when using its methods is that it's not handling exception! For example
Scanner input = new scanner();
Int number = input.nextInt();
The above works good for all integer numbers but if the user mistakly entered a character or a string, it will throw an exception and stops executing the rest of the program.
My question is there any way to avoid this?
Thank you in advance.
Try to catch the exception. Or use the hasNextInt method to prevent the exception from being thrown in the first place.
try {
int number = input.nextInt();
} catch (InputMismatchException e) {
System.out.println("That wasn't a number!");
}
Perhaps you should catch the exception and ask the user again?
See http://www.functionx.com/java/Lesson14.htm for exactly your problem.