Java Do While statement looping infinitely after Try Catch statement [duplicate] - java

This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
I am currently working on some Java code in Eclipse and trying to use a try-catch statement inside of a do-while statement. My current code is as follows:
import java.util.Scanner;
import java.util.InputMismatchException;
import java.util.Random;
public class GG_HighLowInvalid{
public static void main(String[] args){
Scanner cg = new Scanner(System.in);
//Assign and define variables
int guess, rand;
guess = 0;
rand = 10;
//Create loop
do
try{
guess = 0;
//Ask for a guess
System.out.print("Enter your guess: ");
//Record the guess
guess = cg.nextInt();
}
catch(InputMismatchException exception){
System.out.println("Your guess must be an integer.");
}
while (guess != rand);
}
}
When I put in any number, the code works fine and will loop to ask for another input and when 10 is entered, the code stops as it is supposed to (because guess becomes equal to rand). However, if I put in anything that is not an integer (such as "No"), an infinite loop occurs where the output prints the following:
"Your guess must be and integer."
"Enter your Guess: Your guess must be an integer."
"Enter your Guess: Your guess must be an integer."
"Enter your Guess: Your guess must be an integer."
repeating forever until the program is externally terminated.
Since the while statement is (guess != rand), why is a non-integer causing this infinite loop? Shouldn't the manual input under the try-statement be called again? Any assistance in understanding this would be greatly appreciated. Also, I am pretty new to Java, so sorry in advance if I am having simple issues.

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.
Currently, your Scanner is not moving ahead to read the next input but reading the same continuously. You have to explicitly call some method which can read this incorrect value which was not expected. For example, scanner.next() call in catch block can avoid this infinite loop.

Use the following code:
catch(InputMismatchException exception){
cg.next();
System.out.println("Your guess must be an integer.");
}
After you have unsuccessfully read buffer its value isn't emptied and next time when it came to cg.nextInt() it tries to read same wrong value, and you went to loop. You need "to empty buffer", so next time it will read correct value.

You dont need to use a try catch statement. You just have to check if it is an integer or not with the hasNextInt() method of your object scanner. This is an example, it will solve your problem:
public static void main(String[] args) {
Scanner cg = new Scanner(System.in);
boolean valid = false;
//Assign and define variables
int guess, rand;
guess = 0;
rand = 10;
//Create loop
do{
System.out.println("Enter your guess: ");
if(cg.hasNextInt()){
guess = cg.nextInt();
valid = true;
}else{
System.out.println("Your guess must be an integer.");
cg.next();
}
}while (!valid || guess != rand);
}

Try resetting your variable "guess = 0" in catch block.

Related

Is there another way to use hasNextInt() in Java without putting everything in the if-statement?

My objective is to make sure the user inputs an int. Else, exit the program. Then I do some coding that requires that int.
Code Snippet :
Scanner input = new Scanner(System.in);
if (input.hasNextInt()) {
//check if user enters an int
int userinput = input.nextInt();
// assign that int input to variable userinput
// over 100+ lines of code using nextInt var "userinput"
} else {
System.exit(1);
// user did not enter an int
}
Is there a better way to check for whether a user has entered an int and then use that int that doesn't require my entire program to be coded into that if-statement (because nextInt's scope is limited to that if-statement)?
It feels messy to me to put everything into one if-statement.
I wouldn't be allowed to use separate objects/classes since it's early in the semester for my class. This all goes in the main method, and I'm just using simple if-statements/scanner inputs.
Thanks
Definitely! Just negate the if statement and early exit:
Scanner input = new Scanner(System.in);
if (!input.hasNextInt()) {
System.exit(1);
}
// "else"
doMagicalThings(input.nextInt());
Oh, I guess also to note: replace the 100 lines of code with a method call and break it up a bit. That'd be good to do in addition to the above.
Here is a simple example of using hasNextInt () to validate a positive integer input
Scanner input = new Scanner(System.in);
int number;
do {
System.out.println("Input Number ");
while (!input.hasNextInt()) {
System.out.println(" not a number!");
input.next();
}
number = input.nextInt();
} while (number <= 0);
System.out.println("Númber válid " + number);

