I have created an ArrayList of users. I have made a method to add new users. The users must have an email and the program has to check the ArrayList to see if the user already exists in the ArrayList. If I run the check for a correct email and correct name separately, it works, but when I combine it using this while(userExists || matchFound), it doesn't work. I have tried everything, so hope you can help me. Thanks in advance.
public void addUser()
{
System.out.println("-----------------------------"); //separation of previous screen
System.out.println("Create a new user.");
boolean userExists = false;
boolean matchFound = false;
String userToAdd;
do {
System.out.println("Username: ");
userToAdd = input.next();
Pattern p = Pattern.compile(".+#.+\\.[a-z]+");
Matcher m = p.matcher(userToAdd);
matchFound = m.matches();
if (matchFound) {
System.out.println("just a check if it is a email");
}
if(!matchFound) {
System.out.println("no email. Try again.");
matchFound = true;
}
for(User currentUser : db.getUsers()) {
if (currentUser.getName().equals(userToAdd)) {
System.out.println("User already exist. Try again.");
userExists = true;
}
}
} while(userExists || matchFound);
}
You want to stay in the loop as long as the user is not a valid email or it already exists. Therefore you need :
while(userExists || !matchFound);
and you probably shouldn't set matchFound to true when it's false :
if(!matchFound){
System.out.println("no email. Try again.");
matchFound = true; // remove this line
}
It should only be set by matchFound = m.matches();
I think your code would work better if you got the naming right. "matchFound" is not really telling and I guess that is where much of the confusion comes from. This is why I suggest you use "isEmail" instead. This makes the code much more readable. Another problem is that you're using variables inside the loop that you initialize only once outside of the loop. This works well for the first iteratation of the loop but leads to uncertain behaviour the second time. For example if you're entering an email that is already in the system, userExists would be set to true and stay true for consecutive iterations of the loop.
I also removed the output for the case where the email is valid. The user experience is better if you just present errors in the case where they occur. You're surely going to present the user with further functionality after they have entered a valid username. This will be enough feedback so that the user understands that the operation was successful.
This should work:
public void addUser()
{
System.out.println("-----------------------------"); //separation of previous screen
System.out.println("Create a new user.");
boolean userExists = false;
boolean isEmail = false;
do
{
userExists = false;
isEmail = false;
System.out.print("Username: ");
String userToAdd = input.next();
Pattern p = Pattern.compile(".+#.+\\.[a-z]+");
Matcher m = p.matcher(userToAdd);
isEmail = m.matches();
if (!isEmail)
{
System.out.println("Not an email. Try again.");
}
for(User currentUser : db.getUsers())
{
if (currentUser.getName().equals(userToAdd))
{
System.out.println("User already exist. Try again.");
userExists = true;
break;
}
}
}while(userExists || !isEmail);
}
I think you need to stay unless and until the user name does not exist and has valid email id. You should do the following:
while(!userExists || !matchFound);
With this you will loop until and unless you have both valid data.
you should not set matchfound to false when it is false. other wise in the next loop it will be true by default. and you did not change it to false in your first block.
then you should use !matchfound instead match found. so that when you didn't found a match you will loop again
You might want to reintialize the booleans to false as the first statements inside the do loop. Otherwise, if userExists is assigned true for an iteration, it will stay true for all the successive iterations.
do
{
userExists = false;
matchFound = false;
System.out.println("Username: ");
userToAdd = input.next();
}
Related
The question is, if I need to chose only from two options in boolean method (Yes or No) how do I put it in IFs?
I try to do like this (see below), it underlines very last brace. If I use default return outside while (but I don't want to), it underlines first return (after first if).
static boolean isAnotherGamer() {
System.out.println("Play another game? Type in Y or N");
Scanner scanner = new Scanner(System.in);
String answer = scanner.nextLine();
while (true) {
if (answer.equalsIgnoreCase("Y")) {
break;
return true;
} else if (answer.equalsIgnoreCase("N")) {
break;
return false;
}
System.out.println("Input mismatch");
} //IDE underline this brace
}
Here is how I would do it. This allows any part of yes or no to be entered. I think it best to pass a Scanner instance rather than creating one each time. Using a regular expression allows for some latitude in the answer.
^$ - beginning and end of string.
(?i) - ignore case
ye?s? - says must have y but e and s are optional.
static boolean isAnotherGamer(Scanner scanner) {
System.out.println("Play another game? Type in Y(es) or N(o)");
while (true) {
String input = scanner.nextLine();
if (input.matches("(?i)^ye?s?$")) {
return true;
}
if (input.matches("(?i)^no?$")) {
return false;
}
System.out.println("Incorrect response, please enter Y(es) or N(o)");
}
}
Why can you not validate the input first, and then after the input is either a yes or no, decide on what to do. If it is not either, you can make the repetition statement continue to run until after you get what you need. The location of your return statement is the problem because if either if or else if statements are not true, the method will not return a boolean as your method signature suggests, and your method will just be an infinite loop.
Your method is declared to return a boolean. There is no return statement in the flow.
Assume you go into the endless loop. At this moment we evaluate what the user entered (why do we do that inside the endless loop? The answer does not change inbetween, does it?)
If it is 'y', we break the loop.
If it is 'n', we break the loop.
In any other case we print something and remain in the loop.
But as soon as the loop was broken -> where is the return statement?
So from my POV, the function should look like this:
static boolean isAnotherGamer() {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("Play another game? Type in Y or N");
String answer = scanner.nextLine();
if (answer.equalsIgnoreCase("Y")) {
return true;
} else if (answer.equalsIgnoreCase("N")) {
return false;
}
System.out.println("Input mismatch");
}
}
Because you've not set a default return value, if the user doesn't choose either "Y" or "N" then nothing is going to be returned so that's why you're getting an error.
Additionally, you shouldn't be putting any code after your break statements as those lines will be completely ignored (again, nothing returned as your return statements are after your breaks.)
You can just completely remove those break statements if you're just wanting to quit that method once you've got your boolean value or you can update a boolean variable for future use if you're wanting to keep running code inside your method. (I've provided an example of this)
System.out.println("Play another game? Type in Y or N");
Scanner scanner = new Scanner(System.in);
String answer = scanner.nextLine();
//To store the state of the user's answer
boolean providedAnswer = false;
//if the answer was yes, set the boolean's val to true
if(answer.equalsIgnoreCase("Yes")){
providedAnswer = true;
}
//output the boolean's value
System.out.println("User wanted to play again? " + providedAnswer);
//return the boolean value
return providedAnswer;
}```
I have to code a program, that's working with boolean operators. The first thing this program should do is to ask the user for an operator by "command:". The user can only enter "&&", "||", "!" and "quit". Quit just shuts down the program. The next thing it does is to ask the user for a boolean variable, but here is my problem: The program works perfectly fine with entering "true" or "false", but the task I've got says, the user can only use "t" for "f" as input. So here is my question: How can I make the program to understand "t" as "true" and "f" as "false"?(by the way if the user enters"!" the program just outputs the negation of the first parameter)
public static void main(String[] args) {
Scanner eingabe = new Scanner(System.in);
System.out.println("Command: ");
String command = eingabe.nextLine();
if(command.equals("quit")) {
System.exit(0);
}
System.out.println("Parameter 1:");
boolean parameter1=eingabe.nextBoolean();
if(command.equals("!")) {
System.out.println(!parameter1);
System.exit(0);
}
System.out.println("Parameter 2:");
boolean parameter2=eingabe.nextBoolean();
if(command.equals("&&")) {
System.out.println(parameter1&¶meter2);
}else if(command.equals("||")) {
System.out.println(parameter1||parameter2);
}
eingabe.close();
}
}
The easiest way would be to write a little method, something like:
boolean customParseBoolean(String input) {
if ("t".equals(input)) {
return true;
} else if ("f".equals(input)) {
return false;
}
// You don't have to throw an exception on invalid input; just an example.
throw new IllegalArgumentException("Invalid input: " + input);
}
and then invoke this something like:
boolean parameter1 = customParseBoolean(eingabe.nextLin());
It doesn't matter which way you do it, but below should work for your example. It just doesn't cover the case when the input is malformed
String parameterString1 = eingabe.next();
boolean parameter1 = !command.equals("f");
String parameterString2 = eingabe.next();
boolean parameter2 = command.equals("t");
you can always cross verify the user input in if() condition. create a boolean value with false by default, if the user types t make that boolean as true and vice versa.
or else u can use switch statements
this i my first attempt at asking a question so hopefully it shows correctly. Basically what I need the program to do is to ask the user for a preset account number and password and only allow them 3 attempts. I then want to call up another method when both requirements are met so i can continue with the program. The first problem i have is that when i enter the correct password its is still showing as incorrect and i don't know why, then i would like to know if i have call the method within the if statement correctly. Thanks.
import java.util.Scanner;
public class Part4 {
public static void main(String[] args)
{
String password = "password", passwordattempt = null;
int accnum = 123456789, acctry = 0, tries = 0;
Scanner input = new Scanner (System.in);
while (acctry != accnum){
System.out.println("\nPlease enter your account number");
acctry = input.nextInt();
if (acctry != accnum)
System.out.print("That number is incorrect. Please try again.");
else
if (acctry == accnum)
{
while (tries < 3)
{
System.out.println("\nPlease enter password");
passwordattempt = input.next();
if (passwordattempt != password){
System.out.print("That password is incorrect");
tries++;
}
else
if (passwordattempt == password){
System.out.print("That is correct");
AccountDetails.Details(args);
}
}
System.out.print("\nYou have exceeded the ammount of tries");
}
}
}
public static class AccountDetails {
private static void Details(String[] args){
System.out.print("it works");
}
}
}
two problems.
1: You're executing your while loop regardless of if it is successful or not.
.
while(tries < 3)
should be
while(tries < 3 && !successfulPassword)
You'll need to add the successfulPassword variable, so that you don't get it right the first time and yet continue to have to enter passwords.
2: Your comparison of strings is grossly, umm, well, wrong. There's two things that catch my eye. The first is you can't use == and != and get the results you expect. You must use .equals(). Secondly, you don't need to repeat the opposite clause like you do with a human. For example, I tell my daughter "If you eat your supper, then you may have cookies. Else, if you do not eat your supper, then you may not have cookies." To a computer, you don't need that last "if you do not eat your supper". It's guaranteed to be true (since you're in the else block anyway) and it just clutters it up. So that just becomes
.
if(passwordAttempt.equals(password) {
successfulPassword = true;
} else {
tries++;
}
In the Java language, Strings are objects, and thus comparing them using '==' is testing by reference, and not by equality.
I believe what you are looking for is
if (passwordattempt.equals(password)) {
Check here for more information:
http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#equals(java.lang.Object)
I have to tokenize a string which looks like this:
4830673048;Tony White
There must be two tokens separated by a ;
The first token must contain 10 digits, and ONLY digits
The second token may not contain digits.
private static boolean isValid(String accountLine) throws BankAccountException
{
StringTokenizer strTok = new StringTokenizer(accountLine, ";");
boolean valid = true;
if(strTok.countTokens() == 2)
{
if(strTok.nextToken().length() == 10 && strTok.nextToken().matches(".*[0-9].*"))
{
if(!strTok.nextToken().matches(".*[0-9].*"))
{
valid = true;
}
}
}
else
{
System.out.println("Invalid Bank Account info. " + strTok.nextToken());
valid = false;
}
return valid;
}
Here is the code I came up with, but it doesn't do what I expected it to do. I know the problem probably lies in my use of .nextToken(). So then my question is, what's the proper StringTokenizer method for ONLY checking the first or the second token?
Just use String.matches() with the appropriate regex and you only need one line:
return accountLine.matches("\\d{10};[^\\d]+");
Unless this is used in more than place, I would just scrap the method and use the snippet in-line.
See if this works for you:
private static boolean isValid(String accountLine) throws BankAccountException
{
StringTokenizer strTok = new StringTokenizer(accountLine, ";");
boolean valid = true;
if(strTok.countTokens() == 2)
{
String acctNum = strTok.nextToken();
String acctHolder = strTok.nextToken();
if(acctNum.length() == 10
&& acctNum.matches(".*[0-9].*")
&& !acctHolder.matches(".*[0-9].*"))
{
valid = true;
}
}
else
{
System.out.println("Invalid Bank Account info. " + strTok.nextToken());
valid = false;
}
return valid;
}
In the code you posted, you were calling nextToken two times while evaluating the first token, inadvertently moving on to the second token too soon. By assigning the values to variables first, you can easily eliminate this issue.
if(strTok.nextToken().length() == 10 && strTok.nextToken().matches(".*[0-9].*"))
{
if(!strTok.nextToken().matches(".*[0-9].*"))
{
valid = true;
}
}
Now let's look at this code. You first say strTok.nextToken().matches(".*[0-9].*") and than say !strTok.nextToken().matches(".*[0-9].*"). Just delete the inner if and try. You don't need a regex match for second token, so no action is needed for that.
I did some research and found this solid example from Mkyong whose tutorials I admire. In the tutorial he wrote:
while (st.hasMoreElements()) {
System.out.println(st.nextElement());
}
Instead of directly using nextToken().
This tutorial of Oracle gives more decent and all-around explanation. In that, nextToken() is deeply explained and exampled.
As you'll see in both examples, nextToken() and nextElement() functions both take the next token from the tokenizer. So you'll need to assign the first call of one of these functions to a variable and do controls on that. Such as:
String firstToken = st.nextToken().toString();
if(firstToken .length() == 10 && firstToken .matches(".*[0-9].*")) {
...
}
Don't forget to use toString() after nextToken().
Try this:
private static boolean isValid(String accountLine) throws BankAccountException
{
StringTokenizer strTok = new StringTokenizer(accountLine, ";");
boolean valid = true;
String bankAccount = (String)strTok.nextElement();
if(strTok.countTokens() == 2)
{
if(strTok.nextToken().length() == 10 && bankAccount.matches(".*[0-9].*"))
{
valid = true;
}
}
else
{
System.out.println("Invalid Bank Account info. " + bankAccount);
valid = false;
}
return valid;
}
I am working on a loan calculator with data validation. I have written everything and good to go. The only thing I cannot figure out is how to write a while loop in where the user is asked "Continue y/n?: " and then have the program continue ONLY when the user types y/Y and the program ENDS ONLY when the user types n/N, any other input should give an error message like "Invalid, you can only enter Y or N". So if the user enters "x" it should display the error message.
I have tried else if clauses, I have also tried to validate data with the methods I used in the rest of the program but I simply don't know how to validate strings. I can only do it with primitive data types.
This is the only way i know how to write the loop as of now, the problem is it will simply end the program with anything but a Y.
an option for the assignment is to use JOptionPane but I do not know how to incorporate that into the while loop and have it display a yes and a no button.
String choice = "y";
while (choice.equalsIgnoreCase("y")) {
// code here
System.out.print("Continue? (y/n): ");
choice = sc.next();
}
}
while(true) {
//Do something
String choice;
boolean validChoice = false;
boolean breakLoop = false;
while(!validChoice) {
System.out.print("Stay in loop(Y/N)?");
choice = sc.next();
if(choice.equalsIgnoreCase("Y")) {
validChoice = true;
}
if(choice.equalsIgnoreCase("N")) {
validChoice = true;
breakLoop = true;
}
if(!validChoice) {
System.out.print("Error! Pick only Y/N");
}
}
if(breakLoop) {
break;
}
//Do something
}
Essentially, you want two loops: one doing the work and the other one inside prompting for user validation.
boolean isContinuing = true;
while (isContinuing) {
// do work
boolean inputIsInvalid = true;
while (inputIsInvalid) {
System.out.print("Continue? (y/n): ");
String choice = sc.next();
if ("y".equalsIgnoreCase(choice)) {
inputIsInvalid = false;
}
else if ("n".equalsIgnoreCase(choice)) {
inputIsInvalid = false;
isContinuing = false;
}
else {
System.err.print("Error: Only valid answers are Y/N.");
}
}
}
Node: I am using boolean variables instead of break statements, it makes the code more straightfoward and readable.
What about
while(true) {
// do something
// get user input (Y or N)
if(input.equals("Y") {
continue;
} else if(input.equals("N")) {
break;
} else {
System.out.println("entered option not valid, please use Y or N");
}
}
I find the best way is to introduce an explaining method.
while (userWantsToContinue()) {
// do another round
}
And ideally you would even make this a method on an interface that is a UI abstraction :
while (user.wantsToContinue()) {
// do another round
}
decoupling the behavior from the UI implementation.