Java中的或运算符问题 - ||

时间:2016-07-13 01:54:48

标签: java

我正在编写密码验证程序,并且在检查特殊字符的or语句中存在一些问题。我不确定它有什么问题,程序的其余部分似乎运行正常,但输入符合条件的密码,例如P @ ndas123 $%,只会导致无限循环。

我认为这个问题与我对!pass.contains("")部分的重要声明有关。如果这是对的,有人可以帮助我理解为什么声明不正确吗?

import java.util.Scanner;

public class DylanJacksonProg5 {
    public static void main(String[] args) {
        Scanner user_input = new Scanner(System.in);
        boolean valid;
        valid = true;

        do {

            //Password rules declared to user
            System.out.println("Password Verifier");
            System.out.println("");
            System.out.println("Enter a password that meets the following rules: ");
            System.out.println("    Is at least 8 characters long");
            System.out.println("    Contains at least 1 lower letter character");
            System.out.println("    Contains at least 1 upper letter character");
            System.out.println("    Contains at least 1 numeric digit");
            System.out.println("    Contains at least 1 special character of the following set: !@#$%^&*");
            System.out.println("    Does not contain the word 'and' or the word 'the'");


            //Gathering password from user
            System.out.println("Enter your password: ");
            String pass;
            pass = user_input.next();


            //Validating password to rules
            if (pass.length() < 8) {
                int shortlen;
                shortlen = 8 - pass.length();
                System.out.println("Password is too short. Please add " + shortlen + " characters");
                valid = false;

            } else
                System.out.println("Password length is acceptable.");


            //Check for character cases
            boolean hasUppercase = !pass.equals(pass.toLowerCase());
            boolean hasLowercase = !pass.equals(pass.toUpperCase());

            if (!hasUppercase) {
                System.out.println("Must have an uppercase Character");
                valid = false;

            }
            if (!hasLowercase) {
                System.out.println("Must have a lowercase Character");
                valid = false;

            }
            if (hasUppercase) {
                System.out.println("Has an upper case character");
            }
            if (hasLowercase) {
                System.out.println("Has a lowercase Character");
            }


            //Check for digit
            for (int i = 0; i < pass.length(); i++) {
                char x = pass.charAt(i);
                if (!Character.isDigit(x)) {
                    valid = false;

                }
            }


            //check for special character
            if (!pass.contains("!") || !pass.contains("@") || !pass.contains("#") || !pass.contains("$") ||
                    !pass.contains("%") || !pass.contains("^") || !pass.contains("&") || !pass.contains("*"))
            {
                valid = false;
                System.out.println("Password requires a special character from the following: !@#$%^&*");
            }

            // check for 'and'
            if (pass.contains("and")) {
                valid = false;
                System.out.println("Cannot contain 'and'");
            }


            //check for 'the'
            if (pass.contains("the")) {
                valid = false;
                System.out.println("Cannot contain 'the'");
            }
            System.out.println("");

        }
        while (!valid);
    }
}

6 个答案:

答案 0 :(得分:1)

我会直接告诉你一个问题。

由于您在验证循环之前将valid设置为true,并且仅在循环中将其设置为false,因此在第一次尝试时输入无效密码将导致循环从不离开。

valid设置为true应该是循环中完成的第一件事。

除此之外,您的检查每个都单独应用于输入字符串中的每个字符,这种情况是不可能的。例如,您检查整个字符串是否等于其小写变体,然后检查它是否也等于其大写变体。

这意味着任何包含字母的字符串都将被视为无效,因为xyZZy不能同时与xyzzyXYZZY同等。

做一些像(伪代码,并减少几个条件只是为了显示方法)会更正确:

do:
    hasLowercase = false
    hasUpperCase = false
    hasNumeric = false
    isLongEnough = false

    get string from user

    if len(string) >= 8:
        isLongEnough = true

    for each character in string:
        if character is lowercase:
            hasLowerCase = true

        if character is uppercase:
            hasUpperCase = true

        if character is numeric:
            hasNumeric = true

    isValid = hasLowerCase && hasUpperCase && hasNumeric && isLongEnough
