Password Verifier Issue - java

Edit: This is probably very bad code in the PasswordVerifier.Java
I'm doing a password verifier that checks if the entered password is at least 6 characters long, has an Uppercase letter, lowercase letter, and a digit.
I think I have the logistics of it somewhat correct, but for some reason my program isn't going to the next prompt. It asks me for my password and then hangs up and doesn't tell me whether my password is valid or not. I'm thinking that my for loops are correct so I don't know what my issue is.
PasswordVerifier.Java
import java.util.*;
public class PasswordVerifier{
//field
private static int MIN_PASSWORD_LENGTH = 6;
//methods
public static boolean isValid(String str){
boolean valid = false;
PasswordVerifier pass = new PasswordVerifier();
if(pass.hasUpperCase(str)|| pass.hasLowerCase(str) || pass.hasDigit(str)){
valid = true;
}
if (str.length() < 6){
valid = false;
}
return valid;
}
//UpperCase Boolean check
private boolean hasUpperCase(String str){
boolean valid = false;
int i = 0;
while (i < str.length()){
if (Character.isUpperCase(str.charAt(i)))
valid = true;
}
i++;
return valid;
}
//Lowercase Boolean Check
private boolean hasLowerCase(String str){
boolean valid = false;
int i = 0;
while (i < str.length()){
if (Character.isLowerCase(str.charAt(i)))
valid = true;
}
i++;
return valid;
}
//Number boolean check
private boolean hasDigit(String str){
boolean valid = false;
int i = 0;
while (i < str.length()){
if ((Character.isDigit(str.charAt(i))))
valid = true;
}
i++;
return valid;
}
}
PasswordDemo.Java
import javax.swing.JOptionPane;
public class PasswordDemo{
public static void main(String[] args){
String input; //To hold the user's input
input = JOptionPane.showInputDialog("Enter a Password");
if (PasswordVerifier.isValid(input)){
JOptionPane.showMessageDialog(null, "Valid Password");
}
else{
JOptionPane.showMessageDialog(null, "invalid Password, try again.");
}
}
}

Your while loops never increment i, because you placed i++ just past the end of the loop. The result is an infinite loop and the "hanging" you describe.
E.g. replace
while (i < str.length()){
if (Character.isUpperCase(str.charAt(i)))
{
valid = true;
// Added break because we found an uppercase letter already.
break;
}
i++; // Inside the while loop.
}
You'll need to make a similar change to each of your while loops.
Additionally, if you want to enforce all 3 provisions, don't use the logical-OR operator ||, use logical-and, &&:
if (pass.hasUpperCase(str) && pass.hasLowerCase(str) && pass.hasDigit(str)) {
valid = true;
}
That will make sure that the password has an uppercase letter and it has a lowercase letter and it has a digit.

I think your problem is that you are counting i++ outside the while loop.
Put it in the while like this:
private boolean hasUpperCase(String str){
boolean valid = false;
int i = 0;
while (i < str.length()){
if (Character.isUpperCase(str.charAt(i)))
valid = true;
i++;
}
return valid;
}
This is the problem in every while loop you got.

Right now you're making three passes through the password in order to verify the three character conditions - you can condense this down to one pass. In addition, you're checking the password's length last - you should check this first, as it's the fastest condition to verify.
public static boolean isValid(String str) {
if(str.length() < 6) return false;
int i = 0;
boolean hasDigit = false;
boolean hasLower = false;
boolean hasUpper = false;
while(i < str.length() && !hasDigit && !hasLower && !hasUpper) {
if(Character.isDigit(str.charAt(i))) {
hasDigit = true;
} else if(Character.isLowerCase(str.charAt(i))) {
hasLower = true;
} else if(Character.isUpperCase(str.charAt(i))) {
hasUpper = true;
}
i++;
}
return hasDigit && hasUpper && hasLower;
}
In your case the performance gain is probably negligible, but bear this in mind for the future when you may be dealing with more than three conditions and a string (or whatever) with a length much greater than six.

Related

Detect mixed-case words in an if statement

