简体   繁体   中英

How to replace a double while loop?

The program, which assesses password strength, initially checks whether the length of the password is correct (6-12) and whether the password contains extented ASCII characters, ie 127-255.

The problem I have is that if the user first inputs a password which is too short or too long, the program then doesn't check for extended characters in the next password, inputted by the user and vice-versa, with checking for extended characters first.

I implemented a double while loop, if that's the correct way of calling it, however it still didn't bring the desired effect.

import re
import time
#score variable, responsible for later defining if passwords is weak, medium or strong
Score = 0
#list for improvements to password printed out with score at the end
Improvements = []
Password = ""
#defines function for checking for presence of extended characters (i.e. ascii 128-255)
def hasExtended(s):
    return any(ord(i) > 127 for i in s)
#inputs password
Password = input("Please enter a password:")
Password_length = len(Password)
Extended_presence = hasExtended(Password)
#checks password length (6-12), asks user to re-input until password is within boundaries
#checks if password contains extended characters
#double while loops to allow for two conditions simultaneously
while Password_length < 6 or Password_length > 12:
    if Password_length < 6:
        Outputted_length = "too short"
        Outputted_criteria = "no shorter than 6 characters"
    else:
        Outputted_length = "too long"
        Outputted_criteria = "no longer than 12 characters"
    print("Your password is", Outputted_length, ". It has to be", Outputted_criteria, ".")
    Password = input("Please enter a password:")
    Password_length = len(Password)

    while Extended_presence:
        print("Your password contains characters from the extended ASCII list. Please don't use these.")
        Password = input("Please enter a password:")
        Extended_presence = hasExtended(Password)

while Extended_presence:
    print("Your password contains characters from the extended ASCII list. Please don't use these.")
    Password = input("Please enter a password:")
    Extended_presence = hasExtended(Password)

    while Password_length < 6 or Password_length > 12:
        if Password_length < 6:
            Outputted_length = "too short"
            Outputted_criteria = "no shorter than 6 characters"
        else:
            Outputted_length = "too long"
            Outputted_criteria = "no longer than 12 characters"
        print("Your password is", Outputted_length, ". It has to be", Outputted_criteria, ".")
        Password = input("Please enter a password:")
        Password_length = len(Password)
else:
    #defines function for checking for presence of numbers
    def hasNumbers(s):
        return any(i.isdigit() for i in s)
    #defines function for checking for presence of letters
    def hasLetters(s):
        return any(i.isalpha() for i in s)
    #defines function for checking for presence of special characters
    def hasSpecial(s):
        return any(ord(i) < 48 for i in s)
    #checks if password contains letters
    Letter_presence = hasLetters(Password)
    if not Letter_presence:
        Score = Score - 1
        Improvements.append("letters")
    else:
        Score = Score + 1
    #checks if password is all upper case
    Is_upper = Password.isupper()
    if not Is_upper:
        Score = Score + 1
    else:
        Score = Score - 1
        Improvements.append("upper and lower case letters")
    #checks if passwords is all lower case
    Is_lower = Password.islower()
    if not Is_lower:
        Score = Score + 1
    else:
        Score = Score - 1
        Improvements.append("upper and lower case letters")
    #checks if password contains a number
    Number_presence = hasNumbers(Password)
    if not Number_presence:
        Score = Score + 0
        Improvements.append("numbers")
    else:
        Score = Score + 1
    #checks if password is just numbers
    Only_numbers = Password.isdigit()
    if not Only_numbers:
        Score = Score + 0
    else:
        Score = Score - 1
        Improvements.append("other characters")
    #checks if password contains special characters
    Special_presence = hasSpecial(Password)
    if not Special_presence:
        Score = Score + 0
        Improvements.append("special characters, such as '$'")
    else:
        Score = Score + 1
    #outputs weak, medium or strong password to user and suggest improvements
    if Score <= 2:
        print("The program is processing your password...")
        time.sleep(2)
        print("Your password isn't acceptable! Please try again.")
        print("Next time, remember to include", Improvements)
    if Score == 3:
        print("The program is processing your password...")
        time.sleep(2)
        print("Your password is weak, you should try again.")
        print("Next time, remember to include", Improvements)
    elif Score == 4:
        print("The program is processing your password...")
        time.sleep(2)
        print("Your password is medium, it should be OK.")
        print("Next time, remember to include", Improvements)
    elif Score == 5:
        print("The program is processing your password...")
        time.sleep(2)
        print("Your password is strong, it is absolutely fine.")

Try this code , and instead of while just use if in first checking codition of Extended_presence , You don't need while there because its already in the scope of previous while loop :

import re
print([chr(i) for i in range(127,200)])

import re
import time
#score variable, responsible for later defining if passwords is weak, medium or strong
Score = 0
#list for improvements to password printed out with score at the end
Improvements = []
Password = ""
#defines function for checking for presence of extended characters (i.e. ascii 128-255)
def hasExtended(s):
    return any(ord(i) > 127 for i in s)
#inputs password
Password = input("Please enter a password:")
Password_length = len(Password)
Extended_presence = hasExtended(Password)
#checks password length (6-12), asks user to re-input until password is within boundaries
#checks if password contains extended characters
#double while loops to allow for two conditions simultaneously
while Password_length < 6 or Password_length > 12:
    if Password_length < 6:
        Outputted_length = "too short"
        Outputted_criteria = "no shorter than 6 characters"
    else:
        Outputted_length = "too long"
        Outputted_criteria = "no longer than 12 characters"
    print("Your password is", Outputted_length, ". It has to be", Outputted_criteria, ".")
    Password = input("Please enter a password:")
    Password_length = len(Password)

    if Extended_presence:
        print("Your password contains characters from the extended ASCII list. Please don't use these.")
        Password = input("Please enter a password:")
        Extended_presence = hasExtended(Password)

