Java - while loop for scanner validation results in failed input - java

I am trying to add the following scanner validation as follows;
public void promptFilmRating() {
while (!filmScanner.hasNextInt()) {
System.out.println("Please enter a number instead of text.");
filmScanner.next();
}
while (filmScanner.nextInt() > 5 || filmScanner.nextInt() < 1) {
System.out.println("Your number is outside of the rating boundaries, enter a number between 1 and 5.");
filmRatingOutOfFive = filmScanner.nextInt();
}
}
However when using the code that relates to the integer between value validation, repeated inputs are needed in order to record the original input and I am unsure on how to correct this, any advice would be fantastic.

I believe your problem is in while (filmScanner.nextInt() > 5 || filmScanner.nextInt() < 1) {.
Every call to filmScanner.nextInt() asks the stream for a new integer, so by calling .nextInt() twice in the while statement, you are asking for two numbers.
You might want to consider combining your two loops into one.
Example:
int myNum;
do {
myNumb = filmScanner.nextInt();
} while (myNum > 5 || myNum < 1);

Store the value that you are getting in a variable, and use that variable to perform the checks.
Here is an example:
private void promptFilmRating() {
Scanner filmScanner = new Scanner(System.in);
int filmRatingOutOfFive;
do{
System.out.println("Please enter your rating for the film:");
filmRatingOutOfFive = filmScanner.nextInt();
if(filmRatingOutOfFive > 5 || filmRatingOutOfFive < 1)
System.out.println("Your number is outside of the rating boundaries, enter a number between 1 and 5.");
}while(filmRatingOutOfFive > 5 || filmRatingOutOfFive < 1);
System.out.println("You rated this film: "+filmRatingOutOfFive+" out of 5");
}

Related

Non duplicates numbers in user input

I am trying to work out how to create an input validation where it won't let you enter the same number twice as well as being inside a range of numbers and that nothing can be entered unless it's an integer. I am currently creating a lottery program and I am unsure how to do this. Any help would be much appreciated. My number range validation works but the other two validations do not. I attempted the non duplicate number validation and i'm unsure how to do the numbers only validation. Can someone show me how to structure this please.
This method is in my Player class
public void choose() {
int temp = 0;
for (int i = 0; i<6; i++) {
System.out.println("Enter enter a number between 1 & 59");
temp = keyboard.nextInt();
keyboard.nextLine();
while ((temp<1) || (temp>59)) {
System.out.println("You entered an invalid number, please enter a number between 1 and 59");
temp = keyboard.nextInt();
keyboard.nextLine();
}
if (i > 0) {
while(temp == numbers[i-1]) {
System.out.println("Please enter a different number as you have already entered this");
temp = keyboard.nextInt();
keyboard.nextLine();
}
}
numbers[i] = temp;
}
}
Do it as follows:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int[] numbers = new int[6];
static Scanner keyboard = new Scanner(System.in);
public static void main(String args[]) {
// Test
choose();
System.out.println(Arrays.toString(numbers));
}
static void choose() {
int temp;
boolean valid;
for (int i = 0; i < 6; i++) {
// Check if the integer is in the range of 1 to 59
do {
valid = true;
System.out.print("Enter in an integer (from 1 to 59): ");
temp = keyboard.nextInt();
if (temp < 1 || temp > 59) {
System.out.println("Error: Invalid integer.");
valid = false;
}
for (int j = 0; j < i; j++) {
if (numbers[j] == temp) {
System.out.println("Please enter a different number as you have already entered this");
valid = false;
break;
}
}
numbers[i] = temp;
} while (!valid); // Loop back if the integer is not in the range of 1 to 100
}
}
}
A sample run:
Enter in an integer (from 1 to 59): 100
Error: Invalid integer.
Enter in an integer (from 1 to 59): -1
Error: Invalid integer.
Enter in an integer (from 1 to 59): 20
Enter in an integer (from 1 to 59): 0
Error: Invalid integer.
Enter in an integer (from 1 to 59): 4
Enter in an integer (from 1 to 59): 5
Enter in an integer (from 1 to 59): 20
Please enter a different number as you have already entered this
Enter in an integer (from 1 to 59): 25
Enter in an integer (from 1 to 59): 6
Enter in an integer (from 1 to 59): 23
[20, 4, 5, 25, 6, 23]
For testing a value is present in the numbers array use Arrays.asList(numbers).contains(temp)
May better if you use an ArrayList for storing numbers.
I would rewrite the method recursively to avoid multiple loops.
If you are not familiar with recursively methods it is basically a method that calls itself inside the method. By using clever parameters you can use a recursively method as a loop. For example
void loop(int index) {
if(index == 10) {
return; //End loop
}
System.out.println(index);
loop(index++);
}
by calling loop(1) the numbers 1 to 9 will be printed.
In your case the recursively method could look something like
public void choose(int nbrOfchoices, List<Integer> taken) {
if(nbrOfChoices < 0) {
return; //Terminate the recursively loop
}
System.out.println("Enter enter a number between 1 and 59");
try {
int temp = keyboard.nextInt(); //Scanner.nextInt throws InputMismatchException if the next token does not matches the Integer regular expression
} catch(InputMismatchException e) {
System.out.println("You need to enter an integer");
choose(nbrOfChoices, taken);
return;
}
if (value < 1 || value >= 59) { //Number not in interval
System.out.println("The number " + temp + " is not between 1 and 59.");
choose(nbrOfChoices, taken);
return;
}
if (taken.contains(temp)) { //Number already taken
System.out.println("The number " + temp + " has already been entered.");
choose(nbrOfChoices, taken);
return;
}
taken.add(temp);
choose(nbrOfChoices--, taken);
}
Now you start the recursively method by calling choose(yourNumberOfchoices, yourArrayList taken). You can also easily add two additonal parameters if you want to be able to change your number interval.
What you want to do is use recursion so you can ask them to provide input again. You can define choices instead of 6. You can define maxExclusive instead 59 (60 in this case). You can keep track of chosen as a Set of Integer values since Sets can only contain unique non-null values. At the end of each choose call we call choose again with 1 less choice remaining instead of a for loop. At the start of each method call, we check if choices is < 0, if so, we prevent execution.
public void choose(Scanner keyboard, int choices, int maxExclusive, Set<Integer> chosen) {
if (choices <= 0) {
return;
}
System.out.println("Enter enter a number between 1 & " + (maxExclusive - 1));
int value = keyboard.nextInt();
keyboard.nextLine();
if (value < 1 || value >= maxExclusive) {
System.out.println("You entered an invalid number.");
choose(keyboard, choices, maxExclusive, chosen);
return;
}
if (chosen.contains(value)) {
System.out.println("You already entered this number.");
choose(keyboard, choices, maxExclusive, chosen);
return;
}
chosen.add(value);
choose(keyboard, --choices, maxExclusive, chosen);
}
choose(new Scanner(System.in), 6, 60, new HashSet<>());
I hope it will help , upvote if yes
import java.util.ArrayList;
import java.util.Scanner;
public class Test {
private ArrayList<String> choose() {
Scanner scanner = new Scanner(System.in);
ArrayList<String> alreadyEntered = new ArrayList<>(6); // using six because your loop indicated me that you're taking six digits
for(int i = 0 ; i < 6 ; ++i){ // ++i is more efficient than i++
System.out.println("Enter a number between 1 & 59");
String digit;
digit = scanner.nextLine().trim();
if(digit.matches("[1-5][0-9]|[0-9]" && !alreadyEntered.contains(digit))// it checks if it is a number as well as if it is in range as well if it is not already entered, to understand this learn about regular expressions
alreadyEntered.add(digit);
else {
System.out.println("Invalid input, try again");
--i;
}
}
return alreadyEntered // return or do whatever with the numbers as i am using return type in method definition i am returning
}
scanner.close();
}
using arraylist of string just to make things easy otherwise i would have to to some parsing from integer to string and string to integer

Java Monopoly player select validation

I am programming a monopoly type game on java and am having a little trouble setting up the validation for the player select function. The user will have to chose between 2-4 players.
Below is my attempt at doing this utilizing an if else statement and a while loop.
I can't figure out the right way of implementing this and would appreciate any advice.
int numberPlayers = 0;
Scanner scanner = new Scanner(System.in);
System.out.println("Please enter Number of players (2-4)");
if (scanner.nextInt() >= 2 && scanner.nextInt() <= 4) {
numberPlayers = scanner.nextInt();
System.out.println(numberPlayers + " players selected");
} else {
while (scanner.nextInt() < 2 || scanner.nextInt() > 4) {
System.out.println("Not a valid choice. Please enter Number of players (2-4)");
}
}
You can use a do-while loop to ask the user at least once for the player count and keep asking until the input is valid.
public int askForPlayers(Scanner scanner) {
int numberPlayers = 0;
do {
System.out.println("Please enter Number of players (2-4)");
numberPlayers = scanner.nextInt();
} while(numberPlayers < 2 || numberPlayers > 4);
return numberPlayers;
}
When you use a Scanner object, keep in mind that the user might enter something else that is not a number. You have to work with hasNextInt() and next() to deal with such a situation. Also, when you close the Scanner object, you are also closing the InputStream you used, see Close a Scanner linked to System.in.

How to read a String an an integer from one input in the console?

The instructions read:
Write a program that prompts the user to input a student first name followed by a space and an integer test grade, then the user will press enter and you will prompt them again for a name and a test grade; for a total of 10 students and 10 grades. (Ex: Dawn 100 ) ; You must check that the user enters a grade that is >= 0 and <= 100. If not, you must prompt the user with an error message and the user must input the grade again.
I can't figure out how to do this without getting a java.util.InputMismatchException error message.
Scanner input = new Scanner(System.in);
String[] students = new String[10];
int[] grades = new int[10];
for(int i = 0; i < students.length; )
{
System.out.println("Enter a student name and grade(between 0 and 100): ");
if(input.nextInt() > 0 && input.nextInt() <= 100)
{
students[i] = input.next();
grades[i] = input.nextInt();
i++;
}
else
{
System.out.println("*Error* Grade value must be between 0 and 100. Please Try again");
}
}
Let's take a closer look...
if(input.nextInt() > 0 && input.nextInt() <= 100)
You check the input for nextInt, twice, so you're no longer actually comparing the same value, but also, you've asked for a String and an int value, but you've not checked for the String first...
Assume I entered something like 500 -1, then you're if statement would pass successfully, because 500 is > 0 and -1 is <= 100
And if by some miracle, that worked, you're reading another String and another int from the stream...
students[i] = input.next();
grades[i] = input.nextInt();
So, for this to work, the input would have to be something like 1 2 John 50 ... which would just be completely weird and completely void what you're trying to do.
Instead, ask for one piece of information at a time and process it, for example...
Scanner input = new Scanner(System.in);
System.out.print("User name: ");
String name = input.nextLine();
System.out.print("Grade: ");
String gradeValue = input.nextLine();
Scanner parser = new Scanner(gradeValue);
if (parser.hasNextInt()) {
int grade = parser.nextInt();
if (grade >= 0 && grade <= 100) {
// Good grade
} else {
System.out.println("!! " + grade + " is not a valid grade");
}
} else {
System.out.println("!! " + gradeValue + " is not a valid integer value");
}
Don't keep reading from the Scanner when you're not expecting a value, extract the value you need and process it. Here I've used nextLine to get the grade and a second Scanner to parse it, it's safer and avoids the oddities where the new line is left in the buffer. It also gives you better control to process errors ;)
This is the main culprit:
if(input.nextInt() > 0 && input.nextInt() <= 100)
Your if condition contains two (2) calls to input.nextInt(), so at this point — before reading the name — your program will attempt to read two numbers from input and see if the first is greater than 0 and the second less than or equal to 100. And if it succeeded, it would not store the numbers read into any variables.
Instead you need to read the name into students[i] first. Then read the grade into grades[i]. Then check if the grade read is in the interval. I suggest you use a while loop so that as long as the grade is outside the interval, you print the error message and read the grade anew. If the first grade read was OK, you while loop won’t execute at all, so this is fine.
I can't figure out how to do this without getting a
java.util.InputMismatchException error message.
The first mistake you've made is reading user input incorrectly input.nextInt() > 0 && input.nextInt() this is requiring the user to enter an integer value twice whereas what you want is name (string) & grade (int).
the solution below takes that mistake into consideration, however personally I would use a while loop, but since you're using a for loop already I have decided to incorporate with that.
full solution:
Scanner input = new Scanner(System.in);
String[] students = new String[10];
int[] grades = new int[10];
for(int i = 0; i < students.length; i++)
{
System.out.println("Enter a student name and grade(between 0 and 100): ");
String getInput = input.nextLine();
if(Integer.parseInt(getInput.split(" ")[1]) < 0 || Integer.parseInt(getInput.split(" ")[1]) > 100)
{
System.out.println("*Error* Grade value must be between 0 and 100. Please Try again");
i--;
}
else {
students[i] = getInput.split(" ")[0];
grades[i] = Integer.parseInt(getInput.split(" ")[1]);
}
}
note - the solution given only takes into consideration what you've mentioned within your question i.e it is expecting input as such Ousmane 20, Brendon 23 , jack 30 etc, also you can make the program a bit more robust by adding more validations if needed maybe NumberFormatException, Scanner#hasNextInt() and so forth.