While loop breaks after bufferedInput change [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
I'm doing some basic homework, and it's honestly all stuff I know. But I decided to jazz it up a little, and something I'm missing is causing an unexpected error.
The idea is to use a while loop which asks if the user would like to do something. So long as they say yes, the loop continues the operations that it holds (in this case rounding a decimal to an int). However, as soon as I enter yes, or anything really, the loop breaks there and won't continue on to the rounding portion.
public class DecimalRounder {
//Main class method that starts and ends the program. It is prepared to throw an IO exception if need be.
public static void main(String args[])throws IOException
{
//Main initializes a new reader to take input from System.in
InputStreamReader rawInput = new InputStreamReader(System.in);
//Main then initializes a new buffer to buffer the input from System.in
BufferedReader bufferedInput = new BufferedReader(rawInput);
//Main initializes other used variable
double castInput = 0.0;
String contin = "yes";
//Program then sets up loop to allow user to round numbers till content
while (contin == "yes")
{
//Program asks user if they'd like to round.
System.out.println("Would you like to round? Type yes to continue... ");
contin = bufferedInput.readLine();
//If user says yes, rounding begins. ERROR FOUND HERE?
if (contin == "yes") //INPUT "yes" DOESN'T MATCH?
{
//Program then requests a decimal number
System.out.println("Please enter a decimal number for rounding: ");
String givenLine = bufferedInput.readLine();
//rawInput is worked on using a try catch statement
try {
//givenLine is first parsed from String into double.
castInput = Double.parseDouble(givenLine);
//castInput is then rounded and outputted to the console
System.out.println("Rounded number is... " + Math.round(castInput));
//Branch then ends restarting loop.
}catch(Exception e){
//If the data entered cannot be cast into a double, an error is given
System.err.println("That is not a roundable number: " + e.getMessage());
//And branch ends restarting loop.
}
}
}
System.out.println("Have a nice day!");
}
}
Use .equals instead of == to compare strings in JAVA.
Try this :
contin.equals("yes")

How to ask te user and depending on his response run all the code again?

I'm a newbie in Java. I started these days and I'm practicing the catch and try exception. I have this code below which solve an operation between to numbers and I'd like to know what can I do, if for example I want that the user, once he makes an operation and get his result, that this has the possibility to make another operation. something like comes up a question asking if he wants to realize another problem and the code run again from the beginning.
package justpractice;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner Operation = new Scanner(System.in);
int x=1;
while(x==1){
try{
System.out.println("Insert numerator");
int n1 = Operation.nextInt();
System.out.println("Insert denominator");
int n2=Operation.nextInt();
double division = n1/n2;
System.out.println(division);
x=2;
}
catch(Exception e){
System.out.println("Insert a valid value");
}
}
}
}
You can do, for example, adding an if statement with a
System.out.println("Do you want to recalculate ? (1/0 Yes/No)");
Operation.nextInt();
then if the input is 1, keep x = 1, else do x = 2.
Try this code amendment;
package justpractice;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner Operation = new Scanner(System.in);
//better practice
while(true){
try{
System.out.println("Insert numerator");
int n1 = Operation.nextInt();
System.out.println("Insert denominator");
int n2=Operation.nextInt();
double division = n1/n2;
System.out.println(division);
System.out.println("Continue? (y/n)");
String response = Operation.nextLine();
if (response.equals("n")){
break;
}
}
catch(Exception e){
System.out.println("Insert a valid value");
}
}
}
}
To allow your user to calculate division again, you could use a do-while loop. With this loop you can execute the code inside once, ask the user if they would like to calculate again, and repeat the code if they do.
An outline of your code with the loop would something like this:
...
boolean again = true;
do { //Main loop
try {
... //Your division code
... //Put code to ask the user if they want to calculate again here
} catch(Exception e) {
...
}
} while(again == true); //Repeat if the user wants to continue
To get input on if the user wants to calculate again, I recommend using another do-while loop with your Scanner. This loop will allow you to repeat the code when the answer is invalid. In this case, when it's not "y" or "n".
String input;
do {
System.out.println("Would you like to continue? (y/n)");
input = operation.next();
} while(!input.equalsIgnoreCase("y") && !input.equalsIgnoreCase("n"));
After you have got the user's input, you still need to terminate the loop if they said "n". To do this you could use an if statement.
if(input.equalsIgnoreCase("n")) {
again = false; //Terminate the main loop
operation.close(); //Prevent any resource leaks with your Scanner
}
There is no need to check if the user input "y" as again is set to true by default.
Side Note: Variables should always be camelCase. Look at the Java Naming Conventions to learn more about naming things in Java.
EDIT:
The reason the console is repeatedly logging that you entered a non-number even though you entered it once, I'm not exactly sure. I think it's because the call to nextInt() never finishes because of the InputMismatchException being thrown, causing the next call to nextInt() (After the do-while repeats) to think that the letter/symbol you just entered is the one you want to process, repeating the exception over and over again.
To solve this, add this line into your catch block:
if(operation.hasNext()) operation.next();
This will call next() and complete the process of marking the letter/symbol you just entered as already processed, then repeat the do-while loop as normal.

