Okay, here I am again. I searched the forum and found the posts that I need to solve this password validator, but I'm not putting it together in my head correctly for some reason. I haven't started the isUpper, isLower, and isDigit functions, but I'm going to do those next.

#include<iostream>
#include<cstring>



using namespace std;

//function prototypes
bool IsValidPassword(char[]);

int main()
{


IsValidPassword(password);



return 0;
}

//function definitions
    bool IsValidPassword(char password[])
    {

    cout<< " Please enter a password at least six characters long,no      longer than sixteen characters long,containing at least one         uppercase and one lowercase letter, and containing at least one     digit. "<<endl;
    cin>>password;


            for(int i =0;i< 5;i++)
            {
            if(strlen(password)<6 && strlen(password)>16)

            return false;

            }
    return password;
    }

I keep getting an error for "password was not declared in this scope" in main. I understand that the strlen function doesn't work for a character array, and I'm guessing that I can't make an array of strings? (that was a whole other can of worms). Can somebody point me in the right direction?
just in case it's needed, here is the assignment statement:

Filename: password.cpp
a) (7 points)
Imagine you are developing a software package that requires users to
enter their own passwords. Your software requires that users’ passwords
meet the following criteria:
- The password should be at least six characters long.
- The password should contain at least one uppercase and at least one
lowercase letter.
- The password should have at least one digit.
Write the following function:
bool IsValidPassword(string) that accepts the password as a string parameter and
returns a Boolean value whether or not the password is valid.
b) (3 points)
Test your function in main().

You're getting the value for password inside the function. You should get the password inside main so that you can pass it to the function.

The assignment clearly states to pass a string not a char array. The string class has an indexing operator([]) that you can use to get each character in the string. The string class also has a size() function the get the number of characters in a string.

Separate functions shouldn't be necessary, since isupper, islower, and isdigit functions to test a character already exist in the std library.

Edited 1 Year Ago by tinstaafl

I keep getting an error for "password was not declared in this scope" in main.

As tinstaafl pointed out already, that is because password isn't declared in main(), and in any case you are using a C-string (a zero-delimited character array, as used in the C language, the predecessor of C++) instead of a string object (a class that is specific to C++, which is recommended when working with new code in C++, and what the assignment actually asks for). C-strings aren't so much a type as they are a convention for how to use a char array to hold strings; I'll explain what I mean by that a little bit later.

So, what you want to have is a declaration for a string in main(), which you would read in from the console in main() and then pass as the argument for IsValidPassword().

One of the principles of code design is the separation of concerns; that is, you want to have the code for communicating with the data source (e.g., a text shell, a windowed user interface, a database) separate from the code which processes the data (e.g., computations based on the data, validation tests, etc.). This makes the logic of both sections easier to understand, makes the sections more modular, makes the interfaces between the sections clearer, and makes it so the computation isn't bound tightly to the I/O. For example, if you write your validation function so that it only gets the data from its arguments, and only returns the result as a function return, then if later on you need to use it with a GUI program, you won't need to re-write the function.

I understand that the strlen function doesn't work for a character array

Actually, the strlen() function only works on a char array, but the array must have a null character - a '\0' - after the end of the actual string data for it to work. by that I mean, if you have a char array called carray of size 16, and your string is 8 characters long, there needs to be a zero character at the ninth array element - carray[8] - to indicate where the string ends.

This is what I mean by C-strings being a convention rather than a type - whether a char array is a C-string or not entirely depends on how you use it, and if you want to use it for holding a string, then you need to follow certain rules. The string class, on the other hand, actually is a data type (specifically, a C++ class), and includes instance functions (methods) that do most of the work for you

I'm guessing that I can't make an array of strings? (that was a whole other can of worms).

Certainly you can make an array of strings; you should be able to make an array of any data type in C++. However, for C-strings, such an array would look like this:

char str_array[16][32];

while for an array of string objects, it would look like:

std::string str_array[16];

Note that the length of the strings isn't defined - string objects, unlike C-strings, automatically resize themselves as needed.

However, there's nothing in this code that would require an array of strings, regardless of how they are defined. Is this question related to a different problem?

Note also that the std::string class requires the <string> header, not <cstring>, which is the header for the legacy C-string functions.

Finally, while the using namespace std; directive is acceptable with small example programs like this, it isn't really recommended in general. The whole purpose of namespaces is to give programmers control over the visibility of variable, type, and function names, including those in the standard library. All of the standard functions are in the std namespace, and for good reason. When you use the using directive, you are throwing away that control - everything in the std namespace is visible, which then limits the names you can use in your code. It is better to either selectively scope frequently used individual elements, like so:

using std::cout;

or better still, use explicit scoping:

std::cin >> password;

While this isn't very important for you yet, it is something to be aware of for the future. When you get around to defining header files, you'll see why; as you will eventually see, you should never use the using directive in a header file, as it will propagate to every file that includes that header, which is a Bad Thing. For now, just understand that the using namespace directive should be used with caution, if at all.

Edited 1 Year Ago by Schol-R-LEA

Comments
Very explanatory and in depth. Thanks
wow ..

Okay, I will look at the string functions she provided us, and I will get back to the thread. Thanks.

Erk, I did it again - I was editing my post, adding details and clarifying some points, when you answered me. You may want to check what I added to it.

So I decided to use the member function .size();
here is what I have:

//This program establishes and verifies password creation.
//Tadd O'Bannion
#include<iostream>
#include<string>


