This question already has answers here:
How to handle infinite loop caused by invalid input (InputMismatchException) using Scanner
(5 answers)
Closed 6 years ago.
boolean z = false;
do {
try {
a = sc.nextInt();
z = true;
}
catch(Exception e) {
}
}
while(!z);
Try this. If you try an integer the first time it executes properly. However if you enter the wrong type of text it turns into an infinite loop even if you enter an int next and skips assigning the boolean value to true. Why is this?
Your problem is from not handling the end of line token and so the scanner is left hanging. You want to do something like so:
import java.util.Scanner;
public class Foo2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = 0;
boolean catcher = false;
do {
try {
System.out.print("Enter a number: ");
a = sc.nextInt();
catcher = true;
} catch (Exception e) {
} finally {
sc.nextLine();
}
}
// !!while(catcher == false);
while (!catcher);
System.out.println("a is: " + a);
}
}
Also, while (z == false) is bad form. You're much better off with while (!z). This prevents the while (z = false) error, and is a cleaner way of expressing this.
edit for Marcelo:
Marcelo, thanks for your input and advice! Are you saying that the conditional in the if block below will not change the value of the boolean, spam?
boolean spam = true;
if (spam = false) {
System.out.println("spam = false");
}
System.out.printf("spam = %b%n", spam);
Because if it does change it, the coder wouldn't expect this if they intended to write if (spam == false), then there could be subtle and dangerous side effects from this. Again, thanks for helping to clarify this for me!
Related
This question already has answers here:
How to use this boolean in an if statement?
(8 answers)
Closed 6 years ago.
Question 1: If an int greater or equal to 2 is entered by the user the first if statement becomes true and the code is executed setting the boolean error1 variable to false. The do loop should only repeat if the error1 variable is true according to my while statement. However the loop repeats regardless.
How can I make the first if statement when set to true exit the loop?
Question 2: I am using a try-catch code to help repeat the the do-while loop if anything other than an int is entered by the user. However, when something like abc or 12.3 is entered the first println of the try code is executed, the second line of the try statement asking for user input is ignored and the catch code is executed again. This becomes a non-terminating loop without user input.
How can I get the statement to ask for user input after the catch code is executed?
Here is my code:
import java.util.InputMismatchException;
import java.util.Scanner;
public class DeepbotCalc {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int points = 0;
boolean error1 = false;
do {
try {
System.out.println("How many points do you currently have?");
points = input.nextInt();
if (points >= 2){
error1 = false;
}
else if (points > 0 && points < 2) {
System.out.println("you need at least 2 points");
error1 = true;
}
else if (points <= 0) {
System.out.println("Please enter a positive whole number");
error1 = true;
}
} catch (InputMismatchException e){
System.out.println("Please enter a positive whole number.");
error1 = true;
}
} while (error1 = true);
This solves your problem:
import java.util.InputMismatchException;
import java.util.Scanner;
public class DeepbotCalc {
public static void main(String[] args) {
Scanner input;
int points = 0;
boolean error1 = false;
do {
try {
input = new Scanner(System.in);
System.out.println("How many points do you currently have?");
points = input.nextInt();
if (points >= 2) {
error1 = false;
}
else if (points > 0 && points < 2) {
System.out.println("you need at least 2 points");
error1 = true;
}
else if (points <= 0) {
System.out.println("Please enter a positive whole number");
error1 = true;
}
}
catch (InputMismatchException e) {
System.out.println("Please enter a positive whole number.");
error1 = true;
}
} while (error1);
}
}
I changed while(error1 = true) by while(error1), and added a new line of code in the try{} statement.
Each time the try{} statement is executed, a new Scanner object is created overriding the last one.
To stop the loop when the correct input is inserted,
while (error1 = true);
should become
while (error1 == true);
or even better
while(error1);
To fix the endless loop when the incorrect input is inserted, inside the catch add
input.nextLine();
to let the scanner "move on"
There are several questions I would like to ask, please refer the comment part I have added in the code, Thanks.
package test;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test {
/* Task:
prompt user to read two integers and display the sum. prompt user to read the number again if the input is incorrect */
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean accept_a = false;
boolean accept_b = false;
int a;
int b;
while (accept_a == false) {
try {
System.out.print("Input A: ");
a = input.nextInt(); /* 1. Let's enter "abc" to trigger the exception handling part first*/
accept_a = true;
} catch (InputMismatchException ex) {
System.out.println("Input is Wrong");
input.nextLine(); /* 2. I am still not familiar with nextLine() parameter after reading the java manual, would you mind to explain more? All I want to do is "Clear Scanner Buffer" so it wont loop for the println and ask user to input A again, is it a correct way to do it? */
}
}
while (accept_b == false) {
try {
System.out.print("Input B: ");
b = input.nextInt();
accept_b = true;
} catch (InputMismatchException ex) { /*3. Since this is similar to the above situation, is it possible to reuse the try-catch block to handling b (or even more input like c d e...) exception? */
System.out.println("Input is Wrong");
input.nextLine();
}
}
System.out.println("The sum is " + (a + b)); /* 4. Why a & b is not found?*/
}
}
I am still not familiar with nextLine() parameter after reading the java manual, would you mind to explain more? All I want to do is "Clear Scanner Buffer" so it wont loop for the println and ask user to input A again, is it a correct way to do it?
The use of input.nextLine(); after input.nextInt(); is to clear the remaining content from the input stream, as (at least) the new line character is still in the buffer, leaving the contents in the buffer will cause input.nextInt(); to continue throwing an Exception if it's no cleared first
Since this is similar to the above situation, is it possible to reuse the try-catch block to handling b (or even more input like c d e...) exception?
You could, but what happens if input b is wrong? Do you ask the user to re-enter input a? What happens if you have 100 inputs and they get the last one wrong?You'd actually be better off writing a method which did this for, that is, one which prompted the user for a value and returned that value
For example...
public int promptForIntValue(String prompt) {
int value = -1;
boolean accepted = false;
do {
try {
System.out.print(prompt);
value = input.nextInt();
accepted = true;
} catch (InputMismatchException ex) {
System.out.println("Input is Wrong");
input.nextLine();
}
} while (!accepted);
return value;
}
Why a & b is not found?
Because they've not been initialised and the compiler can not be sure that they have a valid value...
Try changing it something more like.
int a = 0;
int b = 0;
Yes, it's okay. And will consume the non-integer input.
Yes. If we extract it to a method.
Because the compiler believes they might not be initialized.
Let's simplify and extract a method,
private static int readInt(String name, Scanner input) {
while (true) {
try {
System.out.printf("Input %s: ", name);
return input.nextInt();
} catch (InputMismatchException ex) {
System.out.printf("Input %s is Wrong%n", input.nextLine());
}
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int a = readInt("A", input);
int b = readInt("B", input);
System.out.println("The sum is " + (a + b));
}
I have put comment to that question line.
package test;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean accept_a = false;
boolean accept_b = false;
int a=0;
int b=0;
System.out.print("Input A: ");
while (accept_a == false) {
try {
a = input.nextInt(); // it looks for integer token otherwise exception
accept_a = true;
} catch (InputMismatchException ex) {
System.out.println("Input is Wrong");
input.next(); // Move to next other wise exception // you can use hasNextInt()
}
}
System.out.print("Input B: ");
while (accept_b == false) {
try {
b = input.nextInt();
accept_b = true;
} catch (InputMismatchException ex) {
System.out.println("Input is Wrong");
input.next();
}
}
System.out.println("The sum is " + (a + b)); // complier doesn't know wheather they have initialised or not because of try-catch blocks. so explicitly initialised them.
}
}
Check out this "nextLine() after nextInt()"
and initialize the variable a and b to zero
nextInt() method does not read the last newline character.
This question already has answers here:
What's the best way to check if a String represents an integer in Java?
(40 answers)
Closed 8 years ago.
import java.util.Scanner;
public class test {
/**
* #param args
*/
public static void main(String[] args)
{
Scanner input = new Scanner (System.in);
boolean US1 = false;
boolean game;
int score = 1;
int wage = 0;
int fin_score = 0;
String ans;
if (US1 == false) {
game = false;
System.out.println (score);
System.out.println("Enter a wager");
wage = input.nextInt();
}
if (wage < score) {
System.out.println ("What is the capital of Liberia?");
ans = input.next();
if (ans.equalsIgnoreCase("Monrovia")) {
System.out.println ("You got it right!");
System.out.println ("Final score " + fin_score);
}
}
}
}
I have found a bunch of solutions using InputMismatchException and try{}catch{} but they never work when they are implemented in my code. is there a way to implement these here? I am trying to make a loop that iterates until the wage entered is an integer
You can have multiple catch exceptions in your code to check for bad input. For example
try{
wage = input.nextInt();
catch (InputMismatchException e){
System.out.print(e.getMessage());
//handle mismatch input exception
}
catch (NumberFormatException e) {
System.out.print(e.getMessage());
//handle NFE
}
catch (Exception e) {
System.out.print(e.getMessage());
//last ditch case
}
Any of these would work fine for Scanner errors, but InputMismatchException is the best to use. It would help your case a great deal if you included the non-working code with the try-catch blocks.
First of all, You should be using Scanner.nextLine, because Scanner.nextInt uses spaces and newlines as delimiters, which is probably not what you want (any thing after a space will be left on the scanner, breaking any next reads).
Try this instead:
boolean valid = false;
System.out.print("Enter a wager: "); //Looks nicer when the input is put right next to the label
while(!valid)
try {
wage = Integer.valueOf(input.nextLine());
valid = true;
} catch (NumberFormatException e) {
System.out.print("That's not a valid number! Enter a wager: ");
}
}
Yes! There is a good way to do this:
Scanner input = new Scanner(System.in);
boolean gotAnInt = false;
while(!gotAnInt){
System.out.println("Enter int: ");
if(input.hasNextInt()){
int theInt = input.nextInt();
gotAnInt = true;
}else{
input.next();
}
}
I tried to find a solution for my problem, but couldn't find one that worked in practice. So please, if YOU'RE NOT SURE you know what the solution is, don't answer. I really need concrete help.
The problem is that when I run my simple code - you can pick a number and it's ok, loop is working fine. When you pick 0, it works too (run is finished), but when you put a letter or any string - there's a problem... an exception keeps looping without stop, even if I try inputting another value.
PS. I need to use Scanner here so please don`t write about readers etc. - just how to solve this specific problem.
Cheers,
Here's code (only main):
public static void main(String[] args) {
// TODO code application logic here
Scanner sc = new Scanner(System.in);
int dane = -1 ;
boolean keepLooping; //if you delete this works the same with same problem
do
{
keepLooping = false;
try
{
System.out.println("Pick a number:");
dane = sc.nextInt();
}catch (InputMismatchException e)
{
System.out.println("Your exception is: " + e);
keepLooping = false;
}
System.out.println("Out from exception");
}while ((dane != 0)||(keepLooping == true));
}
Try this:
public static void main(String[] args) {
// TODO code application logic here
Scanner sc = new Scanner(System.in);
int dane = -1 ;
boolean keepLooping = true; //if you delete this works the same with same problem
while(keepLooping && dane != 0)
{
System.out.println("Pick a number:");
try
{
dane = Integer.parseInt(sc.next());
}catch (NumberFormatException e)
{
keepLooping = true;
}
System.out.println("Out from exception");
}
Problem is when you say -
dane = sc.nextInt();
in the above line if you give an input of anything else than a number it will throw an exception input mismatch.
Lets understand what this line does. actually two things -
first sc.nextInt() reads an integer and only on successfull completion of this task it will assign that integer value to variable dane. but while reading an integer it throws an InputMismatchException so the assignment never happened and yet dane has it's previos value not the new one which scanner read so dane is still not equals to 0.
so the loop continues.
I hope it helps.
Edited
Do like this
public static void main(String[] args) {
// TODO code application logic here
Scanner sc = new Scanner(System.in);
int dane = -1 ;
boolean keepLooping; //if you delete this works the same with same problem
do
{
keepLooping = false;
try
{
System.out.println("Pick a number:");
dane = sc.nextInt();
}catch (InputMismatchException e)
{
System.out.println("Your exception is: " + e);
keepLooping = false;
dane = sc.nextInt();
}
System.out.println("Out from exception");
}while ((dane != 0)||(keepLooping == true)&&(dane!=0));
}
I don't understand the logic to this. If I run this code and enter a non-int such as the letter f, I get stuck in an infinite loop outputting the two println's and I am not given another chance to input an int to the scanner...it just keeps spitting out words to the console.
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);//<<<<<SCANNER HERE
int opponents = 0;
boolean opponentsCreated = false;
while(opponentsCreated == false)
{
try
{
System.out.print("How many players: ");
int tempOpponents = scan.nextInt();
if(tempOpponents > 0)
{
opponents = tempOpponents;
opponentsCreated = true;
}
}
catch(InputMismatchException notAValidInt)
{
System.out.println("Not valid - must be a number greater than 0 ");
}
}
}
But if I simply change the Scanner to be declared inside the while loop, all of a sudden the program works as expected:
public static void main(String[] args) {
int opponents = 0;
boolean opponentsCreated = false;
while(opponentsCreated == false)
{
Scanner scan = new Scanner(System.in);//<<<<<SCANNER HERE
try
{
System.out.print("How many players: ");
int tempOpponents = scan.nextInt();
if(tempOpponents > 0)
{
opponents = tempOpponents;
opponentsCreated = true;
}
}
catch(InputMismatchException notAValidInt)
{
System.out.println("Not valid - must be a number greater than 0 ");
}
}
}
I honestly just sat here for 2 hours trying to figure out what the heck was wrong with my program only to find out it was a matter of where I declared my Scanner even though in both versions of the code the Scanner was not out of scope. So now I'm really curious why it works this way
Adding on to #HovercraftFullOfEels answer:
The root cause is, the scanner position does not move in case of the said exception. So scanner keeps reating same bad input again and again. Quoting JavaDoc
If the translation is successful, the scanner advances past the input
that matched.
catch(InputMismatchException notAValidInt)
{
scan.reset();
System.out.println("Not valid - must be a number greater than 0 ");
//position is still 0
scan.next(); //position is now 1
}
To visualize:
Input: f______________
Scanner position: ^______________
InputMismatchException ^______________
scan.next() _^_____________
Relevant source (look at the source comment):
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());
}
One possible problem is that you may be leaving the end of line token hanging when an excpetion occurs. If you handle this by making sure to swallow the end of line token when needed, you are likely OK. For example:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);// <<<<<SCANNER HERE
int opponents = 0;
boolean opponentsCreated = false;
while (opponentsCreated == false) {
try {
System.out.print("How many players: ");
int tempOpponents = scan.nextInt();
// line below corrected!
scan.nextLine(); // *** this might not be a bad idea either ***
if (tempOpponents > 0) {
opponents = tempOpponents;
opponentsCreated = true;
}
} catch (InputMismatchException notAValidInt) {
System.out.println("Not valid - must be a number greater than 0 ");
scan.nextLine(); // ****** this is what you need here *****
}
}
}
Nice question, by the way!