I couldn't figure out how to solve this problem using a single isValidPassword method so I broke it down into 3 and got it to work. Can someone explain to me how I could use the code I wrote and if possibly condense it?
Create a program Password that prompts for a password from the user and determines if the password is valid or invalid. There should be a static method isValidPassword that validates the password (String) and returns either true or false. A user has ONLY three tries to enter a valid password.
A valid password follows these three rules:
- Must have at least eight characters.
- Must contain ONLY letters and digits.
- Must contain at least two digits.
Use dialog boxes for the program. You must use the String and Character classes for this program. You may NOT use regular expressions. The program only needs to run once.
import javax.swing.JOptionPane;
public class Password {
public static void main(String[] args) {
int retryCount = 0;
while (retryCount < 3) {
retryCount++;
String password = JOptionPane.showInputDialog("Please Enter the Password");
if (CheckPassword(password)) {
JOptionPane.showMessageDialog(null, "Congrats! Correct Password!");
break;
}
else {
JOptionPane.showMessageDialog(null, "Sorry, Invalid Password, you tried " + retryCount + " times");
continue;
}
}
}
public static boolean CheckPassword(String password) {
if (password.length() >= 8 & CheckAlphanumeric(password) && Check2digits(password)) {
return true;
}
else {
return false;
}
}
public static boolean CheckAlphanumeric(String string) {
for (int i = 0; i < string.length(); i++) {
char x = string.charAt(i);
if (x < 0x30 || (x >= 0x3a && x <= 0x40) || (x > 0x5a && x <= 0x60) || x > 0x7a) {
return false;
}
}
return true;
}
public static boolean Check2digits(String string) {
int count = 0;
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (Character.isDigit(c)) {
count++;
}
if (count > 2) {
return true;
}
}
return false;
}
}
Lets give a quick code review:
Read about java naming conventions. Method names go camelCase; and things that return boolean should be named like isPasswordValid() for example
What your are doing here is actually a good approach: one should prefer many small methods (that carry good meaningful names!) over having a few large methods (the thing behind is called the "Single Layer of Abstraction" Principle)
You could read about regular expressions in order to do most of that checking; especially checking for "ascii chars only" is a good candidate there! So even when your assignment says "dont use them"; you might want to learn how to use them. Just for your own learning progress! But as Kayaman pointed out, the Character class has many static helper methods for such checks; so there is no need to implement all of that manually.
Your code is "logically inconsistent". Your code is validating if some string adheres to certain password rules (minimum length, minimum number of digits). But your messages are implying that this code is checking if a provided password is correct; like in: user enters his password, and then code checks if that password is known and matching a previously stored password. In that sense: make sure messages and code content are consistent!
Beyond that; a suggestion how to enhance your design for "real world" usage. Thing is: there can be many many different rules that make a password valid. Which might change over time. And typically, you would want to tell your user which of that rules his input is conflicting with. One option to address these concerns:
public interface PasswordValidator {
public void checkPassword(String password) throws InvalidPasswordException;
}
Then you create various implementations, such as
public class MinimumLengthValidator implements PasswordValidator {
#Override
public void checkPassword(String password) throws InvalidPasswordException {
if (password.lenght() < 8) {
throw new InvalidPasswordException("Given password is not long enough; expecting at least 8 characters");
}
}
And then, you create instances of those different validator classes; and store them in some array. You iterate the array, and call each validation on its own; and when it fails, you directly receive an exception with a nice message for the user.
As said: the above is meant as inspiration only (and just typed down, so beware of typos).
Look at below code which may fulfill your all requirements-
This is pure java class. you can check logic from the below code.
program edit1 - To specify why password is incorrect.
public class Demo {
private final int passwordAttempts = 3;
private int countAttempts = 0;
private String password;
private int digitCounter = 0;
public Demo() {
init();
}
public static void main(String[] args) {
new Demo();
}
private String checkPassword(String pass) {
if (pass.length() >= 8) {
if (StringUtils.isAlphanumeric(pass)) {
char[] toCharArray = pass.toCharArray();
for (int i = 0; i < toCharArray.length; i++) {
char check = toCharArray[i];
if(Character.isDigit(check)){
digitCounter++;
}
}
if (digitCounter >= 1) {
return "success";
}else{
return "digit";
}
}else{
return "alphanumeric";
}
}else{
return "length";
}
}
private void init() {
while (countAttempts < passwordAttempts) {
password = JOptionPane.showInputDialog("Please Enter the Password");
digitCounter = 0;
String passwordResult = checkPassword(password);
if (passwordResult.equals("success")) {
JOptionPane.showInputDialog("yes you entered correct password...");
} else if(passwordResult.equals("length")){
JOptionPane.showInputDialog("password must contain atleast 8 characters...");
}else if(passwordResult.equals("alphanumeric")){
JOptionPane.showInputDialog("only alphanumeric password accept...");
}else if(passwordResult.equals("digit")){
JOptionPane.showInputDialog("password must contain atleast two digits...");
}
countAttempts++;
}
}
}
Now only you need to replace JOptionPane.showInputDialog() method with some other method which only specify message because showInputDialog() method prompts input text field also to enter value and we don't want this. I don't have idea any idea about swing.
Based on your comment -
This method returning string values like success,length,alphanumeric,digit ect. and below we are comparing this values with all above in if else if. whenever it get equal that means we have to show length message ,alphanumeric string message ,digit message accordingly.
Dependency -
I'm using maven. following dependency need to add into pom.xml file.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
If you are not aware about maven then simply download jar file from here and provide in lib folder of your project.
Related
... if instead of a number I get a letter, or a symbol, or 2 decimals.
I am making a change maker program in java.
Everything works good, the only thing i am confused about is checking the string to see if is invalid for my use,
I did this for when is left empty;
if (s1.isEmpty()) {
JOptionPane.showMessageDialog(null, "Invalid input! ");
System.exit(0);
}
That works perfect, now how can I do the else to check for letters or dots or symbols, anything that is not a number?
You could use regular expressions.
Here's some sample code to check for digits only (\\d) in your input string.
The code that actually checks is pattern.matcher(in).matches() and it tries to match the regular expression defined by regex
Let me know if you need more explanations
public class HelloWorld{
public static void main(String[] args) {
String regex = "\\d+";
String inputNumber = "2";
String inputDecimal = "2.0";
String inputString = "two";
String[] inputs = {inputDecimal, inputNumber, inputString };
Pattern pattern = Pattern.compile(regex);
for(String in: inputs){
System.out.print( in + " ");
System.out.print( pattern.matcher(in).matches()? "":"does not");
System.out.print( " contain integer numbers" );
System.out.println("---");
}
}
}
If you need to perform all the processing only when the String is integer why not check for integer value in the if clause and let the else clause be common for all the letter, dots, symbols and also empty.
if(s1.isNum){
//all processing here
}
else{
JOptionPane.showMessageDialog(null,"Invalid Input");
System.out.exit(0);
}
Otherwise you could also use try and catch block.
try{
int num= Integer.parseInt(s1);
//rest of the processing
}
catch(Exception e){
JOptionPane.showMessageDialog(null,"Invalid Input");
System.out.exit(0);
}
Use either according to your requirement
You could use a regular expression1 and String.matches(String) which Tells whether or not this string matches the given regular expression. \\d+ should match one or more digits. Something like
System.out.println("12".matches("\\d+"));
Prints
true
1Some people, when confronted with a problem, think
“I know, I'll use regular expressions.” Now they have two problems. --jwz
To test whether it is an integer, parse it to an int like this:
Integer.parseInt(s1)
You might also want to make use of the value returned but I don't show it here. Now you can apply try catch blocks around the method call and catch NumberFormatException like this:
try {
Integer.parseInt(s1);
//The code here will run if s1 is an integer.
} catch (NumberFormatException e) {
//this will be executed when s1 is not an integer
}
You can also extract a method from the above code. A method that returns true when the exception is not thrown. However, a disadvantage of try catch is that throwing an exception needs time and thus, it slows down your program.
To test whether the string is a letter, you loop through all the chars in the string and use one of the methods of the Character class.
boolean isLetter = true;
for (int i = 0 ; i < s1.length() ; i++) {
if (!Character.isLetter(s1.charAt(i))) {
isLetter = false;
break;
}
}
If isLetter is true, it is a letter. Again, you can also extract this as a method.
To check whether it is a symbol, use one of the methods of the Character class (again).
boolean isSymb = true;
for (int i = 0 ; i < s1.length() ; i++) {
if (!Character.isJavaIdentifierStart(s1.charAt(i))) {
isSymb = false;
break;
}
}
To check for dots in a string, just use
s1.contains(".")
Isn't that simple?
Ok, I solved the problem the following way... I took a little bit of every idea lol...
if (s1 == null) {
JOptionPane.showMessageDialog(null, "You must enter a valid integer");
System.exit(0);
}
if (s1.isEmpty()) {
JOptionPane.showMessageDialog(null, "You must enter a valid integer");
System.exit(0);
}
for (int i = 0; i < s1.length(); i = i + 1) {
if (!Character.isDigit(s1.charAt(i))) {
JOptionPane.showMessageDialog(null, "You must enter an integer value");
System.exit(0);
}
}
i'm making a calculator and i want to throw a window with a message saying that only numbers are accepted in case that the user types a character which isn't a number in the textField, so this is what i did and didn't work at all.
Thanks for reading.
private void txtPantallaActionPerformed(java.awt.event.ActionEvent evt) {
String invalids;
invalids = "|##¢∞¬÷“”≠´‚πø ¥†®€æœå∫∂ƒ™¶§ ~–…„µ ß√©∑Ωqwertyuiopñlkjhgfdsazxcvbnm!$%&/=?¿*^QWERTYUIOPÑLKJHGFDSAZXCVBNM";
for (int i = 0 ; i < invalids.length() ; i++)
{
if(txtPantalla.getText().equals (invalids.substring(i, i+1)))
{
JOptionPane.showMessageDialog(null,"Only works with numbers");
}
}
}
You can use regex for readability and to avoid loop:
String value = txtPantalla.getText();
if(Pattern.matches(".*[^0-9].*", value)) {
// there are some invalid characters!
JOptionPane.showMessageDialog(null, "Only works with numbers");
}
Any solution that requires you to hardcode something is probably wrong.
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;
}
Im writing a binary search tree. The user will use the program as follows:
Which tree would you like to test (BST, ST, RBT)?
BST
How many items would you like to insert?
10000
Pattern (random or sorted)?
sorted
Next command (insert X, delete X, find X, height, quit)?
find 111111
Item not present.
For the first three choices i figure i can just use strings to choose between BST, ST and RBT as wel as to choose between random or sorted, somthing like
String choice
if( choice == "random")
insert random numbers
what im having trouble with is the 4th choice. if the user enters insert 100 as a string, for example, would i just have to take the 100 off and make it an int. and if so, how would i go about doing that?
You can use the combination of the functions to determine whether a string is an int or not
public boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch(NumberFormatException e) {
return false;
}
}
If this function returns true ... string is an integer ... now get the integer value using
Integer.parseInt(str);
First thing I want to note is that a String should not be compared with ==, rather you should use string.equals(comparedString); You can also use the following code to parse through all the inputs that a person enters, and then use both the string entered and the string value entered and it would not be dependent on the start of the string. This would satisfy the options for them all; insert, delete, ect.
String userInput;//received by system in
String choice;
int choiceInt;
for (int i = 0; i < userInput.length(); i++)
{
Character character = userInput.charAt(i);
if (!Character.isDigit(character))
{
choice += character;
}
else if (Character.isDigit(character))
{
choiceInt += character;
}
else
{
System.out.println("Unable to determine character.");
}
/* Code for the comparison of String based option */
//Example
if (choice.equalsIgnoreCase("insert")//NOTE: the ignore case,
// you want users to be
// able to enter in strings
// and not have a case sensitivity.
{
/* do the code you planned on doing here */
}
}
You could also assign integer values for each String possibility that you are willing to accept as valid options. This would increase the coding but also would also for a switch case statement. (which is still interpreted as if, else if, else statements) I think at that point it would be more up to the developers intentions and design preferences. Please correct me if I am wrong.
You can also replace the final else statement by either using a try and catch block.
Try this:
if (input.startsWith("insert")) {
int num = Integer.parseInt(input.replaceAll("\\D", ""));
}