I am starting to code in Java (never done so before), and I am having a headache with input validation.
I need that while a user inputs numbers from 0 to 1000, the while loops keeps getting executed. That works fine. The problem is I would like to check wether he inputs a number, and if he doesn't, the while loop should keep executing and waiting for the next input. So far my code only throws InputMismatchException when inputting something that is not a number and I can't see why.
Here is my code:
Scanner score = new Scanner(System.in);
int i = 0;
while (i < 1000000) {
System.out.print("Insert the new score: ");
if (score.hasNextInt()) {
i = score.nextInt();
if (i > 0) {
if (i < 200000) {
// do something
} else if (i < 500000) {
// do something
} else if (i < 700000) {
// do something
} else if (i < 100001) {
// do something
}
} else if (i < 0) {
// do something else
}
} else {
System.out.print("The score should be a number.");
i = score.nextInt();
}
}
else{
System.out.print("The score should be a number.");
i = score.nextInt(); //<---problem
}
Here you know that input was not a number so you shouldn't be trying to read it as int with nextInt(). So to consume invalid data use
next() which will return from scanner data as Sting which you can later ignore (you don't need to even store it in String variable)
or if you want to consume entire line use nextLine() (but be careful with this to avoid: Skipping nextLine() after using next(), nextInt() or other nextFoo() methods)
In your final else clause, you call score.nextInt() although you know that the next number isn't an int. That's why you get the exception. Just replace the else with this:
else {
System.out.print("The score should be a number.");
score.nextLine(); //This is the line you need to change
}
score.nextLine(); will consume the next line of input safely, and put you back in the loop.
You are receiving this error because you're telling Scanner to get an integer, even when the user does not type an integer. You need to instead accept all input (via a String) and do the validation yourself.
I've modded your code to take input as a String (Scanner#nextLine) and then attempt to update the score.
Scanner score = new Scanner(System.in);
int i = 0;
while (i < 1000000) {
System.out.print("Insert the new score: ");
if (score.hasNext()) {
final String input = score.nextLine();
try {
i = Integer.parseInt(input);
} catch (final Exception e) {
System.out.print("The score should be a number.");
continue;
}
}
if (i>0) {
if (i<200000) {
//do something
}
else if (i<500000) {
//do something
}
else if (i<700000) {
//do something
}
else if (i<100001) {
//do something
}
} else if (i<0) {
//do something else
}
}
Note the continue; statement will indefinitely ask the user for integer input until the user does, just as you requested in your question.
You may want to wrap while contents with try-catch block.
Scanner score = new Scanner(System.in);
int i = 0;
while (i < 1000000){
try{
System.out.print("Insert the new score: ");
if (score.hasNextInt()){
i = score.nextInt();
if (i>0){
if (i<200000){
do something
}
else if (i<500000){
do something
}
else if (i<700000){
do something
}
else if (i<100001){
do something
}
}else if (i<0){
do something else
}
}else{
System.out.print("The score should be a number.");
i = score.nextInt();
}
}catch(Exception e){}
}
You need to wrap your input statement inside a try/catch block and catch the InputMisMatchException. The InputMisMatchException happens because of using nextInt() in the Scanner which is expecting integer.
Scanner input = new Scanner(System.in);
int i = 0;
do {
try {
System.out.print("Enter integer ");
i = input.nextInt();
} catch (InputMismatchException e) {
//anything but integer gets caught here.
System.out.print("Please enter only integer.");
}
//necessary to take the cursor back to start of line, clear the buffer
input.nextLine();
} while (i < 1000000);
Above code example shows how to catch the InputMisMatchException.
I noticed that you have use input.hasNextInt() in your code, and all you need is to replace the following in the else block of your code.
i = score.nextInt()
with
score.nextLine();
As described in other answers, this sentence will clear the buffer waiting for next input. The exception is due to score.nextInt(), the replacement should fix it.
Related
I need to write a program that can validate user input as integer and prevent it from crashing whenever use input is not integer. So I am using try and catch here. However, I got an infinite loop when user input is a non-integer. Below is my code
do {
try {
a = sc.nextInt();
} catch (InputMismatchExpression e) {
System.out.println("This is not integer");
}
} while(a < 1 || a > 10);
Once the Scanner throws an exception, the existing value remains "unconsumed". To avoid this you need to add sc.next() line to consume the existing input and make Scanner await the next value from the user.
do {
try {
a = sc.nextInt();
} catch (InputMismatchExpression e) {
sc.next(); // this "consumes" the invalid input and throws away
System.out.println("This is not integer");
}
} while(a < 1 || a > 10);
If you actually want to break the loop, if user input is a non-integer, then you can simply add a flag value in your code :
int flag = 0;
do {
try {
a = sc.nextInt();
} catch (InputMismatchExpression e) {
System.out.println("This is not integer");
flag=1;
}
} while((a < 1 || a > 10)&&flag==0);
If flag=1, loop will break.
normaly use regex check user input
like :
String userInput = "1234567";
boolean isNumber = userInput.matches("^\\d+$");
System.out.println(isNumber);
The algorithm should take in 3 integers to an ArrayList. If the input is not an integer, then there should be a prompt. When I execute my code the catch clause is executed, but the program runs into a infinite loop. Could someone guide me into the right direction, I appreciate the help. :-D
package chapter_08;
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
public class IntegerList {
static List<Integer> numbers = new ArrayList<Integer>();
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int counter = 1;
int inputNum;
do {
System.out.print("Type " + counter + " integer: " );
try {
inputNum = input.nextInt();
numbers.add(inputNum);
counter += 1;
}
catch (Exception exc) {
System.out.println("invalid number");
}
} while (!(numbers.size() == 3));
}
}
That is because when the next int is read using nextInt() and it fails, the Scanner still contains the typed contents. Then, when re-entering the do-while loop, input.nextInt() tries to parse it again with the same contents.
You need to 'flush' the Scanner contents with nextLine():
catch (Exception exc) {
input.nextLine();
System.out.println("invalid number");
}
Notes:
You can remove the counter variable, because you're not using it. Otherwise, you could replace counter += 1 by counter++.
You can replace while (!(numbers.size() == 3)) with while (numbers.size() != 3), or even better: while (numbers.size() < 3).
When catching exceptions, you should be as specific as possible, unless you have a very good reason to do otherwise. Exception should be replaced by InputMismatchException in your case.
If inputNum = input.nextInt(); cannot be fit into an int and a InputMismatchException is raised, the input of the Scanner is not consumed.
So after the catch, it loops and it goes again here :
inputNum = input.nextInt();
with exactly the same content in the input.
So you should execute input.nextLine(); in the catch statement to discard the current input and allow a new input from the user.
Besides it makes more sense to catch InputMismatchException rather than Exception as other exception with no relation with a mismatch could occur and it would not be useful to display to the user "invalid number " if it is not the issue :
catch (InputMismatchException e){
System.out.println("invalid number ");
input.nextLine();
}
You should to use a break; in your catch(){} like so :
try {
inputNum = input.nextInt();
numbers.add(inputNum);
counter += 1;
} catch (Exception e) {
System.out.println("invalid number ");
break;
}
So if one input is not correct break your loop.
try changing
inputNum = input.nextInt();
to
String inputText=input.next();
inputNum = Integer.valueOf(inputText);
it works perfectly well.
You need to move the scanner to the next line. Add this line of code below the error message in the catch section.
input.nextLine();
I want to make it so that a user entering the wrong data type as figureNumber will see a message from me saying "Please enter an integer" instead of the normal error message, and will be given another chance to enter an integer. I started out trying to use try and catch, but I couldn't get it to work.
Sorry if this is a dumb question. It's my second week of an intro to java class.
import java. util.*;
public class Grades {
public static void main(String args []) {
Scanner stdin = new Scanner(System.in);
System.out.println();
System.out.print(" Please enter an integer: ");
int grade = stdin.nextInt();
method2 ();
if (grade % 2 == 0) {
grade -= 1;
}
for(int i = 1; i <=(grade/2); i++) {
method1 ();
method3 ();
}
}
}
public static void main(String args[]) {
Scanner stdin = new Scanner(System.in);
System.out.println();
System.out.print(" Welcome! Please enter the number of figures for your totem pole: ");
while (!stdin.hasNextInt()) {
System.out.print("That's not a number! Please enter a number: ");
stdin.next();
}
int figureNumber = stdin.nextInt();
eagle();
if (figureNumber % 2 == 0) { //determines if input number of figures is even
figureNumber -= 1;
}
for (int i = 1; i <= (figureNumber / 2); i++) {
whale();
human();
}
}
You need to check the input. The hasNextInt() method is true if the input is an integer. So this while loop asks the user to enter a number until the input is a number. Calling next() method is important because it will remove the previous wrong input from the Scanner.
Scanner stdin = new Scanner(System.in);
try {
int figureNumber = stdin.nextInt();
eagle();
if (figureNumber % 2 == 0) { //determines if input number of figures is even
figureNumber -= 1;
}
for(int i = 1; i <=(figureNumber/2); i++) {
whale();
human();
}
}
catch (InputMismatchException e) {
System.out.print("Input must be an integer");
}
You probably want to do something like this. Don't forget to add import java.util.*; at the beginning of .java file.
You want something in the form:
Ask for input
If input incorrect, say so and go to step 1.
A good choice is:
Integer num = null; // define scope outside the loop
System.out.println("Please enter a number:"); // opening output, done once
do {
String str = scanner.nextLine(); // read anything
if (str.matches("[0-9]+")) // if it's all digits
num = Integer.parseInt(str);
else
System.out.println("That is not a number. Please try again:");
} while (num == null);
// if you get to here, num is a number for sure
A do while is a good choice because you always at least one iteration.
It's important to read the whole line as a String. If you try to read an int and one isn't there the call will explode.
You can actually test the value before you assign it. You don't need to do any matching.
...
int figureNumber = -1;
while (figureNumber < 0) {
System.out.print(" Welcome! Please enter the number of figures for your totem pole: ");
if (stdin.hasNextInt()){
figureNumber = stdin.nextInt(); //will loop again if <0
} else {
std.next(); //discard the token
System.out.println("Hey! That wasn't an integer! Try again!");
}
}
...
This was a difficult question to research, so please forgive me if this is a duplicate.
Basically, I have a while loop that'll only break if a code the user scans is an integer. I check this by trying Integer.parseInt(integer) and only breaks the loop if a NumberFormatException isn't thrown.
My problem, is that when the loop executes for the first time, the exception is thrown, without any user input.
Here's my code:
Scanner input = new Scanner(System.in);
while (true)
{
System.out.print("Please scan barcode: ");
int inCode = 0;
try
{
inCode = Integer.parseInt(input.next());
}
catch (NumberFormatException e)
{
System.out.println("Numbers only, please.");
}
if (inCode != 0) {
// Do Stuff
} else {
System.out.println("Code can't be zero!");
}
}
What should happen, is this:
Please scan barcode: // And here they enter the barcode
But instead this happens:
Please scan barcode: Numbers only, please.
Please scan barcode:
EDIT:
As per Bohemian's answer, I added the continue keyword to my code. That solves the issue, but only halfway. As per the request of the people who put my question on hold (With good reason, as I now see) I'll post a SSCCE for you guys. I'm going to remove the methods for interfacing with the database, though, only keeping the path that has the problem: creating a new account based on the code.
Scanner input = new Scanner(System.in);
while (true)
{
System.out.print("Please scan barcode: ");
int inCode = 0;
try
{
inCode = Integer.parseInt(input.next());
}
catch (NumberFormatException e)
{
System.out.println("Numbers only, please.");
continue;
}
if (true) // Here it checks if an account associated with the code entered exists in the database. Because I'm having issues when it creates a new account, I've made this true.
{
System.out.println("No account associated with that code! Create one?");
System.out.print("(yes/no): ");
String answer = input.next();
if (answer.equalsIgnoreCase("yes"))
{
System.out.println("Alright.");
System.out.print("Please enter a name: ");
String name = input.next();
System.out.print("Alright. Now I'll add that to the database... ");
// Here I add that to the database. Omitted.
System.out.println("Done! Please scan again to interface.");
}
else if (answer.equalsIgnoreCase("no"))
{
System.out.println("Okay then.");
}
else
{
System.out.println("Defaulting to no.");
}
}
}
// I still haven't written the code to interface with the account.
What happens now is, it says (in the first iteration)
Please scan barcode:
But, after going through the process of adding the account, it loops again and says:
Please scan barcode: Numbers only, please.
Please scan barcode:
EDIT:
Please note, everything is inside a while loop, so that when everything that the user has done is finished, it'll return to:
Please scan barcode:
I think what you want is this:
Scanner input = new Scanner(System.in);
while (true) {
System.out.print("Please scan barcode: ");
int inCode = 0;
try {
inCode = Integer.parseInt(input.next());
if (inCode != 0) {
// Do Stuff
break;
}
} catch (NumberFormatException e) {
System.out.println("Numbers only, please.");
}
}
The code you have could be structured better, which would both make it clearer what is happening and easier to track down problems. You only want to loop on the data input - so just loop on the data input:
int inCode = 0;
while (true) {
System.out.print("Please scan barcode: ");
try {
inCode = Integer.parseInt(input.next());
break;
} catch (NumberFormatException e) {
System.out.println("Numbers only, please.");
}
}
// Do stuff
You should consider using scanner.hasNextInt() and scanner.nextInt() rather than scanner.next() though. This will also avoid the need for using the exception like this. Normally using Exceptions to control program flow is a bad idea - really they should be used for handling exceptional circumstances. Integer.parseInt doesn't give you any alternatives, but scanner does.
After the edits, it's clear what the problem is: your while (true) loop doesn't have a break statement in it, so it will keep looping forever.
Personally, I'd suggest moving most of your code out of the loop, and only keeping the barcode-parsing code in it, e.g. like this:
int inCode;
while (true) {
System.out.print("Please scan barcode: ");
try {
inCode = Integer.parseInt(input.next());
if (inCode == 0) {
System.out.println("Code can't be zero!");
} else {
break; // we got a valid barcode! end the loop and move on...
}
} catch (NumberFormatException e) {
System.out.println("Numbers only, please.");
// no need for a "continue" here, since the loop will restart anyway
}
}
// rest of the code here...
or possibly even:
int inCode;
while (true) {
System.out.print("Please scan barcode: ");
try {
inCode = Integer.parseInt(input.next());
} catch (NumberFormatException e) {
System.out.println("Numbers only, please.");
continue;
}
if (inCode == 0) {
System.out.println("Code can't be zero!");
continue;
}
break; // we have a valid barcode! end the loop and move on...
}
// rest of the code here...
I would just continue the loop if there's bad input, then you don't need to test it later:
while (true) {
System.out.print("Please scan barcode: ");
int inCode = 0;
try {
inCode = Integer.parseInt(input.next());
} catch (NumberFormatException e) {
System.out.println("Numbers only, please.");
continue; // ADDED THIS LINE
}
// Do Stuff with inCode
}
Note that by your code testing for zero after the input, you preclude zero as valid input. This code allows any number, including zero. Small point, but there's no worries about edge cases.
You can try this
String in=null;
while (true) {
System.out.print("Please scan barcode: ");
int inCode = 0;
try {
in= input.next();
inCode=Integer.parseInt(in);
} catch (NumberFormatException e) {
System.out.println("Numbers only, please.");
}
if (inCode != 0) {
// Do Stuff
} else {
// Repeat loop
}
or you can directly read an integer through Scanner object instead of using Integer.parseInt() method.
int inCode=0;
while(true) {
System.out.print("Please scan barcode : ");
inCode=input.nextInt();
if(inCode!=0){ //do stuff }
else { //Repeat Loop }
}
I have been trying to stop the exceptions but I cannot figure out how.
I tried parseInt, java.util.NormalExceptionMismatch etc.
Does anyone have any insight how to fix this problem? Formatting is a bit off due to copy and paste.
do
{
System.out.print(
"How many integers shall we compare? (Enter a positive integer):");
select = intFind.nextInt();
if (!intFind.hasNextInt())
intFind.next();
{
// Display the following text in the event of an invalid input
System.out.println("Invalid input!");
}
}while(select < 0)
Other methods I have tried :
do
{
System.out.print(
"How many integers shall we compare? (Enter a positive integer):");
select = intFind.nextInt();
{
try{
select = intFind.nextInt();
}catch (java.util.InputMismatchException e)
{
// Display the following text in the event of an invalid input
System.out.println("Invalid input!");
return;
}
}
}while(select < 0)
It seems to me that you want to skip everything until you get an integer. This code here skips any input except an integer.
As long as there is no integer available (while (!in.hasNextInt())) discard the available input (in.next). When integer is available - read it (int num = in.nextInt();)
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (!in.hasNextInt()) {
in.next();
}
int num = in.nextInt();
System.out.println("Thank you for choosing " + num + " today.");
}
}
Quick sample of how to catch exceptions:
int exceptionSample()
{
int num = 0;
boolean done = false;
while(!done)
{
// prompt for input
// inputStr = read input
try {
num = Integer.parseInt(inputStr);
done = true;
}
catch(NumberFormatException ex) {
// Error msg
}
}
return num;
}
IMO, the best practice is to use nextLine() to get a String input, then parseInt it to get the integer. If unparsable, just complain back to the user and request re-entry.
Remember you may have to do a second nextLine() (discard the input) to clear up the buffer.