Why does this code using nextInt() loops forever? [duplicate]

This question already has answers here:
Endless while loop problem with try/catch
(2 answers)
Closed 7 years ago.
Below code,
import java.util.Scanner;
public class Dummy {
static Scanner sc = new Scanner(System.in);
public static int getIntegerInput(String prompt){
int choice = 0;
for(;;){
System.out.print(prompt);
try{
choice = sc.nextInt();
break;
}catch(java.util.InputMismatchException ex){
System.out.print("What??? ");
}
}
return choice;
}
public static void main(String[] args) {
int choice = getIntegerInput("Enter a number: ");
} //end main
}
does not stop for next user input, if the first user input raised an exception.
How do I understand this problem in the above code? placing sc.next() in catch resolves the problem. But I'm still not clear what is going on under the hood? What is the right approach to resolve this problem?
When nextXYZ() fails to consume a token it leaves it in the InputStream. Here, you are looping over the same input endlessly - each iteration, you attempt to consume this token, throw an exception if it isn't an integer, catch it, and try reading it again - forever.
EDIT:
In order to work around this, you could use next() to consume that token and move on to the next one:
for(;;) {
System.out.print(prompt);
try{
choice = sc.nextInt();
break;
} catch(java.util.InputMismatchException ex) {
sc.next(); // here
}
}
The problem with Scanner next() are they will not advances if the match is not found. And the character for which it failed remain in the stream. Hence its very important to advance the scanner if you found non intended character.
You can use next() method which actually consumes any character or you can use skip method passing skip pattern.
Use hasNext() to know whether a valid match is present or not. If not then consume that character using above said methods.
If it doesnt find an int on the next like, it throws an error. This error is then caught by your program, so the break is never hit because the error jumps over it whenever a non-int (including nothing) is found.

Try catch block causing infinite loop? [duplicate]

This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
I am writing a simple java console game. I use the scanner to read the input from the console. I am trying to verify that it I ask for an integer, I don't get an error if a letter is entered. I tried this:
boolean validResponce = false;
int choice = 0;
while (!validResponce)
{
try
{
choice = stdin.nextInt();
validResponce = true;
}
catch (java.util.InputMismatchException ex)
{
System.out.println("I did not understand what you said. Try again: ");
}
}
but it seems to create an infinite loop, just printing out the catch block. What am I doing wrong.
And yes, I am new to Java
nextInt() won't discard the mismatched output; the program will try to read it over and over again, failing each time. Use the hasNextInt() method to determine whether there's an int available to be read before calling nextInt().
Make sure that when you find something in the InputStream other than an integer you clear it with nextLine() because hasNextInt() also doesn't discard input, it just tests the next token in the input stream.
Try using
boolean isInValidResponse = true;
//then
while(isInValidResponse){
//makes more sense and is less confusing
try{
//let user know you are now asking for a number, don't just leave empty console
System.out.println("Please enter a number: ");
String lineEntered = stdin.nextLine(); //as suggested in accepted answer, it will allow you to exit console waiting for more integers from user
//test if user entered a number in that line
int number=Integer.parseInt(lineEntered);
System.out.println("You entered a number: "+number);
isInValidResponse = false;
}
//it tries to read integer from input, the exceptions should be either NumberFormatException, IOException or just Exception
catch (Exception e){
System.out.println("I did not understand what you said. Try again: ");
}
}
Because of common topic of avoiding negative conditionals https://blog.jetbrains.com/idea/2014/09/the-inspection-connection-issue-2/

Categories