CS50 'Password' Practice Problem

So confused by this problem. I tried doing what the “Implementation Details” said, but it just doesn’t make sense to me. " set each to false before you iterate through the string." :thinking:

Trying my best to do these without caving and looking at the solution.

// Check that a password has at least one lowercase letter, uppercase letter, number and symbol
// Practice iterating through a string
// Practice using the ctype library

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>

bool valid(string password);

int main(void)
{
    string password = get_string("Enter your password: ");
    if (valid(password))
    {
        printf("Your password is valid!\n");
    }
    else
    {
        printf("Your password needs at least one uppercase letter, lowercase letter, number and symbol\n");
    }
}

// TODO: Complete the Boolean function below
bool valid(string password)
{
    if (int isupper(int password))
    {
        return false
    }
    if (int islower(int password))
    {
        return false
    }
    if (int isdigit(int password))
    {
        return false
    }
    if (int ispunct(int password))
    {
        return false
    }

    for (int i = 0; i < password; i++)
    {
        if (isupper(password[i])) && (islower(password[i])) && (isdigit(password[i])) && (ispunct(password[i]))
        {
            return true;
        }
        return false;
    }
}

“Your function will iterate through the password…”

Have you learned how to go through a string one character at a time yet? This is what you want to do here.

“…you may want to create a boolean variable for each and set each to false before you iterate through the string.”

As you go through the string you want to check to see if each letter is either lower case, upper case, a number, or a symbol. So you need to keep track of whether you find one instance of each of these. This is saying that you want to start out assuming that you haven’t found any of these (which is why you would set each variable you are using to track this information to false) and then you would turn the variable to true once you find it in the string.

Thank you! This helped a lot. I am getting closer but I still confused about creating a boolean variable for each and setting each to false

// Check that a password has at least one lowercase letter, uppercase letter, number and symbol
// Practice iterating through a string
// Practice using the ctype library

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

bool valid(string password);

int main(void)
{
    string password = get_string("Enter your password: ");
    if (valid(password))
    {
        printf("Your password is valid!\n");
    }
    else
    {
        printf("Your password needs at least one uppercase letter, lowercase letter, number and symbol\n");
    }
}

// TODO: Complete the Boolean function below
bool valid(string password)
{
   for (int i = 0; i < strlen(password); i++)
   {
        if (password[i] >= 'a' && password[i] <= 'z')
        {
            return true;
        }
        if (password[i] >= 'A' && password[i] <= 'Z')
        {
            return true;
        }
        if (password[i] >= '0' && password[i] <= '9')
        {
            return true;
        }
        if (password[i] >= '!' && password[i] <= '/')
        {
            return true;
        }
   }
   return false;
}

Do you know how to initialize a variable? For example, if you wanted to create a variable named myVariable which is a int and set it to the value 10?

There are four things you need to check that the password includes:

  • uppercase letter
  • lowercase letter
  • number
  • symbol

For each one of those, either the password includes it or it doesn’t. In other words, either it is true or false. So you’ll need a variable for each one to hold whether it is true or false.

yes, would be int myVariable = 10;

So for the other ones I would do the same thing string uppercase_letter = false;

You are close. The implementation details are telling you to use a boolean type, not a string type. Have you covered booleans yet? If not, then I would use an int and set the value to 0 for false and 1 for true. I suppose you could use the strings “true” and “false”, but for booleans I think it is much more accepted practice to either use the boolean type or 0/1.

Yes we have, that make perfect sense. I was actually thinking that but I went with false because the directions spelt out false. But it would be int uppercase_letter = 0

Boolean types have two values, either true or false. These aren’t strings. You can’t set a string type to true or false, but you can set it to the strings “true” or “false”. It’s just makes much more sense to use the boolean type if you are truly dealing with a boolean value.

// Check that a password has at least one lowercase letter, uppercase letter, number and symbol
// Practice iterating through a string
// Practice using the ctype library

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

bool valid(string password);

int main(void)
{
    string password = get_string("Enter your password: ");
    if (valid(password))
    {
        printf("Your password is valid!\n");
    }
    else
    {
        printf("Your password needs at least one uppercase letter, lowercase letter, number and symbol\n");
    }
}