using namespace std;
//function prototypes
bool IsValidPassword(string);
int main()
{
string password;
IsValidPassword(password);

return 0;
}
//function definitions
 bool IsValidPassword(string password)
 {
 cout<< " Please enter a password at least six characters long,no   longer than sixteen characters long,containing at least one   uppercase and one lowercase letter, and containing at least one  digit. "<<endl;
 cin>>password;

   for(int i =0;i< 5;i++)
   {
   if(password.size()<6 && password.size()>16)

   return false;



    return password;
   }
 }

Now my current running error is:

C:\Users\Welcome\Desktop\password.cpp\main.cpp|31|error: cannot convert 'std::string {aka std::basic_string<char>}' to 'bool' in return|

At the risk of death by flame, why am I getting this error? I can see that it cannot use the string as the return...what's the next step? Do I have to return True or False only since it's a bool function? Thanks again for all of the guidance.

Classic "step away from it for a bit and it will come to you".
I looked at it and can't believe, even after saying it up in my last post, that I didn't see I was trying to pass an acceptable bool return, and an unacceptable bool return. I'm posting my code (as it is at the moment), and will repost again once I include the isupper islower and isdigit functions.

//This program establishes and verifies password creation.
//Tadd O'Bannion
#include<iostream>
#include<string>
using namespace std;
//function prototypes
bool IsValidPassword(string);
int main()
{
string password;
IsValidPassword(password);
return 0;
}
//function definitions
 bool IsValidPassword(string password)
 {
 cout<< " Please enter a password at least six characters long,no   longer than sixteen characters long,containing at least one   uppercase and one lowercase letter, and containing at least one  digit. "<<endl;
 cin>>password;
   for(int i =0;i< 5;i++)
   {
   if(password.size()<6 || password.size()>16)
   {
   cout<< " Your password:"<<password<<", does not meet requirements listed above. "<<endl;
   return false;
   }
   else
   {
   cout<<password<<" is an acceptable password. "<<endl;
   return true;
   }

   }
 }

bool IsValidPassword(string) that accepts the password as a string parameter and
returns a Boolean value whether or not the password is valid.

You seem to be missing the point of the assignment. Passing an empty string then asking the user for the password doesn't fit the assignment requirements and is also poor design. Your function should follow the Single Responsibility Principle, and only validate the password not get it from the user.

You're checking the length inside the loop when you only need to check it once before you run the loop

 bool IsValidPassword(string password)
 {
   int size = password.size();     
   if(size<6 || size>16)
   {
       return false;
   }       

   for(int i =0;i< size;i++)
   {
        //Check eacxh character here.
   }
   return true;
 }
int main()
{
    string password;
     cout<< " Please enter a password at least six characters long,no   longer than sixteen characters long,containing at least one   uppercase and one lowercase letter, and containing at least one  digit. "<<endl;
     cin>>password;
    bool validPassword = IsValidPassword(password);
    if(validPassword)
    {
        cout<<password<<" is an acceptable password. "<<endl;
    }
    else
    {
           cout<< " Your password:"<<password<<", does not meet requirements listed above. "<<endl;
    }
    return 0;
}

Edited 1 Year Ago by tinstaafl

I appreciate you pointing that out. I understand what you mean that passing an empty string before testing a condition is poor design. I see how I can fix that from your code above, and I definitely appreciate that you're trying to help me get rid of bad habits before it's too late, but I'm having a hard time understanding how to use the isupper, islower, and isdigit member functions to check for one instance of the condition throughout the string, rather than checking the condition of the entire string itself. do I have to combine the member functions with a search function? I see your comment above to check each character here within the for loop, but I do not know how to use those functions. I am going to look over my notes, and work on this for a bit. Thanks a ton @tinstaafl

The indexing method of the string class returns the char at a specific index in the string.

Using 3 bool variables:

bool oneUpper = false;
bool oneLower = false;
bool oneDigit = false;

that you can set to true when you find a char that meets that requirement means one statement to check if all of them are true.

The functions used to check the chars takes a char as an argument(i.e isupper(password[i])).

Edited 1 Year Ago by tinstaafl

@tinstaafl- Thanks!
I finished it up this evening, and turned it in (since it was due by midnight).
here it is: (I'm comment-numbering my braces so I can keep them grouped properly)

//This program establishes and verifies password creation.
//Tadd O'Bannion
#include<iostream>
#include<string>
using namespace std;
//function prototypes
bool IsValidPassword(string);
int main()
{//1
string password;
 cout<< " Please enter a password at least six characters long,\n containing at least one uppercase \n and one lowercase letter, and containing at least one  digit. "<<endl;
 cin>>password;
IsValidPassword(password);

return 0;
}//1
//function definitions
 bool IsValidPassword(string password)
 {//2
    bool hasDigit = false;
    bool hasUpper = false;
    bool hasLower = false;
        //3
        if(password.length()<6)
        {
            cout<<" The password does not meet the length requirements described above. "<<endl;
            return false;
        }
        //3
            for(int i = 0; i <password.length(); i++)
            {//4
            if(isdigit(password[i]))
                {//braces separating each if statement.!!!!!!!!!!
                //cout<<" The password contains a digit. "<<endl;
                hasDigit = true;
                }
            if(isupper(password[i]))
                {
                //cout<<" The password contains an uppercase letter. "<<endl;
                hasUpper = true;
                }
            if(islower(password[i]))
                {
                //cout<<" The password contains a lowercase letter. "<<endl;
                hasLower = true;
                }
            }//4

        if(hasDigit && hasUpper && hasLower)
        {//5
        cout<<password<<" is an acceptable password. "<<endl;
            return true;

        }//5

        else{
            cout<< " Your password:"<<password<<", is not an acceptable password. "<<endl;
            return false;}
 }//2
This question has already been answered. Start a new discussion instead.