Checking letter case (Upper/Lower) within a string in Java

后端 未结 9 521
闹比i
闹比i 2020-12-04 10:09

The problem that I am having is that I can\'t get my Password Verification Program to check a string to ensure that, 1 of the characters is in upper case and one is in lower

相关标签:
9条回答
  • 2020-12-04 10:57

    To determine if a String contains an upper case and a lower case char, you can use the following:

    boolean hasUppercase = !password.equals(password.toLowerCase());
    boolean hasLowercase = !password.equals(password.toUpperCase());
    

    This allows you to check:

    if(!hasUppercase)System.out.println("Must have an uppercase Character");
    if(!hasLowercase)System.out.println("Must have a lowercase Character");
    

    Essentially, this works by checking if the String is equal to its entirely lowercase, or uppercase equivalent. If this is not true, then there must be at least one character that is uppercase or lowercase.

    As for your other conditions, these can be satisfied in a similar way:

    boolean isAtLeast8   = password.length() >= 8;//Checks for at least 8 characters
    boolean hasSpecial   = !password.matches("[A-Za-z0-9 ]*");//Checks at least one char is not alpha numeric
    boolean noConditions = !(password.contains("AND") || password.contains("NOT"));//Check that it doesn't contain AND or NOT
    

    With suitable error messages as above.

    0 讨论(0)
  • 2020-12-04 10:57

    This is quite old and @SinkingPoint already gave a great answer above. Now, with functional idioms available in Java 8 we could give it one more twist. You would have two lambdas:

    Function<String, Boolean> hasLowerCase = s -> s.chars().filter(c -> Character.isLowerCase(c)).count() > 0;
    Function<String, Boolean> hasUpperCase = s -> s.chars().filter(c -> Character.isUpperCase(c)).count() > 0;
    

    Then in code we could check password rules like this:

    if (!hasUppercase.apply(password)) System.out.println("Must have an uppercase Character");
    if (!hasLowercase.apply(password)) System.out.println("Must have a lowercase Character");
    

    As to the other checks:

    Function<String,Boolean> isAtLeast8 = s -> s.length() >= 8; //Checks for at least 8 characters
    Function<String,Boolean> hasSpecial   = s -> !s.matches("[A-Za-z0-9 ]*");//Checks at least one char is not alpha numeric
    Function<String,Boolean> noConditions = s -> !(s.contains("AND") || s.contains("NOT"));//Check that it doesn't contain AND or NOT
    

    In some cases, it is arguable, whether creating the lambda adds value in terms of communicating intent, but the good thing about lambdas is that they are functional.

    0 讨论(0)
  • 2020-12-04 10:58

    A loop like this one:

    else if (!(Character.isLowerCase(ch)))
                {
                    for (int i=1; i<password.length(); i++)
                    {
                       ch = password.charAt(i);
    
                        if (!Character.isLowerCase(ch))
                           {  
                            System.out.println("Invalid password - Must have a Lower Case character.");
                            password = "";
                           }
                         // end if
                    } //end for
                }
    

    Has an obvious logical flaw: You enter it if the first character is not lowercase, then test if the second character is not lower case. At that point you throw an error.

    Instead, you should do something like this (not full code, just an example):

    boolean hasLower = false, hasUpper = false, hasNumber = false, hasSpecial = false; // etc - all the rules
    for ( ii = 0; ii < password.length(); ii++ ) {
      ch = password.charAt(ii);
      // check each rule in turn, with code like this:
      if Character.isLowerCase(ch) hasLower = true;
      if Character.isUpperCase(ch) hasUpper = true;
      // ... etc for all the tests you want to do
    }
    
    if(hasLower && hasUpper && ...) {
      // password is good
    } 
    else {
      // password is bad
    }
    

    Of course the code snippet you provided, besides the faulty logic, did not have code to test for the other conditions that your "help" option printed out. As was pointed out in one of the other answers, you could consider using regular expressions to help you speed up the process of finding each of these things. For example,

    hasNumber  : use regex pattern "\d+" for "find at least one digit"
    hasSpecial : use regex pattern "[!@#$%^&*]+" for "find at least one of these characters"
    

    In code:

    hasNumber  = password.matches(".*\\d.*");  // "a digit with anything before or after"
    hasSpecial = password.matches(".*[!@#$%^&*].*");
    hasNoNOT   = !password.matches(".*NOT.*");
    hasNoAND   = !password.matches(".*AND.*");
    

    It is possible to combine these things in clever ways - but especially when you are a novice regex user, it is much better to be a little bit "slow and tedious", and get code that works first time (plus you will be able to figure out what you did six months from now).

    0 讨论(0)
提交回复
热议问题