Scanner expects more input than is needed - java

I'm having an issue with a piece of my code that is meant to validate that user input is an integer and between the numbers 1-6.
The issue is that when I add the validation the scanner waits for input three times before it continues. It functions normally if I don't include the validation code. Any ideas why this would be happening?
int level;
boolean good = false;
double physAct;
System.out.print("On a scale of 1 to 6, how active\ndo you consider yourself?\n1 = lazy, 6 = pro athlete: ");
System.out.flush();
while (!good){
if (!in.hasNextInt()){
in.next();
System.out.print("Sorry, you must enter a whole\nnumber between 1 and 6: ");
} else if ((in.nextInt() < 0) || (in.nextInt() > 7)){
in.next();
System.out.print("Sorry, you must enter a whole\nnumber between 1 and 6: ");
} else {
good = true;
}
}
level = in.nextInt();
switch(level){
case 1:
physAct = 1.2;
break;
After this the switch goes on and is used for some other operations.

Your for loop should read the input once and remember it as mentioned. Otherwise each call to in.nextInt() will block until you enter another integer. Keeping close to your same code you need to do the following.
while (!good){
if (!in.hasNextInt()){
in.next();
System.out.print("Sorry, you must enter a whole\nnumber between 1 and 6: ");
} else {
level = in.nextInt();
if (level < 0 || level > 6) {
System.out.print("Sorry, you must enter a whole\nnumber between 1 and 6: ");
} else {
good = true;
}
}
}
remove the level = in.nextInt(); after the loop since you already read in level.

The problem is that your tests (in.nextInt() < 0) || (in.nextInt() > 7) both call nextInt(). You need to call it once, save the result and check the value on that.
int value = in.nextInt();
...
...(value < 0) || value > 7)

Related

Trouble appropriately constructing do while loops with correct conditions to run

I am struggling to correctly loop the code I have written to convert integers to roman numerals.
I have tried implementing a do while loop to run the code starting at "please enter an integer" and ending after my switch statement with the while part being: while(case "y" || "Y" == true )
Any help would be greatly appreciated. I have been searching through previous posts on stack overflow for a couple hours now and haven't been able to find anything that helps.
public class project8
{
/**
* Constructor for objects of class Project4
*/
public static void main(String[] args) {
System.out.println("Welcome to my integer Roman numeral conversion program");
System.out.println("------------------------------------------------------");
System.out.println(" ");
Scanner in = new Scanner (System.in);
System.out.print("Enter an integer in the range 1-3999 (both inclusive): ");
int input = in.nextInt();
if (input < 0 || input > 3999){
System.out.println("Sorry, this number is outside the range.");
System.out.println("Do you want to try again? Press Y for yes and N for no: ");
String userInput = in.next();
switch (userInput) {
case "N":
case "n":
System.exit(0);
break;
case "Y":
case "y":
break;
}
}
else if (input > 0 && input < 3999);
{ System.out.println(Conversion.Convert(input));
}
}
}
1) Your if - else if conditions are redundant. You can use a simple if - else as input can only be in that range or not. else if makes only sence if you had two or more ranges to check, e.g.
if(input > 0 && input < 3999){
...
}
else if (input > 4000 && input < 8000){
...
}
else {
...
}
2) You don't need a switch block instead use the user input in your while condition as you want to continue looping when user input is Y/y, i.e while(userChoice.equals("Y"))
3) Use a do - while loop as you want that your application to run at least on time
public static void main(String[] args) {
System.out.println("Welcome to my integer Roman numeral conversion program");
System.out.println("------------------------------------------------------");
System.out.println(" ");
Scanner in = new Scanner (System.in);
String choice;
do{
System.out.print("Enter an integer in the range 1-3999 (both inclusive): ");
int input = in.nextInt();
if(input > 0 && input < 3999){
System.out.println(Conversion.Convert(input));
}
else{
System.out.println("Sorry, this number is outside the range.");
}
System.out.println("Do you want to try again? Press Y for yes and N for no: ");
choice = in.next();
}while(choice.equals("Y") || choice.equals("y"));
}

