web-dev-qa-db-fra.com

Vérification de la casse des lettres (haut/bas) dans une chaîne en Java

Le problème que je rencontre est que je ne peux pas demander à mon programme de vérification du mot de passe de vérifier une chaîne pour s'assurer que l'un des caractères est en majuscule et l'autre en minuscule. autre et affichez le message d'erreur en fonction de l'instruction à vérifier.

J'ai cherché une réponse sur ce site et sur Internet et je suis incapable d'en trouver une. C'est un devoir.

Ci-dessous, mon code actuel.

import Java.util.Scanner;

public class password
{
    public static void main(String[] args)
    {
        Scanner stdIn = new Scanner(System.in);
        String password;
        String cont = "y";
        char ch;
        boolean upper = false;
        boolean lower = false;

        System.out.println("Setting up your password is easy. To view requirements enter Help.");
        System.out.print("Enter password or help: ");
        password = stdIn.next();
        ch = password.charAt(0);

        while (cont.equalsIgnoreCase("y"))
        {
            while (password.isEmpty())
            {
                System.out.print("Enter password or help: ");
                password = stdIn.next();       
            }

            if (password.equalsIgnoreCase("help"))
            {
                 System.out.println("Password must meet these requirements." +
                     "\nMust contain 8 characters.\nMust contain 1 lower case letter." +
                     "\nMust contain 1 upper case letter.\nMust contain 1 numeric digit." +
                     "\nMust contain 1 special character !@#$%^&*\nDoes not contain the Word AND or NOT.");

                password = "";
            }
            else if (password.length() < 8)
            {
                System.out.println("Invalid password - Must contain 8 charaters.");
                password = "";
            }
            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 = "";
                    }
                }
            }
            else if (!(Character.isUpperCase(ch)))
            {
                for (int i=0; i<password.length(); i++)
                {       
                    ch = password.charAt(i);

                    if (!Character.isUpperCase(ch))
                    {
                        System.out.println("Invalid password - Must have an Upper Case character.");
                        password = "";
                    }
                }
            }
            else
            {
                System.out.println("Your password is " + password);

                System.out.print("Would you like to change your password? Y/N: ");
                cont = stdIn.next();
                password = "";
            }

            while (!cont.equalsIgnoreCase("y") && !cont.equalsIgnoreCase("n"))
            {
                System.out.print("Invalid Answer. Please enter Y or N: ");
                cont = stdIn.next();
            }
        }
    }
}
40
Jon A

Pour déterminer si une chaîne contient des caractères majuscules et minuscules, vous pouvez utiliser les éléments suivants:

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

Cela vous permet de vérifier:

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

Cela fonctionne essentiellement en vérifiant si la chaîne est égale à son équivalent entièrement en minuscule ou en majuscule. Si ce n'est pas vrai, alors il doit y avoir au moins un caractère majuscule ou minuscule.

Quant à vos autres conditions, celles-ci peuvent être satisfaites de la même manière:

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

Avec les messages d'erreur appropriés comme ci-dessus.

138
Sinkingpoint

Une boucle comme celle-ci:

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
            }

A une faille logique évidente: vous le saisissez si le premier caractère n'est pas en minuscule, puis testez si le deuxième caractère n'est pas en minuscule. À ce stade, vous lancez une erreur.

Au lieu de cela, vous devriez faire quelque chose comme ceci (pas du code complet, mais un exemple):

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
}

Bien entendu, l'extrait de code que vous avez fourni, outre la logique défaillante, ne contenait pas de code pour tester les autres conditions imprimées par votre option "aide". Comme cela a été souligné dans l'une des autres réponses, vous pouvez envisager d'utiliser des expressions régulières pour vous aider à accélérer le processus de recherche de chacune de ces choses. Par exemple,

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

Dans du code:

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

Il est possible de combiner ces choses de manière astucieuse - mais surtout lorsque vous êtes un utilisateur novice de regex, il est bien mieux d’être un peu "lent et fastidieux", et d’obtenir du code qui fonctionne pour la première fois (vous pourrez comprendre ce que vous avez fait dans six mois).

7
Floris

Bien que ce code dépasse la compréhension d'un novice, vous pouvez le faire en une seule ligne à l'aide d'une expression rationnelle avec anticipations positives et négatives:

