Trying to create a simple program that has three options for text input. If the user types one of the three, the program moves on. If the user types something else, the program loops back and asks for the input again until a proper response is given.
Using a drop down list or other method will not work, as this is for an assignment.
System.out.print("Enter one of the following: cheese, water, or burger: ");
userMedium = user_input.nextLine( ); // store user input as a string
mediumConvert = userMedium.toLowerCase();
boolean verifyName;
if (mediumConvert.equals("cheese") || mediumConvert.equals("water") || mediumConvert.equals("burger")){
verifyName = false;
} else {
verifyName = true;
}
while (verifyName = true){
System.out.println("Please input a valid medium (cheese, water, or burger): ");
userMedium = user_input.nextLine( );
mediumConvert = userMedium.toLowerCase();
}
This is what I have set up so far, but this just keeps repeating the loop OVER AND OVER. After this section I want to execute a switch to work off each of the three correct responses.
I've spent the last hour on google and YouTube, but everything I found is using integers. It seems pretty easy to validate user input when it is just a number and an operand. But how do I use three possible strings?!
while (verifyName = true)
↑
You're assigning and not comparing. The expression of the assignment returns the assigned value, so your loop is equivalent to:
while (true)
You should change it to:
while (verifyName)
Basically, you should write while (verifyName == true), but it's redundant since it's like asking "Is it true that verifyName has the value true?". Also it prevents potential bugs, like just inserting one = instead of two..
Noticed two things:
1.) By doing
while(verify = true)
you are actually assigning the value true to verifyName. You need to use
while(verifyName)
2.) Where do you reassign the value of verifyName?
You should be validating and reassigning inside the while block.
Also you should consider cleaner alternative solution, but that can wait for another day.
You will never break out of the whileloop because the variable verifyName is never updated inside the loop. This means that you'll either never execute the loop because the user inserted the input you wanted or you'll end up with an infinite loop.
You need to do your input verification inside the loop as well and be careful with the boolean validation as well.
Something like:
while (verifyName) {
System.out.println("Please input a valid medium (air, water, or steel): ");
userMedium = user_input.nextLine( );
mediumConvert = userMedium.toLowerCase();
if (mediumConvert.equals("cheese") || mediumConvert.equals("water") || mediumConvert.equals("burger")){
verifyName = false;
} else {
verifyName = true;
}
}
Related
Java newbie here.
I made a function to simply return an int given by user through Scanner.
The goal is to avoid an error if the user does not type an integer, notify them and let them retry.
It works fine if the value is an integer on the first try, but if I type a char (get an error, function "restart") then the function will return the "default" zero.
Tried different things but I definitly don't get the logic here.
Here is the code :
//Initialize the Scanner earlier
public static Scanner keyBoardRead = new Scanner(System.in);
public static int intEntry()
{
int entry;
keyBoardRead = new Scanner(System.in);
if (keyBoardRead.hasNextInt() == true)
{
entry = keyBoardRead.nextInt();
System.out.println("entry variable = "+entry);
// Here the correct entry prints but doesn't seem to return
return entry;
}
else
{
System.out.println("Invalid entry.\n");
intEntry();
}
return 0;
}
Sample output :
z
Invalid entry.
2
entry variable = 2
// Function exits and output = 0 (?!)
Thanks for your help and please criticize my code :)
I reworked your code a bit as there were a few flaws with it:
public static Scanner keyBoardRead = new Scanner(System.in);
public static int intEntry()
{
int entry;
if (keyBoardRead.hasNextInt())
{
entry = keyBoardRead.nextInt();
System.out.println("entry variable = "+entry);
// Here the correct entry prints but doesn't seem to return
return entry;
}
keyBoardRead.next();
System.out.println("Invalid entry.\n");
return intEntry();
}
Here are the changes explained below:
You do not need to redeclare new Scanner(System.in) with every call
to the method, you state you initially declare it as a class field,
so it should be accessible from inside the method each time.
Your else statement in general is completely unnecessary because you have a return in your if. If your if is executed, it will never enter the code afterward anyway.
You need to return the value from intEntry() with return intEntry() as currently you are just discarding the return value and simply returning 0 unconditionally if else is executed even a single time.
You need to use keyBoardRead.next() if an invalid entry is entered in order to move to the next value and discard the previously entered result. You can also use keyBoardRead.nextLine() instead if you wish to discard the entire line instead.
Using == true on a boolean value is redundant as you can simply check the boolean directly, so if (keyBoardRead.hasNextInt()) instead of if (keyBoardRead.hasNextInt() == true). Credit to #Joop Eggen for catching it.
Example Run:
hi
Invalid entry.
wrong
Invalid entry.
entries
Invalid entry.
55
entry variable = 55
Note: You have a lot of blank space in the output because you are use println and also using \n in the print so it will move to the next line twice.
Also you could easily create a variant to this solution that utilizes a while loop instead of recursion, which is probably a better way to do it so you cannot possibly run into a stack overflow (and is typically easier to read), but I kept the recursion in to keep it similar to your solution.
My code is supposed to keep looping until a valid input is given, ie: if a letter is given it will loop, but if a valid number is given, the code should store it into cSec. Is there anyway to do this?
byte cSec;
boolean contCSec = true;
while(contCSec == true) {
System.out.println("Enter course section: ");
cSec = sc.nextByte();
if(cSec>0)
contCCode = false;
}
cSec can't be used outside the loop.
A rather less verbose form of what you wrote might be:
byte cSec;
do {
System.out.println("Enter course section: ");
cSec = sc.nextByte();
} while (cSec <= 0);
where 'cSec <= 0' denotes an invalid value, per your original, though I imagine there's more to validation than that.
This does not match your title (initialize within loop) since to me that's exactly what you don't want to do.
I think this is clearer than your original since it involved no flag values, and the do...while loop shows up the 'ask then decide to loop' nature a little better.
Adding more validation:
byte cSec;
do {
System.out.println("Enter course section: ");
try {
cSec = sc.nextByte();
}
catch (InputMismatchException ex) {
System.out.println("A number is required");
cSec = -1;
}
} while (cSec <= 0);
In addition to another-dave's wonderful answer, you can suppress the compiler warning by initializing cSec outside of the loop.
byte cSec = 0;
boolean contCSec = true;
while(contCSec == true) {
System.out.println("Enter course section: ");
cSec = sc.nextByte();
if(cSec>0)
contCSec = false;
}
The reason that you get the warning without the first declaration is because, as strange as it sounds, the compiler does not analyze the contents of your boolean in while(contCSec == true). It sees that there is a while loop, and it sees that there will be a boolean resulting from (contCSec == true), but as far as the compiler is concerned, any boolean going into your while condition could be true, or could be false. This means that you could enter the while loop, or you could... not.
As far as the compiler is concerned, anything inside the while loop could happen, or could not happen, and there is no way to know without actually running the code. (If you want to know why this is actually a strict limitation for computers, check out the halting problem.) That means that the compiler has no idea whether cSec = sc.nextByte(); will ever happen or not. Hence, the warning.
This method is supposed to return the integer that the user enters as long as it is only an integer (not a String, float, etc.) and as long as that integer is one of the options in the given list of options. I want to use this method throughout my program whenever I give the user a list of options they need to choose from. These lists will have varying sizes thus I pass as an argument the maximum value (maxValue) that the user could possibly choose thus giving the method the size of the list.
//This method handles the players input and checks if the number entered is one of the options listed or not
public static int response(int maxValue){ //the parameter is the number of options in the particular list
response = new Scanner(System.in);
Boolean check = true;
while(check){
try{
int yesOrNo = response.nextInt();
if(yesOrNo > maxValue || yesOrNo <= 0){ //checks if the int entered does not exceed the list size or go below zero
System.out.println("I'm sorry, that number was not one of the options. Please reselect your choice.");
}else{
check = false;
}
}catch(Exception e){ //catches an exception when the user enters a string or anything but an int
System.out.println("Please only use digits to make a selection.");
response(maxValue);
}
}
return yesOrNo; //returns the user's response. Well, it is supposed to.
}
I am a beginner with regards to programming. I am learning Java through online tutorials and trial and error on dumb, little programs I make. I am working on a fun little text-adventure and am still in the beginning stages.
The trouble I'm having is because this method will only return 0. Isn't yesOrNo being assigned the integer that the user inputs through the scanner response? Why is it only returning 0?
Thank you for your responses. I understand now that I needed to declare my int yesOrNo outside of the try because it was out of scope, as you all put it, being declared within.
BUT a few mentioned 'there is a completely unnecessary function call in the catch block'. The only problem is if I remove it there is an infinite loop created with the System.out.println("Please only use digits to make your selection.") when the user inputs Strings or other non-int values.
Here is my updated code:
//This method handles the players input and checks if the number entered is one of the options listed or not
public static int response(int maxValue){ //the parameter is the number of options in the particular list
response = new Scanner(System.in);
Boolean check = true;
int yesOrNo = 0;
while(check){
try{
yesOrNo = response.nextInt();
if(yesOrNo > maxValue || yesOrNo <= 0){ //checks if the int entered does not exceed the list size or go below zero
System.out.println("I'm sorry, that number was not one of the options. Please reselect your choice.");
}else{
check = false;
}
}catch(Exception e){ //catches an exception when the user enters a string or anything but an int
System.out.println("Please only use digits to make a selection.");
response(maxValue);
}
}
return yesOrNo; //returns the user's response. Well, it is supposed to.
}
After reading other post before just asking another question I found many others facing the same issue. It was correct what some were saying that the infinite loop was created because when the Scanner encounters an error it doesn't remove the token of that error thus causing the while loop to read the same error over again infinitely. Here is what i read exactly:
"As per the javadoc for Scanner:
'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.'
That means that if the next token is not an int, it throws the InputMismatchException, but the token stays there. So on the next iteration of the loop, getAnswer.nextInt() reads the same token again and throws the exception again. What you need is to use it up. Add a getAnswer.next() inside your catch to consume the token, which is invalid and needs to be discarded."
So now that infinite loop problem is fixed :) Onto finding what else I need to learn. Thank you.
yesOrNo goes out of scope because you declared it within the try block. Move the declaration outside to where it is in scope when you return it.
Boolean check = true;
int yesOrNo;
yesOrNo you're returning is not same as
int yesOrNo = response.nextInt();
in your loop. The yesOrNo from the loop disappears (goes out of scope) at the closing } of try.
There has to be another int yesOrNo somewhere. Look for it.
The only this can compile is if yesOrNo is declared as a class or instance variable, unseen in this code snippet.
The declaration of yesOrNo that we do see is declared inside a try block, shadowing the yesOrNo being returned. But there's no reason for it to be a class or instance variable.
Remove it from the class declaration, and declare it locally, before the try block, so it's in scope when it's returned.
int yesOrNo = 0;
try{
yesOrNo = response.nextInt();
I see "int yesOrNo" inside while loop. The value read inside while loop scope is limited to that. Declare that variable outside and try.
I am attempting to validate user input. I have tried some if statements and attempted Boolean. I cant get anything to give the output or rather the validation I am wanting
Users are asked to choose between "red" or "blue" I want them to be required to type either "red" or "blue". I know this could be solved easier through buttons but I am trying to use string input. the code below give an example of where i am.
custColorMsg = "Which color do you want your shirt to be red or blue?";
customerColor = getstringInput(custColorMsg);
String color = null
if( customerColor.equalsIgnoreCase("yes")) {
color = true}
if( customerColor.equalsIgnoreCase("no")) {
color = true}
else if(!customerColor.equalsIgnoreCase("yes" || "no") {
color = false}
I know this last portion is wrong I am just unsure how to go about fixing it. Customers will have three chances to input a valid response then the program will terminate, this portion i can handle. If i can just figure out how to accept "yes" or "no" and refuse anything else.
In terms of the design of this program, I would recommend adding a for loop, that goes from 0 to 2 (this will iterate 3 times). Within the loop, the program can determine what the user's input is. I would also recommend looking at my syntax for the for loop below, I use ifs, else ifs and elses to evaluate the data set more efficiently.
The implementation of the program could be:
for(int i = 0; i < 3; i++)
{
customerColor = getstringInput(custColorMsg);
String color = null
if( customerColor.equalsIgnoreCase("yes")) {
color = true;
break;
}
else if( customerColor.equalsIgnoreCase("no")) {
color = true;
break;
}
else{
color = false;
}
custColorMsg = "Invalid Input, Please Input Again";
}
This will give the user 3 times to input the data, and if they input it correctly, it will stop asking, however, if they do not, it will ask again until they run out of attempts.
There's a few things wrong with your approach.
The semantics of your variable names are a bit off. Which makes the code difficult to read. For example, the variable color which you have defined here as a String, but consistently use as a Boolean is a bit confusing. I'm guessing you mean to define it as a Boolean type and intend to use it as the breaking condition from your loop - it would be more meaningful to name the it as isValidColor or something along those lines.
The following line doesn't do what you think it does:
customerColor.equalsIgnoreCase("yes" || "no")
The method equalsIgnoreCase() takes in a String and not a Boolean like this line of your code will have for an argument. Since the || will resolve to a Boolean value of true or false. Furthermore, those are bad operand types for that operator and the code won't compile.
For your control structure you can use a while loop which will exit when you have reached the max amount of tries or entered a valid response.
Here's a working Console version of what you are trying to accomplish:
String custColorMsg = "Which color do you want your shirt to be red or blue?";
String customerColor;
Boolean validInput = false;
Scanner in = new Scanner(System.in);
int tries = 0;
while (tries < 3 && !validInput)
{
System.out.println(custColorMsg);
customerColor = in.nextLine();
if( customerColor.equalsIgnoreCase("red")) {
validInput = true;
}
else if( customerColor.equalsIgnoreCase("blue")) {
validInput = true;
}
tries++;
}
What the program does: Reads two values from input, asks user whether to add, subtract, or find the product. If user enters one of the three options, it calculates, otherwise the program will loop back to the beginning. The program should STOP after calculation if the user enters one of the three options.
I'm not sure why it keeps on looping. How do I make the script loop only when the user types in a string other than "sum", "difference", or "product"? Also, how can I make the code simpler? Is there any way to loop the program without using do ... while?
import java.util.Scanner;
import java.util.Random;
public class simp_calculator
{
public static void main (String[] args)
{
Scanner scan = new Scanner (System.in);
double a, b;
String response;
boolean noresponse;
do
{
System.out.println ("Please enter first number.");
a = scan.nextDouble();
System.out.println ("Please enter second number.");
b = scan.nextDouble();
System.out.println ("Would you like to find the sum, difference, product?");
response = scan.next();
if (response.equalsIgnoreCase ("sum"))
{
System.out.println (a + b);
}
if (response.equalsIgnoreCase ("difference"))
{
System.out.println (a - b);
}
if (response.equalsIgnoreCase ("product"))
{
System.out.println (a * b);
}
else
{
noresponse = true;
System.out.println ("Starting again...");
}
}
while (noresponse = true);
}
}
You are using the assignment operator, =, so noresponse will always be true. The result of the assignment expression is thus true.
You want to check if it is true, so use the comparison operator ==:
while (noresponse == true);
or, because it's already a boolean:
while (noresponse);
Also, you may be getting a compiler error that noresponse may not have been initialized. You will need to make sure that it's initialized in all cases, and that something sets it to false so the loop will eventually end.
change while (noresponse = true); to while (noresponse == true);.
= is an assignment operation - where as == comparison.
Two errors:
The else applies only to the last if; so for any value, other that "product", noresponse becomes true and the loop goes on. Replace all your ifs from the second on with else ifs.
noresponse should be given the value false at the beginning of the loop.
There are 2 issues:
Currently you are looping while noreponse equals true. So to exit that loop, you need to setnoresponse to false when a particular condition is met :) I could give you the answer, but you should be able to figure it out with the info I've given you. (hint: at some point you need to set noresonse to false).
Also, you are setting noresponse to equal, rather than comparing it. You need to use == to compare.
So make while (noresponse = true); into while (noresponse == true);.
just change while (reponse = true) to while(reponse) and name the variable ..