简体   繁体   中英

How do I validate user input password using isupper, isdigit and regex in c++

How do i go about validating a password? I have tried to loop through and check each value but this didn't work. I tried to create multiple regex conditions but had no luck at all with that. I did manage to get one regex condition to work so went with trying to use that for just the special characters as from looking online this seemed to be the most straightforward approach to me.

I'm giving in (in a sense) and asking the wider programming community for some help, I've been stuck on this for most of the day, I have searched, tried and tested many different methods but none seem to be working, although i'm positive i'm close.

I am a newbie to the world of C++, and I'm loving it too so far. The task in particular I am stuck on (it is a homework task and this is my last option) is to take a user password, test its strength and let the user know, only allowing them to keep the strongest variation.

I know from much searching, trying & testing that this is very much a newbie error. I have been stuck on this for too long now.

After all my searching, what i am trying to implement is using isupper and isdigit to test for uppercase and number conditions and then a regex search for the special character conditions.

When i run my code, it all works error free, up to the point where the password is entered - this is where i've hit a brick wall.

here is the relevant section of code i currently have:

        cout << "Please enter a desired password: ";
        getline(cin, passwd);
        //cin >> passwd;
        //convert the string into an int to be able to check for No of digits (isdigit)
        int pw = stoi(passwd);
        //cout << "ENTERED PASSWORD: " << passwd << endl;
        //regex string to check for special characters
        regex symbols ("^(?=.*[\\character][\\w])");
        string passwordError ("Password is to weak - Please try again! \\n * A Minimum of 18 Characters \\n * A Minimum of 4 UPPERCASE characters \\n * A Minimum of 3 NUMBERS \\n * A Minimum of 3 Special characters.\"<< endl;");

        while getline(cin, passwd)) {
            *//invalid password: less than 14 characters, no uppercase, numbers or symbols*
            if (passwd.length() < 14) {
                cout << "Invalid Password - Password length is too short";
            } else {
                *//***weak password: less than 14 character length, less than x2 uppercase, less than x2 digits and no special characters;*
                if ((passwd.length() < 14) && (isupper(pw < 2) && (isdigit(pw < 2))) && (!regex_match(passwd, symbols))) {
                    cout << passwordError;
                } else {
                    *//medium password: more than 14, less than 16 characters, less than 2 uppercase, numbers and symbols*
                    if ((passwd.length() < 14) && (isupper(pw < 2) && (isdigit(pw < 2))) && (!regex_match(passwd, symbols))) {
                        cout << passwordError;
                    } else {
                        *//strong password: more than 18 characters, more than 4 uppercase, more than 3 numbers and symbols*
                        if ((passwd.length() > 18) && (isupper(pw < 2) && (isdigit(pw < 2))) && (!regex_match(passwd, symbols))) {cout << passwordError;
                        }
                    }
                }
            }
        }
    }
}

There are many many syntax and semantical errors in your code.

You should have at least compiled it one time before posting and then removed the syntax errors. So, easyt hings like "*//" and so on. However, I created a compilable and minimum reproducible variant. This will still not work, becuase of many logical errors.

But first see the MRE:

#include <iostream>
#include <string>
#include <regex>
#include <cctype>

