stumped on password check program

goal:
Output "Valid" if input contains no more than 4 numbers and input's length is greater than 4. Otherwise, output "Invalid".

issue:
program won't load...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
using namespace std;

int main() {
   bool passwordValid;
   string passwordStr;
   int i;
   int numNumbers = 0;
   bool goodDigit;
   bool goodLength;
  
  getline (cin, passwordStr);
  
   for (i = 0; i <= passwordStr.length(); i++){
      if (isdigit(passwordStr.at(i))) {
         numNumbers = numNumbers + 1;
      }
   }
   // valid terms
   if (numNumbers <= 4){
      goodDigit = true;
   }
   
   if (passwordStr.length() > 4){
      goodLength = true; 
   }
   // both terms present,,, password valid;
   if (goodLength && goodDigit){
      passwordValid = true;
   }
   else {
      passwordValid = false;
   }
   
   //cout statements;
   if (passwordValid) {
      cout << "Valid" << endl;
   }
   else {
      cout << "Invalid" << endl;
   }
   
   return 0;
}
> for (i = 0; i <= passwordStr.length();
Do less than, not less-equal.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
using namespace std;

int main() {
    bool passwordValid;
    string passwordStr;
    int i;
    int numNumbers = 0;
    bool goodDigit{false};
    bool goodLength{false};
    
    cout << "Enter password: ";
    getline (cin, passwordStr);
    
    for (i = 0; i < passwordStr.length(); i++)
    {
        if (isdigit(passwordStr[i]) ) {
            numNumbers = numNumbers + 1;
        }
    }
    
    // valid terms
    if (numNumbers <= 4)
    {
        goodDigit = true;
    }
    
    if (passwordStr.length() >= 4){
        goodLength = true;
    }
    
    // both terms present,,, password valid;
    if (goodLength && goodDigit){
        passwordValid = true;
    }
    else {
        passwordValid = false;
    }
    
    //cout statements;
    if (passwordValid) {
        cout << "Valid" << endl;
    }
    else {
        cout << "Invalid" << endl;
    }
    
    return 0;
}
Or depending on whether you have a later use for the bool value:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
using namespace std;

int main()
{
    string passwordStr;
    int numNumbers = 0;
    
    cout << "Enter password: ";
    getline (cin, passwordStr);
    
    for (int i = 0; i < passwordStr.length(); i++)
    {
        if (isdigit(passwordStr[i]) )
        {
            numNumbers++;
        }
    }
    
    if ( (passwordStr.length() >= 4) && (numNumbers <= 4) )
    {
        cout << "Valid\n";
    }
    else
    {
        cout << "Invalid\n";
    }
    
    return 0;
}


thanks @salem c that did the job :)
Just for sheets and sheep dip I did a quick pass (sloppy) rewrite that uses some C++ features you probably haven't seen before. A range-based for loop, uniform initialization and the ? ternary operator.

Plus reducing the need for temporary Boolean variables for test comparisons.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>    // std::string & std::getline
#include <cctype>    // isdigit

int main()
{
   std::cout << "Enter the password: ";
   std::string passwordStr;
   std::getline(std::cin, passwordStr);

   // uniform initialization - https://mbevin.wordpress.com/2012/11/16/uniform-initialization/
   int numNumbers { };

   // range-based for loop - https://en.cppreference.com/w/cpp/language/range-for
   for (const auto& itr : passwordStr)
   {
      if (isdigit(itr)) numNumbers++;
   }

   std::cout << "Password is " 
             // ternary operator - https://www.educba.com/c-plus-plus-ternary-operator/
             << ((numNumbers <= 4 && passwordStr.length() > 4) ? "" : "in")
             << "valid\n";
}

Requires C++11 or later for the range-based for loop and uniform initialization.

numNumbers = numNumbers + 1; could be rewritten as numNumbers += 1; or even more common as numNumbers++; since you are incrementing the number by 1.

You could/should have another test condition for password validity due to using std::getline to retrieve the entire line: check for any spaces.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <string>
#include <cctype>

int main()
{
   std::cout << "Enter the password: ";
   std::string passwordStr;
   std::getline(std::cin, passwordStr);

   int numNumbers { };
   bool hasSpace { }; // uniform initialized to false

   for (const auto& itr : passwordStr)
   {
      if (isdigit(itr)) numNumbers += 1;

      if (isspace(itr)) hasSpace = true;
   }

   std::cout << "Password is " 
             // !hasSpace inverts the value - true to false or false to true. 
             << ((!hasSpace && numNumbers <= 4 && passwordStr.length() > 4) ? "" : "in")
             << "valid\n";
}

Other tests, for upper/lower case letters for instance, could be added to the loop as well. :)
As has been mentioned here before, the isxxx() functions require an argument of type unsigned char - not char.

For the ones that return an int (toupper(), tolower(), the return value needs to be cast to a char.

So L16 would be:

1
2
    if (std::isdigit(static_cast<unsigned char>(itr)))
        ++numNumbers;


or:

 
    numNumbers += std::isdigit(static_cast<unsigned char>(itr)) != 0;


Note. isdigit() et al doesn't return type bool, but type int as it's a c function!

Also:

 
    hasSpace |= std::isspace(static_cast<unsigned char>(itr)) != 0;

Last edited on
I did mention it was a first pass, sloppy bit of code. Which was being revised for a second pass to include the casting. Implicit compiler casting can be notoriously buggy.

Yeah! That's what was happening! :D
Topic archived. No new replies allowed.