I have a loop which breaks upon receiving the correct input from the console. I am using Scanner to read in a String from System.in, which seems to be what's giving me trouble. Here is my code:
boolean loop = true;
while(loop) {
try {
System.out.println("Enter an input (\"input a\" or \"input b\"): ");
String input = scanner.nextLine();
System.out.println("");
if (input.equals("input a")) {
System.out.println("Answer to input a.");
} else if (input.equals("input b")) {
System.out.println("Answer to input b.");
} else {
throw new IllegalArgumentException();
}
loop = false;
} catch (InputMismatchException e) {
System.out.println(e.getMessage());
System.out.println("");
} catch (IllegalArgumentException e) {
System.out.println("Input not recognized. Please enter a valid input.");
System.out.println("");
}
}
When this is called, it loops once without even waiting for input from the user, then actually stops and does what it is supposed to the second time around. IE, the output for this, without the user giving any input at all, is:
Enter an input ("input a" or "input b"):
Input not recognized. Please enter a valid input.
Enter an input ("input a" or "input b"):
If I give it a bad input (so that it loops and asks again), it does the same thing where it loops twice before waiting. I have no idea why.
Why is this happening, and what should I do to avoid it?
EDIT: Test scenarios after hasNext check:
Scenario A:
Enter an input ("input a" or "input b"): input a //my input
Input not recognized. Please enter a valid input.
Enter an input ("input a" or "input b"): //no input given here
Answer to input a.
Scenario B:
Enter an input ("input a" or "input b"): ddd //my input
Input not recognized. Please enter a valid input.
Enter an input ("input a" or "input b"): //no input given here
Input not recognized. Please enter a valid input.
Enter an input ("input a" or "input b"): input b //my input
Answer to input b.
The code which produces this:
boolean loop = true;
while(loop) {
if (scanner.hasNext()) {
try {
System.out.println("Enter an input (\"input a\" or \"input b\"): ");
String input = scanner.nextLine();
System.out.println("");
if (input.equals("input a")) {
System.out.println("Answer to input a.");
} else if (input.equals("input b")) {
System.out.println("Answer to input b.");
} else {
throw new IllegalArgumentException();
}
loop = false;
} catch (InputMismatchException e) {
System.out.println(e.getMessage());
System.out.println("");
} catch (IllegalArgumentException e) {
System.out.println("Input not recognized. Please enter a valid input.");
System.out.println("");
}
}
}
I tried out the code you've wrote down in your question, as a single question, but I can't find any problem with it at all. However, I think I know just the answer.
If you did any other input before this with primitive types or just next(), you need to flush the newline character that unfortunately those next methods leave behind. To do this, just call "scanner.nextLine()" before the statement where the method returns the inputted string and assigns it to input.
You want to make sure that you call in the method as separate; you know, on its own. It's best if you put it in your while loop at the top before you enter so that way for every iteration, the newline character is cleared. The statement will then get rid of the newline character and thus the input buffer is empty. Once that's cleared out, you can finally input your string at your first loop iteration.
How's that for an answer? Try it out and let me know if it works!
You should first check if the user has enetered any data :
if(scanner.hasNext())
{
// code logic
}
Related
I don't know if im using the isNaN right but can you guys help me on using it to accept only numbers in inputs
while (true){
System.out.println("first number");
num1=input.nextDouble();
if (num1.isNaN()){
System.out.println("invalid input");
}
else;
break;
}
My issue is that when i input a letter, it is not displaying the invalid input message. It just stops the program because i input a letter which is not the error i want to see
Scanner does not return a NaN when an invalid input is given. Instead it throws an InputMismatchException. You could use a try-catch statement to catch this exception and handle it appropriately.
Alternatively, Scanner also has a hasNextDouble() function. This waits and checks if the next value is valid as a double, without actually consuming it.
So you could write your loop like this:
while (true){
System.out.println("Please input a number:");
if (!input.hasNextDouble()) {
System.out.println("Not a valid number.");
break;
}
double number = input.nextDouble();
System.out.println("Your input: " + number);
}
See the documentation on Scanner.hasNextDouble
I write a code to let the user input cruise id first and then enter the ship name.
At first, I want to detect whether the user input integer type, if not, the user has to re-enter the first question again.
But in my code, it will directly print the second question instead of go back to the first question and ask again. Same, for the second question, I also want it return back and ask user to input again if the input is wrong
Please help me for that. Thanks!!
try{
System.out.println("Input Cruise ID:");
sc1 = sc.nextInt();
}catch(Exception e){
System.out.println("Please Enter integer:");
sc.nextLine();
}
System.out.println("Input ship name :");
try{
sc2 = sc.next();
}catch(Exception e){
if( sc2 != "Sydney1" || sc2 !="Melmone1"){
System.out.println("Oops!! We don't have this ship!! Please enter the ship name : Sydney1 or Melbone1");
}
}
I write a code to let the user input cruise id first and then enter the ship name. At first, I want to detect whether the user input integer type, if not, the user has to re-enter the first question again.
What you need is an input validation. try-catch block itself will not create an endless loop to reprompt the user should the input is not an integer. What you need is a while loop.
You can use a do-while loop as follows so that it runs first before performing a check:
String input = ""; //just for receiving inputs
do{
System.out.println("Input Cruise ID:");
input = sc.nextInt();
}while(!input.matches("[0-9]+")); //repeat if input does not contain only numbers
int cruiseID = Integer.parseInt(input); //actual curiseID in integer
To perform validation for your second input (i.e, your shipName, you need another while loop which encloses your prompt for input).
try-catch block are mainly used to handle exceptional cases. Try not to misuse it as a control statement for your implementations.
You can add more checks inside the while loop itself. For example, checking if the number is a negative number or zero etc. For example
while (true) {
try {
System.out.println("Input Cruise ID:");
cruiseId = sc.nextInt();
if(cruiseId <=0){
System.out.println("Please Enter integer:");
sc.nextLine();
}
break; // break when no exception happens till here.
} catch (Exception e) {
System.out.println("Please Enter integer:");
sc.nextLine();
}
}
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 read user input that must be only of type int, the problem comes when the user enters letter instead of a int. I know how to handle the exception, but I would like to return the scanner read where the user has made a mistake. How can I do?
I already tried with an infinite loop, but it does not work.
try{
System.out.print("enter number: ");
value = scanner.nextInt();
}catch(InputMismatchException e){
System.err.println("enter a number!");
}
While other answers give you correct idea to use loop you should avoid using exceptions as part of your basic logic. Instead you can use hasNextInt from Scanner to check if user passed integer.
System.out.print("enter number: ");
while (!scanner.hasNextInt()) {
scanner.nextLine();// consume incorrect values from entire line
//or
//tastiera.next(); //consume only one invalid token
System.out.print("enter number!: ");
}
// here we are sure that user passed integer
int value = scanner.nextInt();
A loop is the right idea. You just need to mark a success and carry on:
boolean inputOK = false;
while (!inputOK) {
try{
System.out.print("enter number: ");
numAb = tastiera.nextInt();
// we only reach this line if an exception was NOT thrown
inputOK = true;
} catch(InputMismatchException e) {
// If tastiera.nextInt() throws an exception, we need to clean the buffer
tastiera.nextLine();
}
}
This piece of code is supposed to get an integer number from user and then finish the program. If the user inputs an invalid number, it asks user again.
After catching exception, it uses Scanner.reset() to reset the scanner, but it doesn't work. and it re-throws previous exception.
Scanner in = new Scanner(System.in);
while (true) {
try {
System.out.print("Enter an integer number: ");
long i = in.nextLong();
System.out.print("Thanks, you entered: ");
System.out.println(i);
break;
} catch (InputMismatchException ex) {
System.out.println("Error in your input");
in.reset(); // <----------------------------- [The reset is here]
}
}
I thought Scanner.reset() will reset everything and forget the exception. I put it before asking the user for a new input.
If I get the point wrong, what is the right way?
You misunderstood the purpose of the reset method: it is there to reset the "metadata" associated with the scanner - its whitespace, delimiter characters, and so on. It does not change the state of its input, so it would not achieve what you are looking for.
What you need is a call of next(), which reads and discards any String from the Scanner:
try {
System.out.print("Enter an integer number: ");
long i = in.nextLong();
System.out.print("Thanks, you entered: ");
System.out.println(i);
break;
} catch (InputMismatchException ex) {
System.out.println("Error in your input");
in.next(); // Read and discard whatever string the user has entered
}
Relying upon exceptions to catch exceptional situations is OK, but an even better approach to the same issue would be using has... methods before calling the next... methods, like this:
System.out.print("Enter an integer number: ");
if (!in.hasNextLong()) {
in.next();
continue;
}
long i = in.nextLong();
System.out.print("Thanks, you entered: ");
System.out.println(i);
break;
Per Scanner.reset() javadoc, the method only "resets" locale, radix and delimiter settings. It does not do anything to the data it already read.