boolean ok = 
    password.matches("^(?=.*[A-Z])(?=.*[!@#$%^&*])(?=.*\\d)(?!.*(AND|NOT)).*[a-z].*");
6
Bohemian

J'ai simplifié la réponse de @Quirliom ci-dessus en fonctions utilisables:

private static boolean hasLength(CharSequence data) {
    if (String.valueOf(data).length() >= 8) return true;
    else return false;
}

private static boolean hasSymbol(CharSequence data) {
    String password = String.valueOf(data);
    boolean hasSpecial = !password.matches("[A-Za-z0-9 ]*");
    return hasSpecial;
}

private static boolean hasUpperCase(CharSequence data) {
    String password = String.valueOf(data);
    boolean hasUppercase = !password.equals(password.toLowerCase());
    return hasUppercase;
}

private static boolean hasLowerCase(CharSequence data) {
    String password = String.valueOf(data);
    boolean hasLowercase = !password.equals(password.toUpperCase());
    return hasLowercase;
}
2
Uzair

Ceci est assez ancien et @SinkingPoint a déjà donné une excellente réponse ci-dessus. Maintenant, avec les idiomes fonctionnels disponibles dans Java 8, nous pourrions lui donner une autre tournure. Vous auriez deux 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;

Ensuite, dans le code, nous pourrions vérifier les règles de mot de passe comme ceci:

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

En ce qui concerne les autres contrôles:

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

Dans certains cas, on peut se demander si la création du lambda ajoute de la valeur en termes d’intention de communiquer, mais l’avantage de lambda est qu’ils sont fonctionnels.

1
Coffee_fan

C'est ce que j'ai eu:

    Scanner scanner = new Scanner(System.in);
    System.out.println("Please enter a nickname!");
    while (!scanner.hasNext("[a-zA-Z]{3,8}+")) {
        System.out.println("Nickname should contain only Alphabetic letters! At least 3 and max 8 letters");
        scanner.next();
    }
    String nickname = scanner.next();
    System.out.println("Thank you! Got " + nickname);

Lisez à propos du motif regex ici: https://docs.Oracle.com/javase/7/docs/api/Java/util/regex/Pattern.html

0
Mikhail
package passwordValidator;

import Java.util.Scanner;

public class Main {
    /**
     * @author felipe mello.
     */

    private static Scanner scanner = new Scanner(System.in);

     /*
     * Create a password validator(from an input string) via TDD
     * The validator should return true if
     *  The Password is at least 8 characters long
     *  The Password contains uppercase Letters(atLeastOne)
     *  The Password contains digits(at least one)
     *  The Password contains symbols(at least one)
     */


    public static void main(String[] args) {
        System.out.println("Please enter a password");
        String password = scanner.nextLine();   

        checkPassword(password);
    }
    /**
     * 
     * @param checkPassword the method check password is validating the input from the the user and check if it matches the password requirements
     * @return
     */
    public static boolean checkPassword(String password){
        boolean upperCase = !password.equals(password.toLowerCase()); //check if the input has a lower case letter
        boolean lowerCase = !password.equals(password.toUpperCase()); //check if the input has a CAPITAL case letter
        boolean isAtLeast8 = password.length()>=8;                    //check if the input is greater than 8 characters
        boolean hasSpecial = !password.matches("[A-Za-z0-9]*");       // check if the input has a special characters
        boolean hasNumber = !password.matches(".*\\d+.*");            //check if the input contains a digit
        if(!isAtLeast8){
            System.out.println("Your Password is not big enough\n please enter a password with minimun of 8 characters");
            return true;
        }else if(!upperCase){
            System.out.println("Password must contain at least one UPPERCASE letter");
            return true;
        }else if(!lowerCase){
            System.out.println("Password must contain at least one lower case letter");
            return true;
        }else if(!hasSpecial){
            System.out.println("Password must contain a special character");
            return true;
        }else if(hasNumber){
            System.out.println("Password must contain at least one number");
            return true;
        }else{
            System.out.println("Your password: "+password+", sucessfully match the requirements");
            return true;
        }

    }
}
0
Felipe Mello

Un rapide coup d'œil à la documentation sur la syntaxe des expressions régulières devrait permettre de déterminer s'il contient un caractère majuscule/minuscule à un moment donné.

0
Thomas