while Extended_presence:
    print("Your password contains characters from the extended ASCII list. Please don't use these.")
    Password = input("Please enter a password:")
    Extended_presence = hasExtended(Password)

output:

Please enter a password:hel¢
Your password is too short . It has to be no shorter than 6 characters .
Please enter a password:hello¢
Your password contains characters from the extended ASCII list. Please don't use these.
Please enter a password:hello¢
Your password contains characters from the extended ASCII list. Please don't use these.
Please enter a password:hellllo#

You can implement such scenario like below: check_pass function will check for length of function

def hasExtended(s):
    return any(ord(i) > 127 for i in s)

check_pass = lambda x: x>=6 and x<=12  # check for range of input value

password=input("Password: ")

if check_pass(len(password)) and not hasExtended(password):
    print("Valid password")
else:
    print("Do not use extended ascii characters, use password with minimum length of 6 and maximum length of 12")

to be more precise about error you can use nesting in below way:

if check_pass(len(password)) and not hasExtended(password):
    print("Valid password")
elif check_pass(len(password)) and hasExtended(password):
    print("do not use extended ascii character")
elif not check_pass(len(password)) and hasExtended(password):
    print("password length should be between 6 to 12")

similarly if you want to check for invalid length of minimum lenght and maximum length separately.

If you wish to check all condition separately and then show success or failure you can do like below:

def verify_password(password):
    if len(password) < 6:
        print("require minimum 6 characters")
    if len(password) > 12:
        print("can not use more then 12 characters")
    if hasExtended(password):
        print("use only valid ascii characters")
    else:
        print("valid password")
        return True

while not verify_password(password): # loop will never stops unless valid password or used break statement within
    password = input("Password: ")

The function will check for three different condition if condition satisfied message will be printed else it will continue executing, at the end if it is valid password instead of printing anything it will print valid password and return True instead of None .

I would suggest you to write validator, a function that looks like this:

def validate_password(password):
    ... # check score, symbols and other, print whatever you want
    return score

And then call it in a way like that one:

pass = input('Enter your password')
score = validate_password(pass)
while score <= 3:
    pass = input('Enter another password')
    score = validate_password(pass)

Why don't you delegate your password check to a function and separate the user input from checking the password? That way you can ask the user as many times as you want without complex jumps. Something like:

def validate_password(password):
    if len(password) < 6:
        return 0, "Your password is too short, it has to be no shorter than 6 characters."
    elif len(password) > 12:  # why, tho?
        return 0, "Your password is too long, it has to be no longer than 12 characters."
    # these can be optimized but I'll leave that as an exercise for you
    if any(ord(i) > 127 for i in password):  # again, why?!
        return 0, ("Your password contains characters from the extended ASCII list. "
                   "Please don't use these.")
    score = 0
    improvements = []
    if any(i.isalpha() for i in password):
        score += 1
        if password.isupper() or password.islower():
            score -= 1
            improvements.append("upper and lower case letters")
        else:
            score += 1
    else:
        score -= 1
        improvements.append("letters")
    if any(i.isdigit() for i in password):
        score += 1
        if password.isdigit():
            score -= 1
            improvements.append("other characters")
    else:
        # score -= 1   # are you sure you don't want to reduce the score?
        improvements.append("numbers")
    if any(ord(i) < 48 for i in password):
        score += 1
    else:
        # score -= 1   # are you sure you don't want to reduce the score?
        improvements.append("special characters such as '$'")
    return score, "Next time remember to include: {}".format(", ".join(improvements))

And now you can call it from wherever you want, as many times as you need:

while True:
    candidate = input("Please enter a password: ")
    print("The program is processing your password...")  # why? this happens in an instant
    score, message = validate_password(candidate)
    time.sleep(2)  # why are we making people wait for no reason?
    if score <= 1:
        print(message)
        print("Please try again.")
    elif score == 2:
        print("Your password is weak, you should try again.")
        print(message)
    elif score == 3:
        print("Your password is medium, it should be OK.")
        print(message)
        break
    elif score == 4:
        print("Your password is strong, it is absolutely fine.")
        break

print("Accepted password: " + candidate)

And you can get an output as:

Please enter a password: dfld
The program is processing your password...
Your password is too short, it has to be no shorter than 6 characters.
Please try again.
Please enter a password: dfldsadlslads
The program is processing your password...
Your password is too long, it has to be no longer than 12 characters.
Please try again.
Please enter a password: dflds°
The program is processing your password...
Your password contains characters from the extended ASCII list. Please don't use these.
Please try again.
Please enter a password: ddlllsd
The program is processing your password...
Next time remember to include: upper and lower case letters, numbers, special characters
such as '$'
Please try again.
Please enter a password: ddlllsd12
The program is processing your password...
Next time remember to include: upper and lower case letters, special characters such as '$'
Please try again.
Please enter a password: Ddlllsd12
The program is processing your password...
Your password is medium, it should be OK.
Next time remember to include: special characters such as '$'
Accepted password: Ddlllsd12

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM