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
}
}
}
Related
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");
}
}
Why I'm getting infinite loop in recursion method, without a chance to input any symbol to break it?
class Test {
int key=0;
void meth(){
System.out.println("Enter the number here: ");
try(Scanner scan = new Scanner(System.in)) {
key = scan.nextInt();
System.out.println(key+1);
} catch(Exception e) {
System.out.println("Error");
meth();
}
}
}
class Demo {
main method {
Test t = new Test();
t.meth();
}
}
If you try to create an error (putting string value in key and then try to add to it a number), you will get infinite "Error" text in console, instead of that, after first error, program should ask again the number and only then decide what to do.
If nextInt() fails, it throws an exception but doesn't consume the invalid data. From the documentation:
When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.
You're then recursively calling meth() again, which will try to consume the same invalid data a second time, fail again (without consuming it), and recurse.
Firstly, I wouldn't use recursion here in the first place. Prefer a simple loop. Next, if you have invalid input you should consume it appropriately before trying again. Finally, consider using hasNextInt instead of just using nextInt and catching the exception.
So maybe something like this:
import java.util.Scanner;
class Test {
public static void main(String[] args){
try (Scanner scanner = new Scanner(System.in)) {
System.out.println("Enter the number here:");
while (!scanner.hasNextInt() && scanner.hasNext()) {
System.out.println("Error");
// Skip the invalid token
scanner.next();
}
if (scanner.hasNext()) {
int value = scanner.nextInt();
System.out.println("You entered: " + value);
} else {
System.out.println("You bailed out");
}
}
}
}
I am writing a small program (student, though not an assignment for class...but rather a play on a previous assignment). Previously for class, while learning do/while loops, I wrote a program that prompted a user to input integers. When the user typed in 0, it served to get out of the loop, and then outputted the sum of the squares of all the integers typed.
Example output (double spaced for line breaks):
Type an integer: 3
Type an integer: 0
The sum of the squares is 9
My goal now is to take it a step farther. As written, the program crashes if the user types in anything other than an integer. I have been playing around trying to find ways to allow the user to type in other forms of values, without having it crash. In referencing the code below (which is the program at the moment that does crash at any value sans ints), I tried putting in variations of if statements with the console.hasNextInt() method. Yet my attempts in this would cause an error that number in the do/while test may not have been referenced.
Can anyone offer me any tips? It would be appreciated.
public static void userInterface() {
Scanner console = new Scanner(System.in);
int number;
int numberSquared;
int squaredOutput = 0;
do {
System.out.print("Type an integer (0 to quit): ");
number = console.nextInt();
if (number > 0 || number < 0) {
numberSquared = number * number;
squaredOutput += numberSquared;
}
} while (number != 0);
System.out.println("The sum of the squares is " + squaredOutput);
}
The problem is that you are using console.nextInt(); which only takes the next int.
You can use: console.nextLine();.
It would allow your program to accept a string and you can parse it into an Int when necessary:
try {
number=Integer.parseInt(console.nextLine());
} catch(NumberFormatException e) {
System.out.println("Please input an Integer");
}
Just use this function
public static int next(String message) {
while (true) {
System.out.println(message);
try {
return new Scanner(System.in).nextInt();
} catch (Exception e) {
System.out.println("Invalid input.");
}
}
}
There is problem with your code. When you use console.nextInt() and the scanner try to parse every string as Integer. Better solution is to use console.nextLine() and by your own parse it to your number and catch exception that might be thrown if that string is not parsable as any number that you want.
simply it might look like this.
String yourValue = console.nextLine();
try{
int value = Integer.parseInt(yourValue);
}catch(NumberFormatException e){
System.out.println("watch out this value is unparsable!");
}
Suppose I would like to add a method to Scanner called nextPositiveInt() which is similar to nextInt() except that when a negative integer is detected, a custom InputNegativeException is thrown.
Why would I want to do this when there are solutions that utilise hasNextInt()? While being a little less concise, it seems a whole lot tidier and more logical given the purpose of exceptions. For example:
Extended Scanner method:
Scanner cli = new Scanner(System.in);
boolean inputValid = false;
do
{
System.out.println("Enter your age:");
try
{
int age = cli.nextPositiveInt();
}
catch(InputNegativeException e)
{
System.out.println("You cannot specify a negative age.");
inputValid = false;
}
catch(InputMismatchException e)
{
System.out.println("Your input must be numeric.");
inputValid = false;
}
} while(!inputValid);
hasNext() method:
Scanner cli = new Scanner(System.in);
do
{
System.out.println("Please enter a positive number!");
while(!sc.hasNextInt())
{
System.out.println("That's not a number!");
sc.next(); // this is important!
}
int number = sc.nextInt();
} while(number <= 0);
So assuming you aren't already firing up a response telling me why this is a very bad idea (if it is, please do; I imagine there might be some objection regarding putting validation in Scanner) I'm confused about how to go about this. I guess I need to replicate the body of nextInt() in nextPositiveInt() with some minor changes? Can you even source the body of nextInt() anywhere?
I apologise that I have no code to show any effort I've made but I'm not sure where to start.
Althought Scanner class is final and you cann't extend it there exist another solution. You can use Delegation pattern.
Also as Scanner class has all nessasary methods public you can easily copy original method and make a little change. See source code of Scanner class the only thing you should change is regexp used for matching string in order to exclude negative ints.
Source code of scanner:
public int nextInt() {
return nextInt(defaultRadix);
}
public int nextInt(int radix) {
// Check cached result
if ((typeCache != null) && (typeCache instanceof Integer)
&& this.radix == radix) {
int val = ((Integer)typeCache).intValue();
useTypeCache();
return val;
}
setRadix(radix);
clearCaches();
// Search for next int
try {
String s = next(integerPattern());
if (matcher.group(SIMPLE_GROUP_INDEX) == null)
s = processIntegerToken(s);
return Integer.parseInt(s, radix);
} catch (NumberFormatException nfe) {
position = matcher.start(); // don't skip bad token
throw new InputMismatchException(nfe.getMessage());
}
}
You should change only:
String s = next(integerPattern());
For you purposes you can hardcode regexp. Original regexp can easily be caught on debug.
Definitely it wouldn't be the best solution in terms of realization - a lot of code to write and many copy-paste, but it would be easy and nice to use.
You cannot extend Scanner since it's final:
public final class Scanner
extends Object
implements Iterator<String>
What I would do is have a helper method in one of my classes:
public static int ensureNonNegative(int val) {
if (val >= 0) {
return val;
} else {
throw new InputNegativeException(val);
}
}
and would use it like so:
int val = ensureNonNegative(scanner.nextInt());
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