Ok so I'm trying to write a program that prints certain messages when the input contains a certain word in a certain case.
For example, if the word is orange, the program would detect that the word orange is in the input, and then say something depending on whether it exists, is lower case, or is upper case. As far as all that goes, I'm good, the only thing I can't figure out is how to make it detect the word when it's in mixed case, like oRange, or oranGe.
I think this would do it:
if (!yourString.toLowerCase().equals(yourString) && !yourString.toUpperCase().equals(yourString)) {
mixed = true
}
You can utilize a method to see if a particular string is mixed case, for example:
public static boolean isMixedCase (final String inputString) {
if (inputString == null || inputString.isEmpty()) {
return false;
}
Character c;
boolean hasUpper = false;
boolean hasLower = false;
for (int i = 0; i < inputString.length(); i++) {
c = inputString.charAt(i);
if (Character.isUpperCase(c)) {
hasUpper = true;
}
else if (Character.isLowerCase(c)) {
hasLower = true;
}
}
return hasLower && hasUpper;
}
From your question, it is not entirely clear what your exact requirement is.
If you want to detect whether a string matches another, regardless of case, you could just use String::equalsIgnoreCase:
return input.equalsIgnoreCase("orange");
Otherwise, I assume a string in mixed case is when it contains at least one uppercase and one lowercase character.
Well, there are many options:
Character::toUpperCase and Character::toLowerCase
var lower = false;
var upper = false;
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (Character.isUpperCase(c)) {
upper = true;
}
else if (Character.isLowerCase(c)) {
lower = true;
}
if (lower && upper) {
return true;
}
}
return false;
String::toUpperCase and String::toLowerCase
return !(input.equals(str.toLowerCase()) || input.equals(str.toUpperCase()));
Pattern::matches
boolean upper = Pattern.compile("[A-Z]").matcher(input).find();
boolean lower = Pattern.compile("[a-z]").matcher(input).find();
return upper && lower;
In the abovementioned code, I assumed the string to contain only ASCII characters. If you want to support Unicode as well, then you may want to use Character.isUpperCase(int) or Character.isLowerCase(int).
Use this method to check all the cases: identical, lower-case, upper-case, mixed-case.
public class TestCase
{
public static void main(String[] args) {
String str = "orange";
String strInput = "oRange";
System.out.println(testCase(str, strInput));
}
public static int testCase(String str, String strInput) {
// identical
if(str.equals(strInput)) {
return 1;
}
// all lower-case
if(str.toLowerCase().equals(strInput)) {
return 2;
}
// all upper-case
if(str.toUpperCase().equals(strInput)) {
return 3;
}
// mixed-case
if(str.equalsIgnoreCase(strInput)) {
return 4;
}
// not present
return 0;
}
}
For example, to check if a string is mixed-case:
if(testCase(str, strInput) == 4) {
// mixed-case
}
Since testCase is static, you can also use it outside of this class.

Method to Check Password in Java Not Working

