java nextInt() try catch repeating output more than once - java

I am writing a program that accepts two ints within the program using nextInt(); and have it wrapped in a try catch block to stop bad inputs such as doubles or chars.
When multiple wrong inputs are entered the loop repeats that same number of times. I assume this is because my scan.next() has to loop around enough times to catch the bad inputs w/o error. Is there a way to know this number on the first run through to make a loop to run next in that many times?
In the output the
if(cont == 'N') System.out.print("\nPlease re-enter\n\t:"); will output and mirror the amount of times a mismatched input was written. That is, if I input 3 3.3 it will repeat one extra time, if input s 3.3 2.5 it will repeat three extra times.
I tried putting a loop around scan.next() to default it to ten times, but was overboard and I had to input an extra 8 characters before it started reading again. Maybe a while loop but what would its condition be, I tried while(scan.next() != null){} but that condition never stopped.
//input error checking
char cont = 'Y';
do{
if(cont == 'N')
System.out.print("\nPlease re-enter\n\t:");
cont = 'Y';
/* to stop the accidential typing of things other
* than integers from being accepted
*/
try{
n1 = scan.nextInt();
n2 = scan.nextInt();
}catch(Exception e){
cont = 'N'; //bad input repeat loop
scan.next();//stops infinite loop by requesting Scanner try again
}
} while(cont == 'N');//do loop while told N for continue

Not sure what you want your code to do. From reading what you have posted I assume you want the user to input 2 ints and if he/she doesn't you want to prompt him/her to re-enter something until he/she inputs 2 ints.
If this is the case I would just add
scan = new Scanner(br.readLine());
after this if statement:
if(cont == 'N')
{System.out.print("\nPlease re-enter\n\t:");}
This will solve your looping issue

First try :
change the line in the exception catch from
scan.next();
to
while(scan.hasNext()){
scan.next();
}

You can try to do the following in your catch block:
while(scan.hasNext())
scan.next();

make it a method and do it with that method.
sth like this:
// do it until getting two Integers
boolean isItInteger = false;
while (isItInteger == false) {
isItInteger = getInt();
}
.
.
.
// your method for getting two Integers
public static boolean getInt() {
try {
Scanner sc = new Scanner(System.in);
n1 = sc.nextInt();
n2 = sc.nextInt();
} catch (Exception e) {
System.out.println("Please re-enter");
return false;
}
return true;
}

Related

How to have check user input using scanner without having scanner prompt multiple times

So im writing a couple methods that require the user to input what hour(1-24) they want. I need however to check whether they enter in an int, and a number between 1-24. The problem is that the scanners are called multiple times if sent to the error statement. I don't know how to do this without having these issues.
public static int getHour(Scanner scan){
int hour=0;
System.out.println("Enter the hour for the showtime (1-24):");
do{
if((!scan.hasNextInt())||((hour=scan.nextInt())<1)||(hour>24)){
System.out.println("Enter a valid number");
scan.next();
} else{
return hour;
}
}while((!scan.hasNextInt())||(hour<1)||(hour>24));
return hour;
}
Ideally it only prompts one time when entering in a not valid input such as a string or int outside of 1-24. but it prompts twice or sometimes once depending on the order of what incorrect input you put in.
Any help would be appreciated, thanks
You're encountering this problem because .hasNextInt() does not advance past the input, and .nextInt() only advances if translation is successful. A combination of loops and if-statements can thus cause confusion as to whether or not the scanner will advance. Here's your method rewritten to have the scanner prompt only once for each bad input:
public int getHour(Scanner scan) {
System.out.printf("%nEnter the hour for the showtime (1-24): ");
while (true) {
input = scan.next();
entry = -1;
try {
entry = (int)Double.parseDouble(input);
} catch (NumberFormatException e) {
// Ensures error is printed for all bad inputs
}
if (entry >= 1 && entry <= 24) {
return entry;
}
System.out.printf("%nEnter a valid number: ");
}
}
I prefer to use an infinite loop in this case, but as that can be dangerous, receive it with caution. Hope this helps!

How to scan an indefinite list of numbers from a single input?