int main() {

    std::string passwd{};
    std::cout << "Please enter a desired password: ";
    std::getline(std::cin, passwd);
    //cin >> passwd;
    //convert the string into an int to be able to check for No of digits (isdigit)
    int pw = stoi(passwd);
    //cout << "ENTERED PASSWORD: " << passwd << endl;
    //regex string to check for special characters
    std::regex symbols("^(?=.*[\\character][\\w])");
    std::string passwordError("Password is to weak - Please try again! \\n * A Minimum of 18 Characters \\n * A Minimum of 4 UPPERCASE characters \\n * A Minimum of 3 NUMBERS \\n * A Minimum of 3 Special characters.\"<< endl;");

    while (std::getline(std::cin, passwd)) {
    
        //invalid password: less than 14 characters, no uppercase, numbers or symbols*
        if (passwd.length() < 14) {
            std::cout << "Invalid Password - Password length is too short";
        }
        else {
            //***weak password: less than 14 character length, less than x2 uppercase, less than x2 digits and no special characters;*
            if ((passwd.length() < 14) && (isupper(pw < 2) && (isdigit(pw < 2))) && (!regex_match(passwd, symbols))) {
                std::cout << passwordError;
            }
            else {
                //medium password: more than 14, less than 16 characters, less than 2 uppercase, numbers and symbols*
                if ((passwd.length() < 14) && (isupper(pw < 2) && (isdigit(pw < 2))) && (!regex_match(passwd, symbols))) {
                    std::cout << passwordError;
                }
                else {
                   //strong password: more than 18 characters, more than 4 uppercase, more than 3 numbers and symbols*
                   if ((passwd.length() > 18) && (isupper(pw < 2) && (isdigit(pw < 2))) && (!regex_match(passwd, symbols))) {
                       std::cout << passwordError;
                   }
                }
            }
        }
    }
}

Now a list with the rest of the errors

  • You first read a password and try to convert it to a number with std::stoi`
  • This will in most case fail and throw an exception, crashing you program. /How shall "xyz" be converted to a number?
  • Then you have a while loop that willread the password again, overwriting the previously read password
  • There is no end condition forthe while loop. It will run until you press a special key forEOF(Maybe CTRL-D, depending on your terminal)
  • You should give user instructions after the while . Otherwise the user sits and waits,nothing is happening, but in reality, user input is expected
  • The usage if ìsdigit and isupper`is completely wronn. Those functions are inteded to use with ONE character and not and integer number. This willnever work.
  • The regex seems to be wrong, or you need to explain better, what you want to achieve
  • Even,if the password would be completely OK, you would continue your while loop and start over again.
  • You prompt the user to enter minimum 18 characters, but then check against 14

So, your whole logic needs to be updated.

If you want to have a vrtain number of characters, then you need to count them.

See the below example:

#include <iostream>
#include <string>
#include <regex>
#include <cctype>

int main() {

    // Here we will store the password 
    std::string passwd{};

    // This willindicate, if we have a valid password
    bool passwordOK = false;

    // Read a password
    while (not passwordOK) {

        std::cout << "Please enter a password\n\nPassword requirments is:\n- Minimum 18 characters\n"
        "- At least 4 Uppercase characters\n- At least 3 digits\n- At least 3 special characters:\n\nYour input: ";

        // Read the password
        if (std::getline(std::cin, passwd)) {
            // Assume that the passowrd is OK
            passwordOK = true;

            // Check length
            if (passwd.length() < 18) {
                std::cerr << "\nError: Password length is smaller then 18 characters. It is " << passwd.length() << "\n";
                passwordOK = false;
            }

            // Count digits
            unsigned int numberOfDigits{};
            for (const char c : passwd) if (std::isdigit(c)) ++numberOfDigits;
            if (numberOfDigits < 3) {
                std::cerr << "\nError: Password must contain at least 3 digits. It has " << numberOfDigits << "\n";
                passwordOK = false;
            }


            // Count Uppercase
            unsigned int numberOfUppercase{};
            for (const char c : passwd) if (std::isupper(c)) ++numberOfUppercase;
            if (numberOfUppercase < 3) {
                std::cerr << "\nError: Password must contain at least 4 capitals. It has " << numberOfUppercase << "\n";
                passwordOK = false;
            }

            // Count Special characters
            unsigned int numberOfSpecialCharacters{};
            for (const char c : passwd) if (std::ispunct(c)) ++numberOfSpecialCharacters;
            if (numberOfSpecialCharacters < 3) {
                std::cerr << "\nError: Password must contain at least 3 special characters. It has " << numberOfSpecialCharacters << "\n";
                passwordOK = false;
            }
        }
        if (not passwordOK)
            std::cout << "\n\nPassword not OK. Please try again\n\n\n";

    }
    std::cout << "\n\nYour password is OK\n";
}

This is one of many possible solutions.

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