I'm trying to write a method that returns if the string is or isn't a valid password in CodeHS.
It needs to be at least eight characters long and can only have letters and digits.
In the grader, it passes every test except for passwordCheck("codingisawesome") and passwordCheck("QWERTYUIOP").
Here's what I have so far:
public boolean passwordCheck(String password)
{
if (password.length() < 8)
{
return false;
}
else
{
char c;
int count = 0;
for (int i = 0; i < password.length(); i++)
{
c = password.charAt(i);
if (!Character.isLetterOrDigit(c))
{
return false;
} else if (Character.isDigit(c))
{
count++;
}
}
if (count < 2)
{
return false;
}
}
return true;
}
If anyone can help, I'd appreciate it. Thanks.
Try an approach using patterns (this is simpler than looping):
public boolean passwordCheck(String password)
{
return password!=null && password.length()>=8 && password.matches("[A-Za-z0-9]*");
}
Decent tutorial on regular expressions (that's where the A-Z magic comes from): http://www.vogella.com/tutorials/JavaRegularExpressions/article.html
Assuming your requirement is as stated
It needs to be at least eight characters long and can only have letters and digits
Then there is no need to count digits. Simply check that the password is the minimum length, then loop over every character returning false if any are not a letter or digit. Like,
public boolean passwordCheck(String password) {
if (password != null && password.length() >= 8) {
for (char ch : password.toCharArray()) {
if (!Character.isLetterOrDigit(ch)) {
return false;
}
}
return true;
}
return false;
}
It's failing those tests because your code checks that the password must have at least 2 digits:-
if (count < 2)
{
return false;
}
And your test strings don't have any. Remove this piece of code and it should work. For a better way of doing it, see other answers.

Password verification not working with a particular sequence

i have written this method
public boolean passwordCheck(String password)
{
boolean isValid = false;
int numCount = 0;
if(password.length() < 8){
return false;
}
for(int i = 0; i < password.length(); i++){
if(!Character.isLetterOrDigit(password.charAt(i)))
{
return false;
}
else{
return true;
}
}
return isValid;
}
and when I do passwordCheck("a * b * e * d * c") (imagine no spaces in between the asterisks) it should return false because i have the
if(!Character.isLetterOrDigit(password.charAt(i)))
so since there are things in the password that are not valid characters i would expect it would return false but that is not the case.
You return true after your first character is a letter or digit.
If you use "return" when a character is "unacceptable" (return false) This is OK - because "one bad apple will spoil the bunch".
And also: "One invalid character means the whole password is invalid..." But if you return true just because one character is valid / true. That is the mistake in your method. –
public boolean passwordCheck(String password)
{
if(password.length() < 8) return false;
for(int i=0; i < password.length(); i++)
if(!Character.isLetterOrDigit(password.charAt(i)))
return false;
return true;
}
You don't want to return true until after you've checked every character. But currently, you're returning true as soon as you've checked the first one.
One possible solution is to get rid of the else clause, and move the return true; down outside the loop, like this.
for(int i = 0; i < password.length(); i++){
if(!Character.isLetterOrDigit(password.charAt(i)))
{
return false;
}
}
return true;

I have java code for entering a password following certain rules

Some websites impose certain rules for passwords. I am writing a method that checks whether a string is a valid password.
The rules of the password are:
A password must have at least eight characters
A password consists of only letters and digits
A password must contain at least two digits
I figured out most of the code, I think I got some concept correct just right now no matter what password I enter it prints out "invalid password"..I tried running the debugger but got really confused.
This is my code below:
import java.util.Scanner;
public class practice {
public static void main(String[] args) {
System.out.print("Enter a password");
Scanner input = new Scanner(System.in);
String password = input.nextLine();
boolean isCorrect = checkPassword(password);
if(isCorrect)
{
System.out.println("Valid Password");
}
else
{
System.out.println("Invalid Password");
}
}
//this method checks the password
public static boolean checkPassword(String password)
{
int countDigit = 0;
if (password.length() >=8 ){
return false;
}
for(int i = 0; i <password.length(); i++)
{
if(!(Character.isLetterOrDigit(password.charAt(i))))
{
return false;
}
}
for(int i = 0; i<password.length(); i++){
if((Character.isDigit(password.charAt(i)))){
countDigit = countDigit + 1;
}
}
if (countDigit >= 2){
return true;
}
else
return false;
}
}
The error is here:
if (password.length() >=8 ){
return false;
}
Here you say that if password is longer than or equal to 8 characters, the password is invalid, which is the complete opposite of the requirement. Change it to:
if (password.length() < 8 ){
return false;
}
Also, you can reduce the number of for loops to make the code faster. You can count the number of digits and check isLetterOrDigit in the same for loop:
int countDigit = 0;
if (password.length() < 8) {
return false;
}
for (int i = 0; i < password.length(); i++) {
if (!(Character.isLetterOrDigit(password.charAt(i)))) {
return false;
}
if ((Character.isDigit(password.charAt(i)))) {
countDigit = countDigit + 1;
}
}
if (countDigit >= 2) {
return true;
} else {
return false;
}

Password Validator

I'm currently trying to make a password validator work with boolean method, since the teacher asked us to do so. This is driving me nuts. To be correct, the password need to have one uppercase, one lower case letter, at least 10 characters and one number. I'm aware that right now, my method returns entirely with the value false, but I'm wondering how I can break the code once I have one uppercase, or one lowercase.
Thanks a lot for your help!
public class AtLeast1UppercaseLowercaseNumber {
public static void main(String[] args){
String password = "H";
System.out.println(password);
if(isSecurePassword(password)){
System.out.println("Yay it works");}
else {
System.out.println("you suck");}
}
public static isSecurePassword(String password) {
int uppercase = 0, lowercase = 0, number = 0;
for(int i=0; i<password.length(); i++) {
for(char c ='A'; c <='Z'; c++) {
if(password.charAt(i) == c) {
uppercase++;
if( uppercase >= 1) {
for(char t = 'a'; t <='z'; t++) {
if(password.charAt(i) == t) {
lowercase++;
if(lowercase >= 1) {
}
}
}
for(int j = '0'; j <='9'; j++) {
if(password.charAt(i) == j) {
number++;
if( number >= 1) {
}
}
}
}
return false;
}
}
I suggest you start by creating multiple private and static test methods, and then delegate to them in your public isSecurePassword(String) method. Implement test methods like boolean oneUpper(String), boolean oneLower(String), boolean oneDigit(String) and boolean tenCharacters(String) as an example
private static boolean tenCharacters(String str) {
return str.length() > 9;
}
and a second example
private static boolean oneUpper(String str) {
for (char ch : str.toCharArray()) {
if (Character.isUpperCase(ch)) {
return true;
}
}
return false;
}
Then your isSecurePassword(String) is just
public static boolean isSecurePassword(String str) {
return tenCharacters(str) && oneUpper(str) && oneLower(str)
&& oneDigit(str);
}
Since there is only one return in this method, which explicitly returns false, this method will always return false.
Method 1:
Define a boolean, which will be returned in the last statement of the method. This boolean is true by default and will be set false if one condition is wrong.
Method 2:
The last statement is an implicit return true statement, and whenever a condition is not fullfilled return false. This will prevent the method from executing more tests.
Method 3:
Make the method look like this
if (containsUpperCase(string) && contains...)
return true;
return false;

Categories

Resources