// TODO: Complete the Boolean function below
bool valid(string password)
{
    int uppercase_letter = 0;
    int lowercase_letter = 0;
    int number = 0;
    int symbol = 0;

   for (int i = 0; i < strlen(password); i++)
   {
        if (password[i] >= 'a' && password[i] <= 'z')
        {
            return 1;
        }
        if (password[i] >= 'A' && password[i] <= 'Z')
        {
            return 1;
        }
        if (password[i] >= '0' && password[i] <= '9')
        {
            return 1;
        }
        if (password[i] >= '!' && password[i] <= '/')
        {
            return 1;
        }
        return true; 
   }
   return false;
}

I am trying to get the for loop to understand that if all of these if statements are true then the password is valid, anything else is invalid. Right now any password I input is returning valid even if it doesn’t meet the requirements

What does a return statement do?

The if statement has a condition that you’re evaluating, then you need to decide what is done if that condition is true or false, I am putting the return statement too early causing it to go back to the top? Essentially the return statement is ending the execution of the if statement right?

Instead I should be saying printf("Your password is valid!\n"); ? And at the end say return true to indicate that if all these are true the password is valid?

I think you are getting closer. A return statement immediately stops the execution of a function and causes the function to return a value. In your valid function, you are returning a 1 as soon as one of the criteria are met. But what about the other criteria? You shouldn’t return a value until you know that all four criteria are met. That’s where those four variables you defined at the beginning of the function come into play.

// Check that a password has at least one lowercase letter, uppercase letter, number and symbol
// Practice iterating through a string
// Practice using the ctype library

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

bool valid(string password);

int main(void)
{
    string password = get_string("Enter your password: ");
    if (valid(password))
    {
        printf("Your password is valid!\n");
    }
    else
    {
        printf("Your password needs at least one uppercase letter, lowercase letter, number and symbol\n");
    }
}

// TODO: Complete the Boolean function below
bool valid(string password)
{
    int uppercase_letter = 0;
    int lowercase_letter = 0;
    int number = 0;
    int symbol = 0;

   for (int i = 0; i < strlen(password); i++)
   {
        if (password[i] >= 'a' && password[i] <= 'z')
        {
            lowercase_letter += 1;
        }
        if (password[i] >= 'A' && password[i] <= 'Z')
        {
            uppercase_letter += 1;
        }
        if (password[i] >= '0' && password[i] <= '9')
        {
            number += 1;
        }
        if (password[i] >= '!' && password[i] <= '/')
        {
            symbol += 1;
        }
        return true;
   }
   return false;
}

Thought this logic would but I must be doing something wrong because every password I input returns as valid

Remember, a return statement will make the function exit immediately and return a value. Since you have this statement inside of the for loop that means that the for loop is only going to iterate once (i.e. check the first character in the string) and then always return true. That’s why every password you check is showing as valid.

You need to put the logic that decides whether the password is true or false outside of the for loop because you can’t make that decision until you have gone through all of the letters in the string.

Also, you don’t need to add 1 each time a letter meets one of the criteria. You can just set the variable to 1 and that’s it. Then each variable is either false (0) or true (1). You don’t care how many times it is true.

// Check that a password has at least one lowercase letter, uppercase letter, number and symbol
// Practice iterating through a string
// Practice using the ctype library

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

bool valid(string password);

int main(void)
{
    string password = get_string("Enter your password: ");
    if (valid(password))
    {
        printf("Your password is valid!\n");
    }
    else
    {
        printf("Your password needs at least one uppercase letter, lowercase letter, number and symbol\n");
    }
}

// TODO: Complete the Boolean function below
bool valid(string password)
{
    int uppercase_letter = 0;
    int lowercase_letter = 0;
    int number = 0;
    int symbol = 0;

   for (int i = 0; i < strlen(password); i++)
   {
        if (password[i] >= 'a' && password[i] <= 'z')
        {
            lowercase_letter = 1;
        }
        if (password[i] >= 'A' && password[i] <= 'Z')
        {
            uppercase_letter = 1;
        }
        if (password[i] >= '0' && password[i] <= '9')
        {
            number = 1;
        }
        if (password[i] >= '!' && password[i] <= '/')
        {
            symbol = 1;
        }
   }
    if (lowercase_letter == 1 && uppercase_letter == 1 && number == 1 && symbol == 1)
    {
        return true; 
    }
   return false;
}

Thank you so much! I believe this works, I will check to see if it passes