How to scan an indefinite list of numbers from a single input?
I did a brief google search and found hasNextInt(), but it only stops scanning if the last input is NOT an integer, while I need it to stop if it's the last integer. For example, it will continue to ask me if my list ends with an integer.
My code:
System.out.println("Enter a list of numbers");
int n = 0;
while (input.hasNextInt()){
n = input.nextInt();
List.push(n);
}
List.displayStack();
You may use hasNext() instead. Then parse the input and get the number -
int n=0;
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
try {
n = Integer.parseInt(input.nextLine());
//do something eg.- you have done
//List.push(n);
} catch (NumberFormatException nfe) {
//handle exception
}
}
Now if the input not is an integer then it will not stop. Rather it will go for the catch block. And since the catch block is still in the while loop so you can take a new input still now.
Hope it will help.
Thanks a lot

Do-while, try-catch loop error

Im trying to write code for a school project, the main objective is to get the average gpa of a students semester depending on how many Subjects and Units you input, however, if I try typing 0, the program goes into an infinite try-catch loop with "You can only type positive numbers" Im using valueOf() because I want the user to be able to type "salir" which means exit, to exit the program.
Scanner LeerTeclado = new Scanner(System.in);
int n=0, i=0, suma=0, promedio=0;
String materia, cadena;
//---------------------------------------------------------------------------
out.println("---------------------------");
out.println("-- School Grades --");
out.println("---------------------------");
//---------------------------------------------------------------------------
out.println("\nType 'salir' to terminate the program");
out.println("-----------------------------------------");
out.print("Type the number of subjects to grade: ");
cadena = LeerTeclado.nextLine();
int z = 0;
if("salir".equals(cadena)){
System.exit(0);
}
if("Salir".equals(cadena)){
System.exit(0);
}
///////////////////////////////////////////////////////////////////
do{
try{
z = Integer.valueOf(cadena);
if(z <= 0){
out.println("...............................................");
out.println(" You can only type positive numbers ");
out.println("...............................................");
out.println("\n");
continue;
}
break;
}catch(NumberFormatException ex){
out.println("\n*You have entered non-numeric characters*");
out.print("\nPlease type the number of subjects again: ");
LeerTeclado.nextLine();
}
}while(true);
In the try block, before you write
continue;
but after "You can only type positive numbers," you should prompt the User for another line of input, and wait for the user to enter that.
The "continue" statement skips to the end of the loop and causes the 2nd part of the loop not to run. That is why the loop is running indefinitely.
Move reading cadena into the try block
int z = 0;
do {
try {
cadena = LeerTeclado.nextLine(); // <-- re-read
if ("salir".equalsIgnoreCase(cadena)) { // <-- you might test once.
System.exit(0);
}
// if ("Salir".equals(cadena)) {
// System.exit(0);
// }
z = Integer.valueOf(cadena); // <-- or this loops forever.
Alberto,
There are a few things that need to be changed in order to get this program to work the way you wish. Since you are a student I'm not going to solve it for you. I will answer your question, however.
When you type zero on the command line your program will execute from the z<=0 test down to the continue statement. The continue statement tells the code to ignore everything after and return to the beginning of the loop so it goes back to the beginning of the do statement and repeats. You need some way to end the loop.
May I suggest writing the program a little at a time and test as you go along. That is, write the part that's not in the loop. Once that works write a little something in the loop and test. Keep doing this until the programs works the way you want it to.
Good Luck
do{
try{
z = Integer.valueOf(cadena);
if(z <= 0){
out.println("...............................................");
out.println(" You can only type positive numbers ");
out.println("...............................................");
out.println("\n");
continue;
}
You want to use break
if(z <= 0){
System.out.println("...............................................");
System.out.println(" You can only type positive numbers ");
System.out.println("...............................................");
System.out.println("\n");
break;
}
continue just hops to the top of the if and keeps at it, same thing.

Java .nextLine() repeats line

Everything of my guessing game is alright, but when it gets to the part of asking the user if he/she wants to play again, it repeats the question twice. However I found out that if I change the input method from nextLine() to next(), it doesn't repeat the question. Why is that?
Here is the input and output:
I'm guessing a number between 1-10
What is your guess? 5
You were wrong. It was 3
Do you want to play again? (Y/N) Do you want to play again? (Y/N) n
Here is the code:(It is in Java)
The last do while loop block is the part where it asks the user if he/she wants to play again.
import java.util.Scanner;
public class GuessingGame
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
boolean keepPlaying = true;
System.out.println("Welcome to the Guessing Game!");
while (keepPlaying) {
boolean validInput = true;
int guess, number;
String answer;
number = (int) (Math.random() * 10) + 1;
System.out.println("I'm guessing a number between 1-10");
System.out.print("What is your guess? ");
do {
validInput = true;
guess = input.nextInt();
if (guess < 1 || guess > 10) {
validInput = false;
System.out.print("That is not a valid input, " +
"guess again: ");
}
} while(!validInput);
if (guess == number)
System.out.println("You guessed correct!");
if (guess != number)
System.out.println("You were wrong. It was " + number);
do {
validInput = true;
System.out.print("Do you want to play again? (Y/N) ");
answer = input.nextLine();
if (answer.equalsIgnoreCase("y"))
keepPlaying = true;
else if (answer.equalsIgnoreCase("n"))
keepPlaying = false;
else
validInput = false;
} while (!validInput);
}
}
}
In your do while loop, you don't want the nextLine(), you just want next().
So change this:
answer = input.nextLine();
to this:
answer = input.next();
Note, as others have suggested, you could convert this to a while loop. The reason for this is that do while loops are used when you need to execute a loop at least once, but you don't know how often you need to execute it. Whilst it's certainly doable in this case, something like this would suffice:
System.out.println("Do you want to play again? (Y/N) ");
answer = input.next();
while (!answer.equalsIgnoreCase("y") && !answer.equalsIgnoreCase("n")) {
System.out.println("That is not valid input. Please enter again");
answer = input.next();
}
if (answer.equalsIgnoreCase("n"))
keepPlaying = false;
The while loop keeps looping as long as "y" or "n" (ignoring case) isn't entered. As soon as it is, the loop ends. The if conditional changes the keepPlaying value if necessary, otherwise nothing happens and your outer while loop executes again (thus restarting the program).
Edit: This explains WHY your original code didn't work
I should add, the reason your original statement didn't work was because of your first do while loop. In it, you use:
guess = input.nextInt();
This reads the number off the line, but not the return of the line, meaning when you use:
answer = input.nextLine();
It immediately detects the leftover carriage from the nextInt() statement. If you don't want to use my solution of reading just next() you could swallow that leftover by doing this:
guess = input.nextInt();
input.nextLine();
rest of code as normal...
The problem really lies in a completely different segment of code. When in the previous loop guess = input.nextInt(); is executed, it leaves a newline in the input. Then, when answer = input.nextLine(); is executed in the second loop, there already is a newline waiting to be read and it returns an empty String, which activates the final else and validInput = false; is executed, to repeat the loop (and the question).
One solution is to add an input.nextLine(); before the second loop. Another is to read guess with nextLine() and then parse it into an int. But this complicates things as the input could not be a correct int. On a second thought, the code already presents this issue. Try entering a non-numeric response. So, define a function
public static int safeParseInt(String str) {
int result;
try {
result= Integer.parseInt(str) ;
} catch(NumberFormatException ex) {
result= -1 ;
}
return result ;
}
And then replace your first loop with:
do {
validInput= true ;
int guess= safeParseInt( input.nextLine() ) ;
if( guess < 1 || guess > 10 ) {
validInput= false ;
System.out.print("That is not a valid input, guess again: ");
}
} while( !validInput );
PS: I don't see any problem with do-while loops. They are part of the language, and the syntax clearly indicates that the condition is evaluated after the body is executed at least one time. We don't need to remove useful parts of the language (at least from practice) just because others could not know them. On the contrary: if we do use them, they will get better known!
validInput = false;
do {
System.out.print("Do you want to play again? (Y/N) ");
answer = input.next();
if(answer.equalsIgnoreCase("y")){
keepPlaying = true;
validInput = true;
} else if(answer.equalsIgnoreCase("n")) {
keepPlaying = false;
validInput = true;
}
} while(!validInput);
I changed the coding style as I find this way more readable.
Your problem is that nextInt will stop as soon as the int ends, but leaves the newline in the input buffer. To make your code correctly read the answer, you'd have to enter it on the same line as your guess, like 5SpaceYReturn.
To make it behave more than one would expect, ignore the first nextLine result if it contains only whitespace, and just call nextLine again in that case without printing a message.
I believe the output of input.nextLine() will include the newline character at the end of the line, whereas input.next() will not (but the Scanner will stay on the same line). This means the output is never equal to "y" or "n". Try trimming the result:
answer = input.nextLine().trim();

Java: Infinite loop using Scanner in.hasNextInt()

I am using the following code:
while (invalidInput)
{
// ask the user to specify a number to update the times by
System.out.print("Specify an integer between 0 and 5: ");
if (in.hasNextInt())
{
// get the update value
updateValue = in.nextInt();
// check to see if it was within range
if (updateValue >= 0 && updateValue <= 5)
{
invalidInput = false;
}
else
{
System.out.println("You have not entered a number between 0 and 5. Try again.");
}
} else
{
System.out.println("You have entered an invalid input. Try again.");
}
}
However, if I enter a 'w' it will tell me "You have entered invalid input. Try Again." and then it will go into an infinite loop showing the text "Specify an integer between 0 and 5: You have entered an invalid input. Try again."
Why is this happening? Isn't the program supposed to wait for the user to input and press enter each time it reaches the statement:
if (in.hasNextInt())
In your last else block, you need to clear the 'w' or other invalid input from the Scanner. You can do this by calling next() on the Scanner and ignoring its return value to throw away that invalid input, as follows:
else
{
System.out.println("You have entered an invalid input. Try again.");
in.next();
}
The problem was that you did not advance the Scanner past the problematic input. From hasNextInt() documentation:
Returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. The scanner does not advance past any input.
This is true of all hasNextXXX() methods: they return true or false, without advancing the Scanner.
Here's a snippet to illustrate the problem:
String input = "1 2 3 oops 4 5 6";
Scanner sc = new Scanner(input);
while (sc.hasNext()) {
if (sc.hasNextInt()) {
int num = sc.nextInt();
System.out.println("Got " + num);
} else {
System.out.println("int, please!");
//sc.next(); // uncomment to fix!
}
}
You will find that this program will go into an infinite loop, asking int, please! repeatedly.
If you uncomment the sc.next() statement, then it will make the Scanner go past the token that fails hasNextInt(). The program would then print:
Got 1
Got 2
Got 3
int, please!
Got 4
Got 5
Got 6
The fact that a failed hasNextXXX() check doesn't skip the input is intentional: it allows you to perform additional checks on that token if necessary. Here's an example to illustrate:
String input = " 1 true foo 2 false bar 3 ";
Scanner sc = new Scanner(input);
while (sc.hasNext()) {
if (sc.hasNextInt()) {
System.out.println("(int) " + sc.nextInt());
} else if (sc.hasNextBoolean()) {
System.out.println("(boolean) " + sc.nextBoolean());
} else {
System.out.println(sc.next());
}
}
If you run this program, it will output the following:
(int) 1
(boolean) true
foo
(int) 2
(boolean) false
bar
(int) 3
This statement by Ben S. about the non-blocking call is false:
Also, hasNextInt() does not block. It's the non-blocking check to see if a future next call could get input without blocking.
...although I do recognize that the documentation can easily be misread to give this opinion, and the name itself implies it is to be used for this purpose. The relevant quote, with emphasis added:
The next() and hasNext() methods and their primitive-type companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token. Both hasNext and next methods may block waiting for further input. Whether a hasNext method blocks has no connection to whether or not its associated next method will block.
It is a subtle point, to be sure. Either saying "Both the hasNext and next methods", or "Both hasnext() and next()" would have implied that the companion methods would act differently. But seeing as they conform to the same naming convention (and the documentation, of course), it's reasonable to expect they act the same, and hasNext()
clearly says that it can block.
Meta note: this should probably be a comment to the incorrect post, but it seems that as a new user I can only post this answer (or edit the wiki which seems to be preferred for sytlistic changes, not those of substance).
Flag variables are too error prone to use. Use explicit loop control with comments instead. Also, hasNextInt() does not block. It's the non-blocking check to see if a future next call could get input without blocking. If you want to block, use the nextInt() method.
// Scanner that will read the integer
final Scanner in = new Scanner(System.in);
int inputInt;
do { // Loop until we have correct input
System.out.print("Specify an integer between 0 and 5: ");
try {
inputInt = in.nextInt(); // Blocks for user input
if (inputInt >= 0 && inputInt <= 5) {
break; // Got valid input, stop looping
} else {
System.out.println("You have not entered a number between 0 and 5. Try again.");
continue; // restart loop, wrong number
}
} catch (final InputMismatchException e) {
System.out.println("You have entered an invalid input. Try again.");
in.next(); // discard non-int input
continue; // restart loop, didn't get an integer input
}
} while (true);

Categories

Resources