until isValid

这将检查每个单独的字符,以便其中任何(而不是要求所有)将条件标记为true。

答案 1 :(得分:0)

您的代码存在多个问题,这些问题彼此无关:

  1. 您从未在循环中将valid设置为true,这意味着如果您输入1个错误密码,valid将始终保持false,这意味着无论您之后输入多少正确的密码,循环都将无限重复。换句话说:只有在您第一次尝试输入正确的密码时,程序才会停止。
  2. 大布尔表达式不检查密码是否包含任何字符,而是检查密码是否包含所有字符。绘制真相表或应用DeMorgan的法律,你会看到:

    !p.c("!") || !p.c("@") || !p.c("#") || !p.c("$") || !p.c("%") || !p.c("^") || !p.c("&") || !p.c("*")
    // is the same per DeMorgan's Laws as 
    !(p.c("!") && p.c("@") && p.c("#") && p.c("$") && p.c("%") && p.c("^") && p.c("&") && p.c("*"))
    
  3. 只要您找到一个不是数字的单个字符,就会拒绝密码,IOW 所有字符必须是数字。
  4. 很明显#2和#3相互矛盾,因此根本无法输入有效密码,因此即使你修复了#1,仍然无法退出循环。

答案 2 :(得分:0)

如果您没有密码中的所有特殊字符,则OR运算符会发生冲突,因为在条件语句中,如果您有“!”但不是“@”,它仍然会导致错误值。

您可以做的是分别检查每个特殊字符。

答案 3 :(得分:0)

很抱歉没有解释,但这是你的特殊字符检查块中的否定声明。通常使用!条件有效,但它没有在我使用的这个在线IDE上。不确定为什么。

此代码可以使用:

//check for special character
if (pass.contains("!") || pass.contains("@") || pass.contains("#") || pass.contains("$") ||
                pass.contains("%") || pass.contains("^") || pass.contains("&") || pass.contains("*"))
{
    valid = true;
    System.out.println("Password requires a special character from the following: !@#$%^&*");
}
else
{
    valid = false;  
}

答案 4 :(得分:0)

以下是OR运算符的工作原理:

     if( condition1 || condition2 || condition3 || condition4)
     {
          // .....your code;
     }

如果condition1为真,则不检查剩余条件,程序将移动到IF块内。但是,如果Condition1为false,则检查condition2。如果这是真的,则不检查剩余条件否则(如果它是假的)将检查condition3。依此类推。但是,正如其他人已经提到的那样,你的代码存在的问题多于OR运算符。

例如,对于password = P @ ndas123 $%,它不包含“!”,所以!pass.contain(“!”)将给出true,有效将被设置为false,从而导致无限循环。

答案 5 :(得分:0)

您的代码存在3个问题:

    在对输入进行任何检查之前,
  1. valid必须在循环内设置为true: do { valid = true; ...
  2. 降低&amp;大写检查应以不同方式进行,例如:

        boolean hasUppercase = false;
        boolean hasLowercase = false;
        for (int i = 0; i < pass.length(); i++){
            if (Character.isUpperCase(pass.charAt(i))){
                hasUppercase = true;
            }
            if (Character.isLowerCase(pass.charAt(i))){
                hasLowercase = true;
            }
        }
    
  3. 您的特殊字符检查不正确,您可以使用以下代码:

  4. if (!(pass.contains("!") || pass.contains("@") || pass.contains("#") || pass.contains("$") || pass.contains("%") || pass.contains("^") || pass.contains("&") || pass.contains("*"))){ valid = false; }

    编辑:实际上还有另外一个: 你的数字检查也不会起作用,你可以用下面的代码:

    boolean isDigit = false;
    for (int i = 0; i < pass.length(); i++) {
        char x = pass.charAt(i);
        if (Character.isDigit(x)) {
            //valid = false;
            isDigit = true;
            break;
        }
    }
    if (!isDigit)
        valid = false;