Java: Using scanner to read in boolean values failing. - java

import java.util.Scanner;
public class Cardhelp2{
private static String[] pairArray={"A,A","K,K","Q,Q","J,J","10,10","9,9","8,8","7,7","6,6","5,5","4,4","3,3","2,2"};
public static void generateRandom(int k){
int minimum = 0;
int maximum = 13;
for(int i = 1; i <= k; i++)
{
int randomNum = minimum + (int)(Math.random()* maximum);
System.out.print("Player " + i +" , You have been dealt a pair of: ");
System.out.println(pairArray[randomNum]);
}
} //reads array and randomizes cards
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("How many players would you like to play with? ");
int m = scan.nextInt();
generateRandom(m);
//displays the cards
___________________________________________________
System.out.println("Would you like to play?");
Scanner scanner = new Scanner(System.in);
if(scanner.next().equalsIgnoreCase("y")||scanner.next().equalsIgnoreCase("yes")) {
System.out.println("This will be fun");
} else if(scanner.next().equalsIgnoreCase("n")||scanner.next().equalsIgnoreCase("no")) {
System.out.println("Maybe next time");
} else {
System.out.println("Invalid character");
}
}
}
Im having trouble understanding why the end part is not working, I've been told i need to change scanner.next(); to a variable but im not sure how to do it and get the code working. Is there a simple way of reading in the users answer then displaying a response to the user?
Thanks

Your conditional expression
if(scanner.next().equalsIgnoreCase("y")||scanner.next().equalsIgnoreCase("yes"))
calls scanner.next() twice, which means the second call will read/wait for more input. Instead you need to call it only once, store the result and use that in the comparison:
String tmp = scanner.next();
if(tmp.equalsIgnoreCase("y")||tmp.equalsIgnoreCase("yes"))

Let's assume the user inputs "yes".
At
if(scanner.next().equalsIgnoreCase("y")||scanner.next().equalsIgnoreCase("yes")) {
Scanner.next() produces "yes" in the first test. So the code is effectively
"yes".equalsIgnoreCase("y")
Which is false, so it moves to the next test:
scanner.next().equalsIgnoreCase("yes")
Here's where your issue is.
the "yes" entered has already been consumed by the first test. Now the Scanner has nothing in the buffer.
If you want to test the SAME input again, you must capture it, and use that in your tests.
So
String userReply= Scanner.next();
if(userReply.equalsIgnoreCase("y")||userReply.equalsIgnoreCase("yes")) {...
This is becauswe, with each call to scanner.next(), the Scanner returns the next value in the stream, and then MOVES PAST IT
If the user had entered "yes" and then "no", the tests would be performed like this:
if("yes".equalsIgnoreCase("y")||"no".equalsIgnoreCase("yes")) {...

You need change the way of Scanner's calls.
The user input \n and Scanner seems don't follow with the next token. Then you need read line by line.
:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("How many players would you like to play with? ");
int m = Integer.parseInt(sc.nextLine()); // May thrown NumberFormatException
generateRandom(m);
//displays the cards
System.out.print("Would you like to play? ");
String input = sc.nextLine();
if (input.equalsIgnoreCase("y") || input.equalsIgnoreCase("yes")) {
System.out.println("This will be fun");
} else if (input.equalsIgnoreCase("n") || input.equalsIgnoreCase("no")) {
System.out.println("Maybe next time");
} else {
System.out.println("Invalid character");
}
}

Related

Trying to stop a Do-While Loop for an application

I'm creating an application for a homework, the problem is that I am trying to create a do-while loop to exit the application (Using the question "Do you want to exit (Y/N)"). To work with the do-while loop, I created a method to store the app and then called the method in the do-while loop, so that when I try to stop the loop, the method loops once more. I want when I type "Y" to the console the whole program stops and doesn't loop one more time.
I created a simple example to explain my problem.
Here's the method:
public static void App(){
Scanner sc = new Scanner(System.in);
System.out.print("Write a number: ");
int num1 = sc.nextInt();
System.out.print("Write another number: ");
int num2 = sc.nextInt();
System.out.println("\nResult: "+(num1+num2));
}
And here I'm trying to create the loop in the main method:
public static void main(String[] args) {
Scanner sc2 = new Scanner(System.in);
App();
String answer;
do {
System.out.println("Do you want to exit (Y/N)?");
answer = sc2.next();
App();
} while (answer.equalsIgnoreCase("N")) ;
}
the problem is that I am trying to create a do-while loop to exit the application
You already have that in your program.
so that when I try to stop the loop, the method loops once more...
That doesn't fit the goal of your program.
I want when I type "Y" to the console the whole program stops and doesn't loop one more time
A lot of context that doesn't fit right in.
But anyway, you just have to reorganize your program.
In other words, just move your App() method.
public static void main(String[] args) {
Scanner sc2 = new Scanner(System.in);
String answer;
do {
App();
System.out.println("Do you want to exit (Y/N)?");
answer = sc2.next();
} while (answer.equalsIgnoreCase("N")) ;
}
Also, I spotted a lot of bad practices, so I kind of fixed them:
public static void main(String[] args) throws Exception {
try(Scanner sc2 = new Scanner(System.in)){
String answer;
do {
App();
System.out.print("Do you want to exit (Y/N)?");
answer = sc2.nextLine();
} while (answer.equalsIgnoreCase("N")) ;
}
}
Lastly, maybe (just maybe) try to solve your problem first before seeking help for your homework.
The reason why your program is running again after you type n is because the App() method is ran after the question is asked within the do part of the loop.
This code below is the simplest fix I could think of.
public static void main(String[] args) {
Scanner sc2 = new Scanner(System.in);
// I removed the line 'App();' as the App method will always run at least one time. Therefore putting that method within the 'do' part of the loop allows us to ask the user if they wish to exit or not after they have received their answer.
String answer;
do {
App();
System.out.print("Do you want to exit (Y/N)?"); //I changed the 'println' to 'print' here
answer = sc2.next();
} while (answer.equalsIgnoreCase("N")) ;
}
As a side note, methods in java should be lower-case when following typical Java naming conventions. While this will not affect how your code runs, I would suggest renaming the method from App() to app().
Everything looks good in your code, Just change the execution logic as shown in code blocks.
public static void main(String[] args) {
Scanner sc2 = new Scanner(System.in);
App(); //remove this line from here
String answer;
do {
App(); //call App function here so that it got executed at least one time
System.out.println("Do you want to exit (Y/N)?");
answer = sc2.next();
App(); //remove this as well
} while (answer.equalsIgnoreCase("N")) ;
}
Here is yet another approach except it uses a while loops instead of do/while loops. Two different approaches are provided and both provide User entry validation:
Approach #1:
public static void appMethod() {
Scanner sc = new Scanner(System.in);
int num1 = Integer.MIN_VALUE; // Initialize with some obscure value.
int num2 = Integer.MIN_VALUE; // Initialize with some obscure value.
while (num1 == Integer.MIN_VALUE) {
System.out.print("Write a number: ");
try {
num1 = sc.nextInt();
} catch ( java.util.InputMismatchException ex) {
System.out.println("Invalid Entry! Try again..."
+ System.lineSeparator());
sc.nextLine(); // consume the ENTER key hit otherwise this error will keep cycling.
num1 = Integer.MIN_VALUE;
}
}
while (num2 == Integer.MIN_VALUE) {
System.out.print("Now, write yet another number: ");
try {
num2 = sc.nextInt();
} catch ( java.util.InputMismatchException ex) {
System.out.println("Invalid Entry! Try again..."
+ System.lineSeparator());
sc.nextLine(); // consume the ENTER key hit otherwise this error will keep cycling.
num2 = Integer.MIN_VALUE;
}
}
System.out.println("\nResult: " + num1 +" + " + num2 + " = " + (num1 + num2));
}
Approach #2:
This next approach makes use of the Scanner#nextLine() method. The thing to remember about nextLine() is that, if you use it in your console application then basically recommend you use it for everything (all prompts). A 'quit' mechanism is also available in this version. Read the comments in code:
public static void appMethod() {
Scanner sc = new Scanner(System.in);
// Retrieve first number...
String num1 = "";
while (num1.isEmpty()) {
System.out.print("Write a number (q to quit): ");
// Making use of the Scanner#nextLine() method
num1 = sc.nextLine();
// Has 'q' been supplied to Quit?
if (num1.equalsIgnoreCase("q")) {
return;
}
/* Validate the fact that a signed or unsigned Integer or
Floating Point value has been entered. If not show Msg. */
if (!num1.matches("-?\\d+(\\.\\d+)?")) {
System.out.println("Invalid Entry! (" + num1 + ") Try again..."
+ System.lineSeparator());
num1 = ""; // empty num1 so as to re-loop.
}
}
// Retrieve second number...
String num2 = "";
while (num2.isEmpty()) {
System.out.print("Now, write yet another number (q to quit): ");
num2 = sc.nextLine();
if (num2.equalsIgnoreCase("q")) {
return;
}
if (!num2.matches("-?\\d+(\\.\\d+)?")) {
System.out.println("Invalid Entry! (" + num2 + ") Try again..."
+ System.lineSeparator());
num2 = "";
}
}
// Convert the numerical strings to double data type values.
double number1 = Double.parseDouble(num1);
double number2 = Double.parseDouble(num2);
// Display the result.
System.out.println("\nResult: " + num1 +" + " + num2 + " = " + (number1 + number2));
}

How to only allow user to use certain values and have to make them use a $ in their input for my program

//Payment Process
System.out.println("Order payment");
System.out.println("-------------");
System.out.println("");
System.out.printf("$%.2f remains to be paid. Enter coin or note: ", totalPrice);
double payment;
payment = scan.nextInt();
while (payment <= totalPrice) {
System.out.printf("$%.2f remains to be paid. Enter coin or note:", totalPrice - payment);
payment += scan.nextInt();
So I'm creating a project for Uni where I ask a user to buy coffee from my program. This is a snippet of the code under the payment process section. The two main questions I have are:
1. How do I make it so that the program only works when the input that is put in starts with a $ (eg. 10 would be invalid but $10.00 is valid)
2. How do I make it so that the user can only input $100.00, $50.00, $20.00, $10.00, $5.00, $2.00, $1.00, $0.50, $0.20, $0.10 and $0.05.
I wrote a small program, first is a String, so it can check whether the text is start with $. Since your program is using number, so the String will be converted to double by remove the $ after this.
public static void main(String[] args) {
// TODO code application logic here
Scanner input = new Scanner(System.in);
final String payment = input.next();
if(payment.startsWith("$") && payment.matches(".*\\.\\d\\d"))
{
double paymentConverted = Double.parseDouble(payment.substring(1));
// write ur others logic here
}
else
{
System.out.println("Invalid text !");
}
}
startWith() used to check the first value, matches(".*\\.\\d\\d") check if string ends with two digits after a dot.
Between, you have some error on your code
double payment;
payment = scan.nextInt();
should be nextDouble() if not mistaken.
answer for question 1:
this checks if your input starts with a Dollar-sign($), you could move the code to a function and check it that way
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
boolean isValid = false;
String input;
do {
System.out.printf("input: ");
input = sc.next();
//check if the input is valid
if((input != null) && (input.length() > 0)) {
if('$' == input.charAt(0)) {
isValid = true;
break;
}
}
System.err.printf("Your input was invalid! input:%s%n", input);
} while(!isValid);
sc.close();
System.out.printf("Your input was correct! input:%s%n", input);
}
rather crude but simple answer for question 1 & 2:
make a Set which contains all valid inputs and check if the input is contained in that very Set.
public static void main(String[] args) {
Set<String> validInputs = new HashSet<>();
validInputs.addAll(Arrays.asList("$100.00", "$50.00", "$20.00", "$10.00", "$5.00", "$2.00", "$1.00", "$0.50", "$0.20", "$0.10", "$0.05"));
Scanner sc = new Scanner(System.in);
boolean isValid = false;
String input;
do {
System.out.printf("input: ");
input = sc.next();
// check if the input is valid
if(validInputs.contains(input)) {
isValid = true;
break;
}
System.err.printf("Your input was invalid! input:%s%n", input);
} while(!isValid);
sc.close();
System.out.printf("Your input was correct! input:%s%n", input);
}
Use nextLine() instead of nextInt() to read input, because the addition of $ makes the input a String.
When you have a short list of pre-set values that are acceptable input, the simplest way to validate input is to read the line from the user and simply compare this to a list of acceptable values that you already know.
// Create a list of allowed values
List<String> allowedValues = new ArrayList<>(Arrays.asList("$100.00", "$50.00", "$20.00"));
// read user input
String input = scan.nextLine();
// use the built-in contains() function on the List object
if (!allowedValues.contains(input)) {
System.out.println("Your input is not valid.");
}
System.out.println("Your input is valid.");

How would i do input validation?

Tells the user if the number entered is even or even. I need help with the input validation. The validation i need do is that the user cannot entered anything but a number. Trying to do the validation without the try and catch method.
import java.util.Scanner;
public class oddoreven {
public static void main (String [] args) {
Scanner input = new Scanner (System.in);
//declaractions
int num;
//while loop
do{
System.out.println("PLease enter a number to see whether it is even or odd. To end tyype in -99.");
num = input.nextInt();
// input valid
}while(num != -99); // loop ends
// begins the method
public static void is_odd_or_even_number(int number){
int rem = number%2;
\
You can call Scanner.hasNextInt() to determine if the next input is an int (and consume anything else). Also, you might make an infinite loop and break when the input is -99 (or 99, your code tests for 99 but your prompt says -99). Finally, you should call your method. Something like,
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int num;
do {
System.out.println("Please enter a number to see whether it is "
+ "even or odd. To end type in -99.");
if (input.hasNextInt()) {
num = input.nextInt();
if (num != -99) { // <-- directions say -99.
is_odd_or_even_number(num);
} else {
break;
}
} else {
System.out.printf("%s is not a valid int.%n", input.nextLine());
}
} while (true);
}
You can use Scanner.nextLine() to get a string input. Then loop through the characters to make sure they are all digits. (assuming non-negative integers only)
string rawInput = input.nextLine();
boolean validInput = true;
for (char c : rawInput) {
if (!Character.isDigit(c)) {
validInput = false;
break;
}
}
if (validInput) {
int num == Integer.parseInt(rawInput);
// proceed as normal
}
else {
// invalid input, print out error message
}
You can use regex to check whether all the characters of string entered by user are digits or not,
num.matches("[0-9]+") // return true if all characters are digits
or
num.matches("^[0-9]*$") // return true if all characters are digits
but before that change your num = input.nextint() to num = nextLine() and make num as String. if you dont do this there is no need of validating user input as you are requiring.

Scanner loop doesn't cycle when hitting enter twice

boolean loop = false;
double numberOfStudents;
System.out.print("Enter a number: ");
if ((scnr.nextLine().trim().isEmpty()) ) {
loop = true;
}
while (loop) {
System.out.println("Enter a number");
if (scnr.hasNextDouble() ){
System.out.println("Loop has stopped");
numberOfStudents = scnr.nextDouble();
loop = false;
}
}
System.out.println("You're outside the loop!");
I'm trying to get the program to say "Enter a number" until the user has entered an actual number (no white spaces or letters or signs). When the user has entered a number, it sets numberOfStudents equal to that number and breaks out of the loop.
But if you hit enter twice, it doesn't iterate. It only displays "Enter a number" once.
What is wrong with the loop logic? Why isn't it looping until valid input is taken?
For the actual answer to your question of "Why doesn't 'Enter a number' display more than once?" see Tom's comment (update: Tom's answer).
I've rewritten your loop in a way which preserves your code, but also makes it a little easier to handle format exceptions (though at the risk of silently swallowing an exception -- should be acceptable for this use case).
Can be up to you to use this design, here is an SO post on why empty catch blocks can be a bad practice.
public static void main(String args[])
{
boolean loop = true;
double numberOfStudents;
Scanner scnr = new Scanner(System.in);
while(loop){
System.out.print("Enter a number: ");
String input = scnr.nextLine();
try{
numberOfStudents = Double.parseDouble(input);
loop = false;
}catch(NumberFormatException e){
}
}
System.out.println("You're outside the loop!");
}
Output:
Enter a number:
Enter a number:
Enter a number:
Enter a number: 50
You're outside the loop!
First of all: Since you're reading from System.in a call to the input stream will block until the user entered a valid token.
So let's check first scan using your scnr variable:
scnr.nextLine()
nextLine() reads everything til the next line delimiter. So if you just press return, then it will successfully read it and will perform the next stuff.
The next call is:
scnr.hasNextDouble()
This call expects a "real" token and ignores white spaces, except as a delimiter between tokens. So if you just press return again it doesn't actually read that input. So it still waits for more (for the first token). That is why it stucks in your loop and you won't get another "Enter a number" output.
You can fix that by either enter a real token, like a number, or by changing the loop like trobbins said.
I hope you now understand your program flow a bit more :).
While trobbins code basically solves your problem, it's bad practice to use exceptions for flow control.
I used a small regexp to check if the value is a number. But this example is not complete, it will still crash it the user enters for example two decimal points. So you would need to create a proper number check or just use integers where the check is much easier.
Someone in the comments pointed out that people may want to enter scientific notation like 5e10, so this would also be another case to check for. If this is just some code you need as a proof of concept or something quick and dirty, you can go with the exception handling method but in production code you should avoid using exceptions this way.
double numberOfStudents;
Scanner scnr = new Scanner(System.in);
while(true) {
System.out.print("Enter a number: ");
String input = scnr.nextLine().trim();
if(input.matches("^[0-9\\.]{1,}$")) {
System.out.println("Loop has stopped");
numberOfStudents = Double.parseDouble(input);
break;
}
}
System.out.println("You're outside the loop!");
The following code should help you:
double numberOfStudents = 0;
Scanner scnr = new Scanner(System.in);
boolean readValue = false; //Check if the valid input is received
boolean shouldAskForNumber = true; //Need to ask for number again? Case for Enter
do {
if (shouldAskForNumber) {
System.out.print("Enter a number:");
shouldAskForNumber = false;
}
if (scnr.hasNextDouble()) {
numberOfStudents = scnr.nextDouble();
readValue = true;
} else {
String token = scnr.next();
if (!"".equals(token.trim())) { //Check for Enter or space
shouldAskForNumber = true;
}
}
} while (!readValue);
System.out.printf("Value read is %.0f\n", numberOfStudents);
System.out.println("You're outside the loop!");
Update
Understood the following statement in question different way:
But if you hit enter twice, it doesn't loop back. It only displays
"Enter a number" once.
The code is set to print "Enter a number" only once if the user hits RETURN/ENTER or enters space character. You may remove the special check and use the code if needed.
import java.util.Scanner;
public class Testing {
public static boolean checkInt(String s)
{
try
{
Integer.parseInt(s);
return true;
} catch (NumberFormatException ex)
{
return false;
}
}
public static void main(String[] args) {
boolean loop = false;
double numberOfStudents;
Scanner scnr = new Scanner(System.in);
String input = "";
while (!(checkInt(input))) {
System.out.println("Enter a number");
input = scnr.nextLine();
}
numberOfStudents = Integer.parseInt(input);
System.out.println("Number of students: " + numberOfStudents );
}
}
//this code is working fine, if you want you check it out.
//In your code your taking another input if the first is an int/double; if the first input is not a number then you have mentioned to take input again..
Use a debugger to see what the code is actually doing. Here's a guide on debugging in Eclipse. After you have finished debugging your code, you will probably know what the problem is.
Below code will help you
boolean loop = true;
double numberOfStudents;
Scanner scnr = new Scanner(System.in);
System.out.print("Enter a number: ");
String input = scnr.nextLine();
while(!scnr.hasNextDouble()){
System.out.print("Enter a number: ");
try{
numberOfStudents = Double.parseDouble(input);
break;
}catch(NumberFormatException e){
}
input = scnr.nextLine();
}
System.out.println("You're outside the loop!");
The following code is working,
boolean loop = true;
double numberOfStudents;
Scanner scnr=new Scanner(System.in);
while(loop) {
System.out.println("Enter a number");
if ((scnr.nextLine().trim().isEmpty()) ) {
loop = true;
}
if (scnr.hasNextDouble() ){
System.out.println("Loop has stopped");
numberOfStudents = scnr.nextDouble();
loop = false;
}
}
System.out.println("You're outside the loop!");
The output is,
run:
Enter a number
hj
po
Enter a number
lhf
Enter a number
o
Enter a number
p
Enter a number
a
Enter a number
34
Loop has stopped
You're outside the loop!
You have to scan the next line if you want to get more values form the scanner again. The code should be like:
while (loop) {
System.out.println("Enter a number");
if(!(scnr.nextLine().trim().isEmpty())){
if (scnr.hasNextDouble() ){
System.out.println("Loop has stopped");
numberOfStudents = scnr.nextDouble();
loop = false;
}
}
}

Using nextLine() and nextInt() together in my context always gets an error

I'm writing some Java code that'll make a guessing game, where a random number is generated based on your maximum value and you have to guess the correct number. You can also set the amount of attempts you can get. This is where the problem occurs.You see, you can set a number of attempts in number form or write out "unlimited". I have an example of the code that does this here with comments to help you out:
import java.util.Scanner;
public class Game{
public static int processMaxAttempts;
public static Scanner maxAttempts;
public static String processMaxAttempts2;
public static void main(String args[]){
//Prints out text
System.out.println("Fill in your maximum attempts OR write \"unlimited\".");
//Creates a scanner
maxAttempts = new Scanner(System.in);
//Looks at the scanner "maxAttempts" and reads its integer value
processMaxAttempts = maxAttempts.nextInt();
//Looks at the scanner "maxAttempts" and reads its string value
processMaxAttempts2 = maxAttempts.nextLine();
//Prints out "unlimited" if "maxAttempts" has a string value and "set" if it has an integer value
if(processMaxAttempts2.equals("unlimited")){
System.out.println("unlimited");
}else{
System.out.println("set");
}//Close else
}//Close main method
}//Close class
What happens is a get an error that says this:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:857)
at java.util.Scanner.next(Scanner.java:1478)
at java.util.Scanner.nextInt(Scanner.java:2108)
at java.util.Scanner.nextInt(Scanner.java:2067)
at com.pixelparkour.windows.MainGameWindow.main(MainGameWindow.java:34)
That error targets this line of code:
processMaxAttempts = maxAttempts.nextInt();
So... yeah. I have no idea. I'm very new to Java (I've been learning it for only 3 days) and I'm a bit helpless. I'd love to know what my problem is so I can apply to it the future and program some cool games!
You need to put a check on content type before reading the content.
What you need is :
if(maxAttempts.hasNextInt()){ // this will check if there is an integer to read from scanner
processMaxAttempts = maxAttempts.nextInt();
} else {
processMaxAttempts2 = maxAttempts.nextLine();
}
if(processMaxAttempts2!=null && processMaxAttempts2.equals("unlimited")){
System.out.println("unlimited");
}else{
System.out.println("set");
}
I think this is what you are looking for
public class Test
{
private int guessableNumber;
private Integer maxAttempts;
public Test()
{
maxAttempts = 0;
}
public void doYourStuff(){
Scanner scan = new Scanner(System.in);
Random random = new Random();
System.out.println("Please enter your amount of guesses or type unlimited for unlimited guesses");
String s = scan.next();
if(s.toUpperCase().equals("UNLIMITED")){
guessableNumber = random.nextInt(100);
}
else {
try{
maxAttempts = Integer.parseInt(s);
guessableNumber = random.nextInt(100) + Integer.parseInt(s);
}catch(Exception e){
System.out.println("You did not enter a valid number for max attempts");
}
}
int counter = 0;
System.out.println("Type in a guess");
while(scan.nextInt() != guessableNumber && counter <=maxAttempts){
System.out.println("You did not guess correctly try again");
++counter;
}
if(counter > maxAttempts){
System.out.println("You have exceeded your max attempts");
}
else {
System.out.println("Correct you guessed the correct number: "+ guessableNumber);
}
}
public static void main(String[] args)
{
Test test = new Test();
test.doYourStuff();
}
}
One little trick that always works for me is just going ahead and making a second scanner, i.e. num and text, that way you can always have one looking for int values and the other dealing with the Strings.

Categories

Resources