Using while loop for nested if statements

Although I know I'm missing something, can't seem to get my head around a simple loop.
while (true){
if (n < 0)
System.out.print("less than 0")
else if (n > 35)
System.out.print("greater than 35")
else
calc(n)
}
I'm trying to use a while loop to loop the code and asks for input until the user inputs a value greater than 0 and less than 35, I have tried using continue but too no avail, thanks in advanceenter image description here
I have added sc of full code, the while loop will go after requesting input at the bottom of the code
// if using jdk 1.7 or above else close scanner in finally block.
try (Scanner s = new Scanner(System.in)) {
int n;
while (true) {
n = s.nextInt();
if (n < 0) {
// ask for value greater then 0
System.out.print("Please enter a value greater then 0 ");
// extra print statement so input will be printed on next line after message
System.out.println();
} else if (n > 35) {
// ask for value less then 35
System.out.print("Please enter a value less then 35");
System.out.println();
} else {
// process input and break if correct input has received
calc(n);
break;
}
}
}
Well you aren't "asking for input". Also the while loop will NEVER exit. You probably at the minimum want a break in there somewhere.
I think you are missing the input for the user:
Scanner in = new Scanner(System.in);
int n = 0;
while (n != 27){ /*Can be any number here instead of 27, even -1*/
n = in.nextInt();
if (n < 0)
System.out.print("less than 0")
else if (n > 35)
System.out.print("greater than 35")
else
calc(n)
}
Also i would suggest you to not use while(true) becuase you will have endless loop, you can put instead a condition: while(n != 27)
So each time you enter 27 it will end the loop.
I am also not sure of that calc method but maybe you could use something like this?
Boolean checked = true;
While(checked) {
if (n < 0) {
System.out.print("less than 0");
}
else if (n > 35) {
System.out.print("greater than 35")'
}
else {
calc(n)
checked = false;
}
}
Hope it helps. Cheers
How about:
Scanner in = new Scanner(System.in);
int n = 0;
while (true){
n = in.nextInt();
if (n < 0)
System.out.print("less than 0");
else if (n > 35)
System.out.print("greater than 35");
else{
calc(n);
break;
}
}
You are missing two things in your code.
1) Inside while loop, there is no mechanism to update the value of variable n. i.e, if outside loop, the value of n is set to say 2, the loop will keep on printing Greater than 35. So a mechanism is needed to update it's value
2) Breaking mechanism for while loop. Because the condition is while(true) and there is no break inside the loop, the loop will continue endlessly. So, a loop breaking mechanism is needed
Below is a sample code where input is taken from console using Scanner and break is used for loop breaking condition
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = 0;
while (true) {
n = scan.nextInt();
if (n < 0)
System.out.print("less than 0");
else if (n > 35)
System.out.print("greater than 35");
else {
calc(n);
break;
}
}
scan.close();
}
you can use do while. like this:
do {
calc(n);
} while(n < 0 || n > 35)
expect calc(n) function read user input value and put it in n variable.

Going out from a switch inside a do while, but without a boolean, it's possible? Java

