I'm trying to write a program where the run method calls a predicate method that asks someone "Do you want to go to a movie tonight?". If the user enters "yes" to the question I want the program to say "Ok. Let's go tonight." If the user enters "no" I want the program to print "That's cool lets go next week." But if the user enters "maybe" I want my program to say "it's a yes or no question" then ask the question again "Do you want to go to go to a movie tonight? " and then wait for a user to enter a response again. The problem I' having is if the user enters "maybe" the program says "it's a yes or no question" then automatically prints "that's fine lets go next week." How do i fix this incorrect logic in my program? This is a question in the chapter focusing on parameter passing in my book. Did I correctly design my program to pass the string value from the run method to the isYesorNo method for what I'm trying to write?
import acm.program.*;
public class MoviesTonight extends ConsoleProgram {
public void run() {
String answer = readLine("do you want to go to a movie tonight?");
if (isYesorNo(answer)) {
println("Ok. Let's go tonight");
} else
println("that's cool let's go next week");
}
private boolean isYesorNo(String response) {
while (!response.equals("yes") && !response.equals("no")) {
println("it's a yes or no question");
break;
}
return (response.equals("yes"));
}
}
I would use a enum for returning the answer if you want something other than true/false, but still a discrete set of values.
For example:
enum Answer {
YES,
NO,
MAYBE
}
Then switch on the enum instead of if/else (down to personal preference, I think a switch statement is cleaner), putting all in a while loop:
boolean yesOrNo = false;
while (!yesOrNo) {
Answer answer = readAnswer("do you want to go to a movie tonight?");
switch (answer) {
case ANSWER.YES:
println("Ok. Let's go tonight");
yesOrNo = true;
break;
case ANSWER.NO:
println("that's cool let's go next week");
yesOrNo = true;
break;
default:
println("it's a yes or no question");
break;
}
}
So basically if the answer is MAYBE, yesOrNo doesn't get set to true so the while loop is executed again when the condition is checked.
The readAnswer method should be a private static helper method and return the correct enum value based on the input string. Either do this by using an if/else or switch statement on the string.
Two things here:
The logic is wrong. If the input is "maybe", then your isYesOrNo will print out "it's a yes or no question", but then returns false, which gives the additional (problematic) output ""that's cool let's go next week".
The break in the loop does not make sense, which is the real problem. The loop should continue unless the condition is meet, it should break out on the first execution of the loop.
In addition to the suggestions already provided, the isYesOrNo method contains a significant error, which is in fact the answer to your base question:
The problem I'm having is if the user enters "maybe" the program says "it's a yes or no question" then automatically prints "that's fine lets go next week." How do i fix this incorrect logic in my program?
return (response.equals("yes"));
If the response is 'maybe', then it does not equal 'yes', and the return will be false -- this is why it immediately prints, "that's cool let's go next week". That is in fact the 'else' condition you supplied for if(isYesOrNo(answer)).
As it stands, you're checking to see if the response is yes/no, starting a while loop which runs if it isn't yes/no, breaking the while loop prematurely, and then returning false on one of the conditions which spawned the while loop in the first place (read: not 'yes'), which finally gets handled as a 'no' (which may not be the case).
Try something like the following, if you want to use if-else:
public void askQuestion(){
String response = readline("Do you want to go to a movie tonight?");
getYesNoResponse(response);
}
public void getYesNoResponse(String answer){
if (answer.equals("yes"){
//print the yes response
} else if (answer.equals("no") {
//print the no response
} else {
askQuestion();
}
}
Related
I'm fairly new to java and was wondering how would one force a user to enter a valid option in a do...while loop?
What i'm trying to achieve here is to display a menu for as long as the user does not select the exit option which is '4' in my case (it's a char not an int). But if the selection is invalid I want to display an error message and prompt the user to make a new selection, this time, without displaying the menu again.
So far, inside my do...while loop i'm displaying different information according to the user selection. If they enter anything other than 1-4, they end up in my last else if which displays an error message, but at the same time they leave the if/else if loop and end up back in the main menu.
Don't know if this is clear but any help would be appreciated. I also tried the same thing with switch but got the same problem.
Thanks.
do {
// display main menu
if (menu == '1') { ... }
else if (menu == '2') { ... }
else if (menu == '3') { ... }
else if (menu == '4') { ... }
else if (menu != '4') { // display error message }
} while (menu != '4')
Okay, so you have a job which we can describe in a self-contained fashion with a short list of clearly stated parameters:
Ask the user for input.
Check that the input is valid.
If not, keep asking.
That's it. That's a job we can write. Easily at that.
So, do that! Make a method to do just this job. There's only one parameter you need, which is: "What constitutes valid input". If we can simplify that we just need a character, and everything from '1' to this char is valid, then:
public char askUser(char maxValid) {
do {
char in = askUserForInput(); // however you get that char.
if (in >= '1' || in <= maxValid) return in;
System.out.println("Enter a value between 1 and " + maxValid + "> ");
} while (true);
}
Then you can just call this method when you need input.
You can roll this logic (so, that'd be a do/while loop inside your do/while loop) into the main loop, but two rather significant aspects of writing good code is to find easily isolatable aspects and to, well, isolate them (be it making new methods, types, modules, or subsystems - it applies across the entire hierarchy), and to avoid repeating yourself.
But if I put it to "valid = false;" it does not work in debug or running.
In fact even running the code, I can't type anything after the "Do you want to order anything else?", no matter if it's in debug or running mode.
Am I missing something? After asking "how many you want to order" and you put in a number after it should ask "do you want to order anything else" which is does but then I can't type and break out of the do while loop. Everything else is working up to that point.
do {
boolean itemValid = true;
while (itemValid) {
System.out.println("Please enter an item name: ");
String enterItem = scnr.nextLine();
if (keepTrack.containsKey(enterItem)) {
System.out.println(keepTrack.get(enterItem));
itemValid = false;
} else {
System.out.println("Sorry we don't exist.");
continue;
}
System.out.println("How many do you want to order?");
int enterQuan = scnr.nextInt();
yourOrder = enterQuan;
valid = false;
}
System.out.println("Do you want to order anything else?");
String yesNo = scnr.nextLine();
if (yesNo.equalsIgnoreCase("n")) {
valid = false;
} else
break;
} while (valid);
Two problems with your code. First, probably unnoticed yet:
do ...
if (keepTrack.containsKey(enterItem)) {
System.out.println(keepTrack.get(enterItem));
itemValid = false;
} else {
System.out.println("Sorry we don't exist.");
continue;
}
When your input is "invalid", you turn into the else branch. The else branch continues the loop. The loop depends on value. Thus: as soon as you start with value=true, and then have an invalid input, you end up with a never-ending loop. Because nothing between the loop start and the continue statement will ever change the conditions that would end the loop.
Your actual question: when you call int enterQuan = scnr.nextInt() that does not consume the "ENTER" that you typed on the console. See here for details.
And there is another problem:
if (yesNo.equalsIgnoreCase("n")) {
valid = false;
} else
break;
}
When the user enters n or N, you go valid=false which ends the outer do-while loop. Thus: when the user enters anything else, the elsepath is taken. What is to be found in the else path? A break. Which also ends the do-while loop.
In other words: your code does exactly what you told it to do: to end the do-while loop, one way or the other.
The real answer is: you need to be much more careful what you put in your code. Each and any character matters. And when you put something into your code for an experiment: remember that it is there, and has effects.
I have a registration page where the user has to enter personal information about themselves, if something entered is invalid then error notifications should pop up
if (!PhoneNumber.startsWith("055") || !PhoneNumber.startsWith("050") || !PhoneNumber.startsWith("056") || !PhoneNumber.startsWith("052")) {
// does not match
contact_number.setError("Please enter a valid phone number");
return;
}
if (TextUtils.isEmpty(password) )
{
VendorRegPassword.setError("Please enter your password");
return;
}
else if (password.length() < 6)
{
VendorRegPassword.setError("Please use more than 6 characters");
return;
}
if (TextUtils.isEmpty(email) || !email.contains("#") )
{
VendorRegEmail.setError("Please enter a valid email address");
}
Independently they work on their own but when put together it does not work properly, also the phone number error does not work properly, can somebody help me with this?
The other answer is correct; the return statement simply prevents all checks to be executed. And in this case, you want all validations to take place, as each validation has a different way of informing the user about the problem.
Beyond that: from a "clean code" perspective you should be careful to simply stuff all validations into the same poor method. Instead: structure your code so that it clearly expresses what is going on, like:
private void validateAll(PhoneNumber number, Email email, Password password) {
validatePhoneNumber(number);
validateEmail(email);
...
and separate helpers like
private void validatePhoneNumber(number) {
boolean validPrefix = false;
for (String validPrefix : PREFEIXES) {
if (phoneNumber.startsWith(validPrefix) {
validPrefix = true;
}
}
if (!validPrefix) {
contact_number.setError("Please enter a valid phone number");
}
}
for example. And please note - I fixed another bad practice (your idea to simply hard-code all valid prefixes). You always want to put such information into some constant set/list; so that you have exactly one place in your code that knows what those prefixes are.
They are not working together properly because you are returning from the method in if or else ifconditions. Remove return statements from if and else. Because return will terminate the execution of method, so further code will never be executed due to return.
They are working separately because, there is no need to execute further conditions (no further conditions at all), so returning from method seems correct solution.
I'm trying to learn java but I'm stuck trying to do a single program which concerns Do While Statement with two conditions. Specifically, I want a method to run until the user write "yes" or "no". Well, down there is my thing, what is wrong with it?
String answerString;
Scanner user_input = new Scanner(System.in);
System.out.println("Do you want a cookie? ");
do{
answerString = user_input.next();
if(answerString.equalsIgnoreCase("yes")){
System.out.println("You want a cookie.");
}else if(answerString.equalsIgnoreCase("no")){
System.out.println("You don't want a cookie.");
}else{
System.out.println("Answer by saying 'yes' or 'no'");
}while(user_input == 'yes' || user_input == 'no');
}
}}
I'd do something similar to Tim's answer. But to do things the way you were trying to do them, you have a lot of problems that need to be fixed:
(1) String literals in Java are surrounded by double quote marks, not single quote marks.
(2) user_input is a Scanner. You can't compare a scanner to a string. You can only compare a String to another String. So you should be using answerString in your comparison, not user_input.
(3) Never use == to compare strings. StackOverflow has 953,235 Java questions, and approximately 826,102 of those involve someone trying to use == to compare strings. (OK, that's a slight exaggeration.) Use the equals method: string1.equals(string2).
(4) When you write a do-while loop, the syntax is do, followed by {, followed by the code in the loop, followed by }, followed by while(condition);. It looks like you put the last } in the wrong place. The } just before the while belongs to the else, so that doesn't count; you need another } before while, not after it.
(5) I think you were trying to write a loop that keeps going if the input isn't yes or no. Instead, you did the opposite: you wrote a loop that keeps going as long as the input is yes or no. Your while condition should look something like
while (!(answerString.equals("yes") || answerString.equals("no")));
[Actually, it should be equalsIgnoreCase to be consistent with the rest of the code.] ! means "not" here, and note that I had to put the whole expression in parentheses after the !, otherwise the ! would have applied only to the first part of the expression. If you're trying to write a loop that does "Loop until blah-blah-blah", you have to write it as "Loop while ! (blah-blah-blah)".
I might opt for a do loop which will continue to take in command line user input until he enters a "yes" or "no" answer, at which point the loop breaks.
do {
answerString = user_input.next();
if ("yes".equalsIgnoreCase(answerString)) {
System.out.println("You want a cookie.");
break;
} else if ("no".equalsIgnoreCase(answerString)) {
System.out.println("You don't want a cookie.");
break;
} else {
System.out.println("Answer by saying 'yes' or 'no'");
}
} while(true);
its only my second program with java and im running into some issues.
I'm trying to get input from a user, either yes or no, then based on that go to an if else statemene. Heres what I have so far
String answer= UI.askString("Do you want to continue?");
if(answer=="yes"){
UI.println("Lets go");
}
else if(answer == "no"){
UI.println("Thank you. Goodbye");
}
else{
UI.println("Please enter yes or no");
}
Im thinking perhaps its better to use booleans for this?
Any help is gladly appreciated!
(also if you're wondering, its a custom import hence the weird syntax in some lines)
Cheers.
When you compare two Strings in Java with the == operator, they are compared to see if they are the same object, rather than whether they contain the same text. So, you could type "yes", and when you use if (answer == "yes") the comparison fails, because the object you got back from UI.askString is a different object, stored at a different place in memory, than the String the compiler generated from the literal "yes".
To compare the value of the two Strings you need to write answer.equals("yes"), or "yes".equals(answer). Either one will work, and will call the equals method of the String class, which will compare the actual text.
The latter syntax, "yes".equals(answer), is often recommended because it will not cause a NullPointerException, even if the variable answer is set to null. This is because the equals method handles null and simply returns false. If, on the other hand, you used the answer.equals("yes") form, and answer was null, you would be trying to invoke a method on null and an exception would be thrown.
what you are looking for is a dialog box. Here is oracle examples, with code. It is more than I can write here. There are ton of yes, no boxes and detection's of user input with them.
http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html
Quick answer:
int dialogResult = JOptionPane.showConfirmDialog (null, "Would You Like to Save your Previous Note First?","Warning",dialogButton);
if(dialogResult == JOptionPane.YES_OPTION){ ... }
Other choices ...
YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, and CLOSED_OPTION
For a command line program you need...
import java.util.Scanner;
The code will look like ...
Scanner in = new Scanner(System.in);
String line = in.nextLine();
//ask them to write yes, no, whatever
if(line.equal("yes"){ }
else if (line.eqals("no") {}
else {}
using MikeG010590's answer, you can try:
Scanner in = new Scanner(System.in);
String line;
System.out.println("you want to continue?");
Boolean exit = null;
do {
line = in.nextLine();
switch (line) {
case "yes":
exit = false;
break;
case "no":
exit = true;
break;
default:
System.out.println("Please enter yes or no");
break;
}
}
while (exit == null);
System.out.println(exit ? "Thank you. Goodbye" : "Lets go");