C++ Password Strength Checker Project
Type a password and get an instant strength rating with reasons.
What you will build
Paste in a password and the checker scores it — length, mixed case, digits, symbols — then explains what's missing. It teaches systematic string analysis, and the scoring-rules design is your first taste of building a small rule engine.
What you will learn
- Iterating characters in a string
- Classifying characters with <cctype>
- Designing a simple scoring system
- Giving specific, actionable feedback
Feature checklist
- Scores length, upper/lower case, digits, symbols
- Rates password Weak / Fair / Strong / Excellent
- Lists exactly which checks failed
- Flags common patterns like '1234' or 'password'
- Never stores or prints the password back unnecessarily
Starter code
#include <iostream>
#include <string>
#include <cctype>
int score(const std::string& pw, bool& up, bool& low,
bool& dig, bool& sym) {
up = low = dig = sym = false;
for (unsigned char c : pw) {
if (std::isupper(c)) up = true;
else if (std::islower(c)) low = true;
else if (std::isdigit(c)) dig = true;
else sym = true;
}
int s = 0;
if (pw.size() >= 8) ++s;
if (pw.size() >= 12) ++s;
if (up) ++s; if (low) ++s; if (dig) ++s; if (sym) ++s;
return s; // 0-6
}
int main() {
std::string pw;
std::cout << "Password: ";
std::getline(std::cin, pw);
bool u, l, d, s;
int sc = score(pw, u, l, d, s);
std::cout << "Score: " << sc << "/6 -> "
<< (sc <= 2 ? "Weak" : sc <= 4 ? "Fair" : "Strong") << "\n";
if (!u) std::cout << " - add an uppercase letter\n";
if (!d) std::cout << " - add a digit\n";
if (!s) std::cout << " - add a symbol like ! or #\n";
}Full walkthrough
Step 1: Define what 'strong' means as countable checks
The starter's score() function runs a battery of yes/no tests on the string: length at least 8, length at least 12, contains a lowercase letter, an uppercase letter, a digit, and a symbol — one point each, 6 maximum. Turning 'strong' into six concrete questions is the design move; the rest of the program is just asking them.
Step 2: Classify characters with <cctype>
Loop over the string once, setting flags with std::islower, std::isupper, std::isdigit from <cctype>, and treat 'not alphanumeric and not space' as a symbol. One pass, four flags. Cast each char to unsigned char before calling the cctype functions — passing a negative char value is undefined behaviour that bites on non-ASCII input.
for (char ch : pw) {
unsigned char u = static_cast<unsigned char>(ch);
if (std::islower(u)) hasLower = true;
else if (std::isupper(u)) hasUpper = true;
else if (std::isdigit(u)) hasDigit = true;
else if (!std::isspace(u)) hasSymbol = true;
}Step 3: Map the score onto a verdict
0–2 points is Weak, 3–4 is Fair, 5 is Strong, 6 is Excellent. Keep the thresholds in one place so the report and the verdict can never disagree about what a 4 means.
Step 4: Report exactly which checks failed
The checklist demands specifics, not just a grade: print a line per failed test ('✗ no symbol', '✗ under 12 characters'). This is why score() should expose the individual results, not only the total — a struct of bools or a bitmask beats a bare int the moment the report needs detail.
Step 5: Flag the embarrassingly common patterns
Check the lowercased password against a small built-in list ('password', '123456', 'qwerty', 'letmein') and for obvious sequences like '1234' or 'abcd' inside it. A hit caps the verdict at Weak no matter how many points it scored — 'Password1!' passes every composition rule and is still a terrible password, and your checker should say so.
Step 6: Never echo the password back
Read the password, analyse it, report on it — but do not print it in the results. The starter's checklist says 'never stores or prints the password back unnecessarily', which is a real security habit, not decoration: checkers that log passwords create the very leaks they exist to prevent.
Step 7: Test with a ladder of passwords
Run 'abc' (Weak), 'sunshine' (long but one class, plus a dictionary word), 'Sunshine7' (Fair/Strong boundary), and 'Tr7!falcon99' (12 characters, all four classes — Excellent). If 'Password1!' does not get flagged as common, your pattern check is not wired in.
Common mistakes
- Returning only the total score from score(), then being unable to list which checks failed without duplicating the whole analysis.
- Passing plain char (possibly negative) into std::isupper and friends — cast to unsigned char first.
- Treating length as the only real test, so 'aaaaaaaaaaaaaaaa' (16 points of nothing) rates Excellent.
Compile and run
g++ -std=c++17 -o password_checker password_checker.cppSample run
$ ./password_checker
Enter a password to check:
> sunshine
Strength: Weak (2/6)
✓ at least 8 characters
✓ has a lowercase letter
✗ under 12 characters
✗ no uppercase letter
✗ no digit
✗ no symbol
Enter a password to check:
> Tr7!falcon99
Strength: Excellent (6/6)
✓ at least 8 characters
✓ at least 12 characters
✓ lowercase, uppercase, digit and symbol all present
Enter a password to check:
> Password1!
Strength: Weak — this is one of the most common passwords in the world.Try it in your browser
This project has a browser demo in the classic site. The demo is a browser re-implementation of the same logic, not the compiled C++ program: Type a password and watch the strength meter react. Nothing you type leaves this page.