So the code is about giving a limit of inputs in a do while.
In this case you have 3 oportunities to continue. After that the do while stops, also you have the oportunitie to stop just presing any key plus enter, but also when you start, do you have the oportunitie (here enters the switch) to exit the program.
The problem or where I get stuck is here.
That maybe it's possible without a boolean, or maybe changing or adding something that I don't yet know. Sorry I try to find an answer but all I saw it's about going out a while loop whith boolean or so. Not like this.
Scanner kb = new Scanner(System.in);
// c = continue
char c;
// attempt to limit the input to 3 times
int attempt = 3;
// option = op
int op = 0;
do {
do{
System.out.println("Choose continue[0] or go out[1].");
while (!kb.hasNextInt()) {
kb.nextLine();
System.out.println("It's not a number.");
}
op = kb.nextInt();
} while ( op <= -1 || op >= 2 );
switch (op) {
case 0:
System.out.println("Continue!");
break;
case 1: //here I tried; attempt = -1
break; //is where I think it needs to be something
default:
break;
}
System.out.println("Do you wanna try again,"+attempt+" less?[c]+enter\n"
+ "Any other key + enter to exit.");
c = kb.next(".").toUpperCase().charAt(0);
attempt--;
} while ( attempt > 0 && ( c == 'C' ) );
//here also to put !( op == 0 )
kb.close();
I think you can do this pretty easily without a case switch by using a method:
static Scanner kb = new Scanner(System.in);
public static void main(String args[]){
if(getContinueOption(3)){
//do what you want to do
}
}
private static boolean getContinueOption(int attempts) {
System.out.println("Would you like to continue? Y[1] : N[0]");
while(attempts > 0){
int input = kb.nextInt();
if(input == 1){
return true;
}
attempts--;
System.out.println( (attempts == 0)? "Ok :(" : "Are you sure?");
}
return false;
}
You only need to ask for continuation if user chooses 0.
Scanner kb = new Scanner(System.in);
// c = continue
char c = 'a';
// attempt to limit the input to 3 times
int attempt = 3;
// option = op
int op = 0;
do {
do{
System.out.println("Choose continue[0] or go out[1].");
while (!kb.hasNextInt()) {
kb.nextLine();
System.out.println("It's not a number.");
}
op = kb.nextInt();
} while ( op <= -1 || op >= 2 );
switch (op) {
case 0:
System.out.println("Continue!");
System.out.println("Do you wanna try again,"+attempt+" less?[c]+enter\n"
+ "Any other key + enter to exit.");
c = kb.next(".").toUpperCase().charAt(0);
attempt--;
break;
case 1:
attempt = -1;
break;
default:
break;
}
} while ( attempt > 0 && ( c == 'C' ) );
kb.close();
This question is a little hard to understand, but I think what you want is...
Scanner kb = new Scanner(System.in);
// c = continue
char c;
// attempt to limit the input to 3 times
int attempt = 3;
// option = op
int op = 0;
the_loop:
do {
do{
System.out.println("Choose continue[0] or go out[1].");
while (!kb.hasNextInt()) {
kb.nextLine();
System.out.println("It's not a number.");
}
op = kb.nextInt();
} while ( op <= -1 || op >= 2 );
switch (op) {
case 0:
System.out.println("Continue!");
break;
case 1: //here I tried; attempt = -1
break the_loop; //is where I think it needs to be something
default:
break;
}
System.out.println("Do you wanna try again,"+attempt+" less?[c]+enter\n"
+ "Any other key + enter to exit.");
c = kb.next(".").toUpperCase().charAt(0);
attempt--;
} while ( attempt > 0 && ( c == 'C' ) );
//here also to put !( op == 0 )
kb.close();
Note the_loop and break the_loop;
It's actually simpler than that and avoids the use of if statements, although I am not sure why you would do it this way in real life, it's a good exercise to go over concepts.
Let's look at the implementation first:
import java.util.*;
import java.lang.*;
class SillyEnforcer {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
char c = 'C';
int attempt = 3;
int op = 0;
while(attempt > 0 && c == 'C') { // attempt loop
do {
System.out.println("Enter 0 to continue, 1 to exit");
while (!kb.hasNextInt()) {
kb.nextLine();
System.out.println("Not a number, try again.");
}
op = kb.nextInt();
switch(op) {
case 0:
continue;
case 1:
op = -1;
break;
default:
System.out.println("Number can only be 0 or 1.");
op = 0; // positional trickery
continue;
}
} while(op != -1);
System.out.println("Do you wanna try again, ("+ attempt + " attempt" +
((attempt > 1) ? "s" : "") + " left) ? C<ENTER> to continue\n"
+ "Any other key<ENTER> to exit");
c = kb.next(".").toUpperCase().charAt(0);
attempt = attempt - ((c == 'C') ? 1 : 0);
}
}
}
Inner magic
Notice that by using continue for case 0 and reassigning op=-1 for case 1 we can manage the messages correctly and by assigning op=0 in default: we take care of the edge case where a clever person enters -1 as the integer above.
And notice that we make the while statement exit on op == -1. This makes the flag which exits while separate from the input which gives you the magic you need to cover all cases. -1 will never happen by input, (we fix that in default) and 0 is the only thing that sets op to -1. All other cases continue the inner while loop.
'C' for continue magic
We only want to decrease attempt if someone actually wants to continue otherwise we exit anyways, it does not matter here but you can extend this logic to change the question to "do you want to exit [Y/n]" and loop if answer is not a 'Y' or an 'n' while decreasing attempt only on a valid answer of 'Y'

