I am working on writing a file reader, and the idea is to have the user enter a number that represents the line number from the text file. The variable that holds this number is of type int. However, when the user enters a String instead, Java throws the InputMismatchException exception, and what I want is to have a loop in the catch clause, where I will be looping until the user enters a valid value, i.e. an int. The skeleton looks like this:
public void _____ throws IOException {
try {
// Prompting user for line number
// Getting number from keyboard
// Do something with number
} catch (InputMismatchException e) {
// I want to loop until the user enters a valid input
// When the above step is achieved, I am invoking another method here
}
}
My question is, what are some possible techniques that could do the validation?
Thank you.
while(true){
try {
// Prompting user for line number
// Getting number from keyboard
// Do something with number
//break;
} catch (InputMismatchException e) {
// I want to loop until the user enters a valid input
// When the above step is achieved, I am invoking another method here
}
}
Avoid using exceptions for flow control. Catch the exception, but only print a message. Also, do need for loops within loops.
It's as simple as this:
public void _____ throws IOException {
int number = -1;
while (number == -1) {
try {
// Prompt user for line number
// Getting number from keyboard, which could throw an exception
number = <get from input>;
} catch (InputMismatchException e) {
System.out.println("That is not a number!");
}
}
// Do something with number
}
You can avoid the Exception
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine())
String input = sc.nextLine();
if (isNumeric(input) {
// do something
// with the number
break; // break the loop
}
}
The method isNumeric:
public static boolean isNumeric(String str) {
return str.matches("^[0-9]+$");
}
If you want use a dialog for input number:
String input = JOptionPane.showInputDialog("Input a number:"); // show input dialog
Related
I am new to Java and I tried to use exceptions in my Java code to give the user an alert if in case he/she types a negative number or a non-numerical value in the text field. But still, when I enter a single-digit positive number, the catch blocks get executed.
//textfield to enter the amount of Rs.
txt_rupees = new JTextField();
//KeyListener to check if the content entered in the text field is a number or not.
txt_rupees.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
try {
//convert the user input in the textfield from string to double
double check = Double.parseDouble(txt_rupees.getText());
//checking if the number entered by the user is positive or not.
if (check > 0) {
lb_check1.setText(" ");
}
else {
lb_check1.setText("Please enter a valid number");
}
}
catch (NumberFormatException ne){
//If the user enters a non-numerical character then this message should be displayed by the label.
lb_check1.setText("ALERT: Please enter a valid float or int value in the textfield");
}
}
});
To understand how try-catch block work, I will give an example.
class InsufficientMoneyException extends Exception{
InsufficientMoneyException(int money){
System.out.println("You only have $"+money);
}
}
class A throws InsufficientMoneyException{
try{
int money = 100;
if(money<1000) throw new InsufficientMoneyException(money);
System.out.println("I am NOT being executed!");
} catch (InsufficientMoneyException e){System.out.println("I am being executed!");}
}
Code block will get executed unless it encounters a statement that tells it to throw a exception. After throwing the exception, the catch will catch the exception and the catch block will get executed.
In your case,
double check = Double.parseDouble(txt_rupees.getText());
The library function parseDouble() will throw the NumberFormatException so the lines in try block after this line, won't get executed.
I have a program that is trying to validate a passed value. I want a user to input anything and the method that I pass it to will validate whether the input would work.
This is my code:
public static void main(String[]args) {
Scanner input = new Scanner(System.in);
ChequingAccount a = new ChequingAccount();
double deposit = inputCheck("Enter deposit amount: ", input);
a.setDeposit(deposit);
}
public static double inputCheck(String prompt, Scanner input) {
boolean userValid = false;
do {
System.out.print(prompt);
double user;
try {
user = input.nextDouble();
if (user < 0) {
throw new IllegalArgumentException("Value cannot be lower than 0");
}
userValid = true;
} catch (InputMismatchException e) {
System.out.println("The value entered is not a number");
user = inputCheck(prompt, input);
input.nextLine();
} catch (IllegalArgumentException ex) {
System.out.println(ex.getMessage());
user = inputCheck(prompt, input);
}
return user;
} while (!userValid);
}
The code works except for the fact that when the method catches the InputMismatchException, the code then will loop a bunch of times and breaks the program. I thought adding a doWhile loop would solve the issue but it didn't do anything.
you don't need a loop , you need recursion
public static double inputCheck(String prompt, Scanner input) {
double user;
try {
user = input.nextDouble();
if (user < 0) {
throw new IllegalArgumentException("Value cannot be lower than 0");
}
return user;
} catch (InputMismatchException e) {
System.out.println("The value entered is not a number");
return inputCheck(prompt, input);
} catch (IllegalArgumentException ex) {
System.out.println(ex.getMessage());
return inputCheck(prompt, input);
}
}
You're calling your own method from inside; the inputCheck method's code calls inputCheck. This is a somewhat creative way to write a loop.
You also have... a loop.
So you 2 loops, to do the job that one loop should do. That's why all heck breaks loose here. Pick one: Either use the do/while construct (so do not call yourself), or, don't loop, and call yourself. Either one can be made to work here.
The nextLine stuff is irrelevant and not the problem here (in general don't call that; just set the delimiter properly; call scanner.useDelimiter("\\r?\\n") and to get entire lines, use next(), not nextLine().
There are number of approaches that can work for this – iteration, recursion, exception catching, etc. Your solution is mixing several of them together which makes it harder to understand and also harder to fix.
Here is an example that uses a simple while loop, no recursion, no exception catching. It uses hasNextDouble() and, depending on the result, either proceeds to capture the double (by calling nextDouble()), or prints a message (along with consuming and ignoring whatever non-double token is present by calling next()).
public static double inputCheck(String prompt, Scanner input) {
while (true) {
System.out.print(prompt);
if (input.hasNextDouble()) {
double number = input.nextDouble();
if (number < 0) {
System.out.println("Value cannot be lower than 0. Please try again.");
} else {
return number;
}
} else {
System.out.println("The value entered is not a number. Please try again.");
input.next(); // consume and ignore whatever non-double input is waiting on the scanner
}
}
}
import java.util.Scanner;
public class HelloWorld {
public static int num;
public static Scanner scan;
public static void main(String[] args) {
System.out.println("Hello World");
/* This reads the input provided by user
* using keyboard
*/
scan = new Scanner(System.in);
System.out.print("Enter any number: ");
// This method reads the number provided using keyboard
check();
// Closing Scanner after the use
// Displaying the number
System.out.println("The number entered by user: "+num);
}
public static void check(){
try{
num = scan.nextInt();
}
catch (Exception e){
System.out.println("not a integer, try again");
check();
}
}
}
Im new to coding, and am taking this summer to teach myself some basics. I was wondering if someone could advise me on how I can create this method to take in a int, and check the input to make sure thats its a int. If the input is not a int, I would like to re run in.
Simple. Say you have something as shown below . . .
NumberThing.isNumber(myStringValue);
.isNumber() determines if your string is a numerical value (aka a number). As for putting the code in a loop to continue to ask the user for input if their input is invalid, using a while loop should work. Something like . . .
while (. . .) {
// use something to exit the loop
// depending on what the user does
}
You might consider moving the user request code to the check method. Also, use a break statement to exit your while loop after a valid number is entered.
while ( true )
{
System.out.println( "Enter an integer.");
try
{
num = scan.nextInt();
break;
}
catch (Exception e)
{
System.out.println("not a integer");
}
}
I found this code online as a password loop game, it's working fine, but my question is: how?
What does happen in this catch block exactly?
I'm curious about this line specifically:
reader.next();
boolean loop = true;
Scanner reader = new Scanner(System.in);
System.out.println("PIN: ");
while (loop) {
try {
Integer Code = reader.nextInt();
if (Code == 8273) {
System.out.println("Access granted");
loop = false;
} else {
System.out.println("Access denied");
}
} catch (Exception e) {
System.out.println("Please enter a valid PIN!");
reader.next();
}
}
Edit : of course I did deliberately input a Non-integer input to cause the exception.
Edit2 :
When I removed that line, the program kept printing Please enter a valid PIN! For ever.
In fact, what the programmer really wanted here is to capture the next line of input, and verify whether that was a valid integer.
But the code is, admittedly, very confusing. And it relies on the fact that by default, when you "swallow" the next token with anything but .nextLine() with a Scanner, it relies on the current delimiter, which by default matches a newline.
Not good.
Here is a version which is more explicit:
String input;
int code;
while (true) {
System.out.print("PIN: ");
input = reader.nextLine();
try {
code = Integer.parseInt(input);
} catch (NumberFormatException ignored) {
// not an integer!
System.out.println("Enter a valid PIN!");
continue;
}
if (code == 8273)
break;
System.out.println("Access denied");
}
System.out.println("Access granted");
If nextInt throws an exception (because the value entered isn't an int), then the catch block is entered. The last line of which,
reader.next(); // <-- discards invalid token.
Removes the invalid token and then the loop iterates.
Also, don't box the Code1
int code = reader.nextInt();
1Using an Object type and then testing equality with == is a bad idea™. Also, by convention Java variable names start with a lower case letter.
The catch block simply catches the exception when anything other than an integer is entered. Since Code is an Integer, the input would have to be an integer. After catching the exception and printing the error, the reader moves to the next input until a proper value is entered, and the boolean loop becomes false, which ends the while loop at the end of the if statement once the correct value is entered.
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.