Find two smallest value inputs

The instructions are: "Ask the user for the following information, in this order:
A terminating value (real number). The user will enter this value again later, to indicate that he or she is finished providing input.
A sequence of real numbers. Keep asking for numbers until the terminating value is entered.
Compute and output the smallest and second-smallest real number, in that order. It is possible for the smallest and second-smallest numbers to be the same (if the sequence contains duplicate numbers)."
I uploaded my code and the grading software gave me a zero saying the program is not consistent with the assignment, however, when testing my code it runs just as required for the assignment. Any feedback as to why this may happen would be appreciated.
This is my code:
public class TwoSmallest
{
public static void main (String[] args)
{
double terminator;
System.out.print ("Please enter a terminating value: ");
terminator = IO.readDouble();
double lowest1;
double lowest2;
System.out.println("Please enter sequence of numbers:");
lowest1 = IO.readDouble();
while (lowest1 == terminator)
{
IO.reportBadInput();
lowest1 = IO.readDouble();
}
lowest2 = IO.readDouble();
while (lowest2 == terminator)
{
IO.reportBadInput();
lowest2 = IO.readDouble();
}
double input;
do
{
input = IO.readDouble();
if (input < lowest1)
{
if(lowest2 < lowest1)
lowest2 = lowest1;
lowest1 = input;
}
else if (input < lowest2)
lowest2 = input;
}while (input != terminator);
System.out.println("RESULT: " + lowest1);
System.out.println("RESULT: " + lowest2);
}
}
Here are the two scenarios which are not handled by your solution :
For suppose you have given the sequence of numbers 3,7,1 the result of your code is 1 and 7 not 1 and 3.
It is because you are not changing lowest2 value when input < lowest1.
If your input is 3,1,7 where first number is lowest1, second number is lowest2 and then input variable value is 7 then the condition (input < lowest1) is false, so there will be no swapping of lowest1 and lowest2 values and the result will be 3 and 1 instead of 1 and 3.