how do i prevent the scanner from accepting strings, negative integers, or numbers less than 2?

How do i prevent negative numbers from being returned by this method?
I have tried setting the while loop to
(n < 0 && n != 0)
to no avail.
Here is my code for the method currently:
public int getNumber() {
int n = 1;
while(n < 2 && n != 0) {
if(n < 0) {
System.out.print("Error, please enter a valid number greater than 0(0 to exit): ");
scan.next();
n = scan.nextInt();
}
try {
System.out.print("Enter the upper bound(0 to exit): ");
n = scan.nextInt();
break;
}
catch(java.util.InputMismatchException e) {
System.out.print("Error, please enter a valid number greater than 0(0 to exit): ");
scan.next();
continue;
}
}
return n;
}
I have also tried to put my if statement inside the try block like this:
public int getNumber() {
int n = 1;
while(n < 2 && n != 0) {
try {
System.out.print("Enter the upper bound(0 to exit): ");
n = scan.nextInt();
if(n < 0) {
System.out.print("Error, please enter a valid number greater than 0(0 to exit): ");
scan.next();
n = scan.nextInt();
}
break;
}
catch(java.util.InputMismatchException e) {
System.out.print("Error, please enter a valid number greater than 0(0 to exit): ");
scan.next();
continue;
}
}
return n;
}
When i put the if statement inside the try block, i started to input negative numbers consecutively to test. It worked for the first time i entered a negative number, then gave me a blank scanner input line, and then finally allowed a negative number to return, which in turn screws the rest of my program up. Please help, im a first semester student in java. Thank you.
You input a negative number, then it goes into your n<0 if and you put in another one and then break out of the loop.
Try changing your if to:
while(n < 0)
Do not use while loop condition for validating input. Your loop condition does not give your program a chance to accept and check the number before making a decision to keep or to reject the entered value. As the result, your program starts prompting end-users with an error message even before they typed anything.
You should not call nextInt without first checking if the Scanner is ready to give you an int by calling hasNextInt.
Finally, you need a rejection loop to throw away non-integer input until hasNextInt succeeds. This is usually done with a nested while loop, which prints an error prompt, and throws away the entered value.
The overall skeleton for reading and validating an int looks like this:
System.err.println("Enter a number between 0 and 5, inclusive");
int res = -1;
while (true) {
while (!scan.hasNextInt()) {
System.err.println("Incorrect input. Please enter a number between 0 and 5, inclusive");
scan.nextLine(); // Discard junk entries
}
res = scan.nextInt();
if (res >= 0 && res <= 5) {
break;
}
System.err.println("Invalid number. Please enter a number between 0 and 5, inclusive");
}
// When you reach this point, res is between 0 and 5, inclusive
couldn't you just check for 'hasNextInt', then test the input.
int n = 0;
System.out.println("Enter a number between 0 and 5);
while (scan.hasNextInt()) {
n = scan.nextInt();
if (n >= 0 && n <= 5) {
break;
}else{
//prompt error message or handle however you wish
}
}
return n;
likewise you could also force with an unsigned integer.
Final code to not return negative integers or strings:
public int getNumber() {
System.out.print("Enter the upper bound(0 to exit): ");
int nums = 1;
while(true) {
while(!scan.hasNextInt()) {
System.out.print("Error. Please enter a valid integer greater than 1(0 to exit): ");
scan.nextLine();
}
nums = scan.nextInt();
if(nums > 2 || nums == 0) {
break;
} else {
System.out.print("Error. Please enter a valid integer greater than 1(0 to exit): ");
scan.nextLine();
}
}
return nums;
}
Thanks a million you guys!

Infinite looping; do not understand how

In the code below, when I input anything other than an integer value the code does not ask for my input again and just loops the string outputs infinitely. A little help...
int choice = 0;
while(choice == 0)
{
try
{
System.out.println("Start by typing the choice number from above and hitting enter: ");
choice = input.nextInt();
}
catch(Exception e)
{
}
if ((choice == 1) || (choice == 2) || (choice == 3))
{
break;
}
else
{
System.out.println("Invalid choice number. Please carefully type correct option.");
choice = 0;
}
}
When you input a non-integer it will not be consumed. You need to scan past it. This can be done by, for example, adding a input.nextLine() statement to your catch block. This will consume the invalid input and allow your program to read new data.
This will solve your problem:
catch(Exception e)
{
input.nextLine(); // Consume the invalid line
System.out.println("Invalid choice number. Please carefully type correct option.");
}
You could also read the line as a string and try to parse it as a number using Scanner.nextLine and Integer.parseInt, but I prefer using nextInt for integers. It makes the purpose of the code more clear (in my opinion).
When nextInt is used and the next input is not an int, it will throw an exception but not consume the data, i.e. the next call will return immediately because the data is still present.
You can fix this by calling the skip method with a pattern like [^0-9]* to skip all invalid input. Then an input like "aaa3" would work. If you want to ignore everything, use .* as pattern.
The trouble is that you are not consuming the remaining data in the stream. I solved it with the following code, although you will want to document you code better before you use it in a program:
int choice = 0;
while(choice == 0)
{
try
{
System.out.print("Start by typing the choice number from above and hitting enter: ");
choice = input.nextInt();
}
catch(Exception e)
{
input.next();
System.out.println("Invalid choice number. Please carefully type correct option.");
}
if ((choice == 1) || (choice == 2) || (choice == 3))
{
break;
}
choice = 0;
}
You can simplify and reduce your code as follows:
int choice;
System.out.println("Start by typing the choice number from above and hitting enter: ");
while(true)
{
try {
choice = input.nextInt();
if ((choice == 1) || (choice == 2) || (choice == 3))
break;
} catch(InputMismatchException e) { // handle only the specific exception
input.nextLine(); // clear the input
}
System.out.println("Invalid choice number. Please carefully type correct option.");
}
Are you using Scanner(system.in); from the import java.util.Scanner; package?
Try adding input.nextLine(); in the catch to clear the value to stop the infinite loop.
public static void main(String[] args) {
int choice = 0;
Scanner input = new Scanner(System.in);
while(choice == 0)
{
try
{
System.out.println("Start by typing the choice number from above and hitting enter: ");
choice = input.nextInt();
}
catch(Exception e)
{
input.nextLine();
System.out.println("Invalid choice number. Please carefully type correct option.");
}
if ((choice == 1) || (choice == 2) || (choice == 3))
{
break;
}
else
{
System.out.println("Invalid choice number. Please carefully type correct option.");
choice = 0;
}
}
}
Looks like in the line choice = input.nextInt();
choice value is always 0. Print choice soon after that.
Also for non integer value add a condition to break from the loop.

Categories

Resources