Right Loop for this exercise in Java

Hi guys i am learning java in order to code in Android, i got some experience in PHP, so i got assigned an exercise but cant find the right loop for it, i tried else/if, while, still cant find it, this is the exercise:
1- prompt the user to enter number of students, it must be a number that can divide by 10 (number / 10) = 0
2- check of user input, if user input not dividable by 10 keep asking the user for input until he enter the right input
How i code it so far, the while loop not working any ideas how to improve it or make it work?
package whiledowhile;
import java.util.Scanner;
public class WhileDoWhile {
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
/* int counter = 0;
int num;
while (counter <= 100) {
System.out.println("Enter number");
num = user_input.nextInt();
counter += num; // counter = counter + num
//counter ++ = counter =counter +1
}
System.out.println("Sum = "+ counter);
*/
int count = 0;
int num;
System.out.println("Please enter a number: ");
num = user_input.nextInt();
String ex;
do {
System.out.print("Wrong Number please enter again: " );
num++;
}
while(num/10 != 0 );
}
}
When using a while loop, you'll want to execute some code while a condition is true. This code needs to go inside the do or while block. For your example, a do-while loop seems more appropriate, since you want the code to execute at least one time. Also, you'll want to use the modulo operator, %, inside of your while condition, not /. See below:
Scanner s = new Scanner(System.in);
int userInput;
do {
// Do something
System.out.print("Enter a number: ");
userInput = s.nextInt();
} while(userInput % 10 != 0);
Two things:
I think you mean to use %, not /
You probably want to have your data entry inside of your while loop
while (num % 10 != 0) {
// request user input, update num
}
// do something with your divisible by 10 variable

Categories