Need Help Chili

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
User avatar
Alacaster
Posts: 81
Joined: October 16th, 2016, 5:08 pm
Location: Spokane, WA

Need Help Chili

Post by Alacaster » February 3rd, 2017, 6:15 am

You said to ask for help if i need it in the isupper challenge video so here i am.

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>

int main()
{
    char passwd[20];

    int x = 1;
    bool good[4];
    bool GreatPass = false;
    do{
    printf("Type a password \n");
    scanf(" %s", &passwd);
        do{
            if( isalpha(passwd[x]) )
                {
                    if( isupper(passwd[x]) )
                        { good[1] = true; break;}
                        else{good[2] = true;}
                }

            if( isdigit(passwd[x]) )
            {
                good[3] = true;
            }

        x++;

        }while(x <= 18);

        if( isdigit(passwd[8]) || isalpha(passwd[8]))
        {
            good[4] = true;
        }

        if(good[1] != true){printf("You need an uppercase letter in your password. \n");};
        if(good[2] != true){printf("You need a lowercase letter in your password. \n");};
        if(good[1] != true && good[2] != true){printf("You need a letter in your password. \n");};
        if(good[3] != true){printf("You need a number in your password. \n");};
        if(good[4] != true){printf("You need a longer password. \n");};
        if(good[1] == true && good[2] == true && good[3] == true && good[4] == true){printf("Great Password"); GreatPass = true;}
    }while(GreatPass != true);
}
I have no idea whats wrong
You can't be betrayed if you don't have any friends.
Why live? Cause why not.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Need Help Chili

Post by albinopapa » February 3rd, 2017, 7:14 am

There are several mistakes made in this code.

Code: Select all

int main()
{
    // You should really initialize your variables, even arrays
    // You can initialize the array to 0's by adding {} after the [] and before the ; in C++ or = {}; in C
    char passwd[20]{};

    // Array indexes start at 0, so this counter variable should start at 0
    int x = 0;

    // Uninitialized array of bools, if you initialize them to 0's as shown above, their default value is false
    // Also, you access this array with numbers 1-4, but the indexes only go from 0-3;
    bool good[4]{};
    bool GreatPass = false;
    do{
    printf("Type a password \n");
    scanf(" %s", &passwd);
        do{
            if( isalpha(passwd[x]) )
                {
                    if( isupper(passwd[x]) )
                        // This break here skips the rest of the string if the first letter is UPPER
                        { good[1] = true; /*break;*/}
                        else{good[2] = true;}
                }

            if( isdigit(passwd[x]) )
            {
                good[3] = true;
            }

        // Here you increase x, but you never reset it back to 0 if the user gives an invalid password
	// Same goes for the 'bool good' array

        x++;

        // You check from 1 to 18, what happens if the string is less than that?
        // You can use the strlen() function to get the length of the string the user supplied.  
        // It returns the string length only, and doesn't include the null terminator
        }while(x <= 18);

        // If the password can only be 8 or more alphanumeric characters,
        // this will fail if the string is only 8 characters because the eighth index would be the NULL terminator
        if( isdigit(passwd[8]) || isalpha(passwd[8]))
        {
            good[4] = true;
        }

        if(good[1] != true){printf("You need an uppercase letter in your password. \n");};
        if(good[2] != true){printf("You need a lowercase letter in your password. \n");};
        // I think this should be || not &&.  
        if(good[1] != true && good[2] != true){printf("You need a letter in your password. \n");};
        if(good[3] != true){printf("You need a number in your password. \n");};
        if(good[4] != true){printf("You need a longer password. \n");};
        if(good[1] == true && good[2] == true && good[3] == true && good[4] == true){printf("Great Password"); GreatPass = true;}
    }while(GreatPass != true);
}
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

egizz983
Posts: 311
Joined: August 27th, 2016, 12:30 pm

Re: Need Help Chili

Post by egizz983 » February 3rd, 2017, 3:46 pm

when asking questions u should also mention what kind of problem you are facing : error code , something not working and ect.

User avatar
Alacaster
Posts: 81
Joined: October 16th, 2016, 5:08 pm
Location: Spokane, WA

Re: Need Help Chili

Post by Alacaster » February 5th, 2017, 6:08 am

Thank you so much. I still don't know what "{}" does after a variable declaration.
I assume it sets all the variables in an array to a certain value.

Code: Select all

int main()
{
    //It it gave an error message here unless i used NULL
    char passwd[20]={"\0"};

    int x = 0;

    bool good[4]={false}; // Here i was just confused. Does {} set all variables in an array to a set value?
    bool GreatPass = false;

    do{
    printf("Type a password: \t");
    scanf(" %s", &passwd);
    printf("\n");
        do{
            if( isalpha(passwd[x]) )
                {
                    if( isupper(passwd[x]) )
                        // This break here skips the rest of the string if the first letter is UPPER
                        // Oh . . . Opps . . 
                        { good[1] = true; /*break;*/}
                        else{good[2] = true;}
                }

            if( isdigit(passwd[x]) )
            {
                good[3] = true;
            }

        x++;

        // Iff the string was less than 18 then i assumed that it would just waste time and not do anything.
        // No where in this loop does it have the option to set any Boolean to false.
        }while(x <= strlen(passwd));

        // Thanks!
        if( isdigit(passwd[7]) || isalpha(passwd[7]))
        {
            good[4] = true;
        }
        
        // Thanks again
        x = 0; // I reset x

        //I added a break statement so it didn't print out useless information.
        if(good[0] != true && good[2] != true){printf("You need a letter in your password. \n"); break;};
        if(good[0] != true){printf("You need an uppercase letter in your password. \n");};
        if(good[1] != true){printf("You need a lowercase letter in your password. \n");};
        if(good[2] != true){printf("You need a number in your password. \n");};
        if(good[3] != true){printf("You need a longer password. \n");};
        if(good[0] == true && good[2] == true && good[3] == true && good[4] == true){printf("Great Password \n"); GreatPass = true;}
    }while(GreatPass != true);
}
You can't be betrayed if you don't have any friends.
Why live? Cause why not.

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Need Help Chili

Post by chili » February 5th, 2017, 7:19 am

yeah, a single value in the {} will init all elements with that value.
multiple values will init individual elements starting from 0.
Chili

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Need Help Chili

Post by albinopapa » February 5th, 2017, 8:21 am

//It it gave an error message here unless i used NULL
char passwd[20]={"\0"};

int x = 0;

bool good[4]={false}; // Here i was just confused. Does {} set all variables in an array to a set value?
bool GreatPass = false;
Are you coding in C or C++?
An empty set of braces just initializes all elements of an array/struct/class/union to 0.

In C you have to do
int myArray[20] = {0}; // or apparently something similar as you did {"\0"} and {false}

In C++ you can do
int myArray[20]{};
or
int myArray[20] = {};
// Iff the string was less than 18 then i assumed that it would just waste time and not do anything.
// No where in this loop does it have the option to set any Boolean to false.
}while(x <= strlen(passwd));
Yeah, it would just waste time. Btw, you can just put strlen(passwd) in a var before the second do/while stuff since it doesn't change during the inner do loop. That would also help out in this part

Code: Select all

        if( isdigit(passwd[7]) || isalpha(passwd[7]))
        {
            good[4] = true;
        }
You could just do:

Code: Select all

        if( lengthOfString >= stringMin )
        {
            good[4] = true;
        }
Of course, you'd also have to create a var named stringMin and set it to 8 or whatever.

The inner do/while loop is a good case for a for loop since you can get the length of a string and know how many iterations to do, it would also take care of incrementing and resetting the X variable.

const int lengthOfString = strlen(passwd);
for(int x = 0; x < lengthOfString; x += 1)
{
// do your checks for isdigit and isalpha
}
//I added a break statement so it didn't print out useless information.
if(good[0] != true && good[2] != true){printf("You need a letter in your password. \n"); break;};
I would consider using continue instead of break. Break will break out of the do loop so it never asks for the password again, whereas I think you are wanting it to ask again and it still skips all the unnecessary printf statements.

Here's how it all would look

Code: Select all

int main()
{
	// Initialize arrays to 0's
	char passwd[ 20 ] = { 0 };
	bool good[ 4 ] = { 0 };

	// It's a good idea to use the sizeof operator.  
	// I didn't know if bool was a typedef for int or _Bool
	const int goodSize = sizeof( good );
	bool GreatPass = false;

	// Use variables instead of magic numbers when possible.  
	// Makes changing and testing a lot easier
	const int minStringLength = 8;

	do
	{
		// Zero all elements in the good array each failed password attempt
		memset( good, 0, goodSize );
		printf( "Type a password: \t" );
		scanf( " %s", &passwd );
		printf( "\n" );

		// Cache the length of the string for multiple uses
		const int lengthOfString = strlen( passwd );

		// You can use a for loop to track and increment the index 
		for( int i = 0; i < lengthOfString; i += 1 )
		{
			if( isalpha( passwd[ i ] ) )
			{
				if( isupper( passwd[ i ] ) )
				{
					good[ 0 ] = true;
				}
				else
				{
					good[ 1 ] = true;
				}				
			}
			// If isalpha, it can't be a digit, so else if
			else if( isdigit( passwd[ i ] ) )
			{
				good[ 2 ] = true;
			}
		}

		// Now you can just check the length of the string using the cached version
		if( lengthOfString >= minStringLength )
		{
			good[ 3 ] = true;
		}

		if( !good[ 0 ] && !good[ 1 ] ) 
		{ 
			printf( "You need a letter in your password. \n" ); 
			// Use continue to skip the rest of the printf statements,
			// but still loop back and ask for a different password
			continue; 
		}
		if( !good[ 0 ] ) 
		{ 
			printf( "You need an uppercase letter in your password. \n" ); 
		}
		if( !good[ 1 ] ) 
		{ 
			printf( "You need a lowercase letter in your password. \n" ); 
		}
		if( !good[ 2 ] ) 
		{ 
			printf( "You need a number in your password. \n" ); 
		}
		if( !good[ 3 ] ) 
		{ 
			printf( "You need a longer password. \n" ); 
		}

		// Assign bool values directly by logical and (&&) or, bitwise and (&)
		// GreatPass = good[ 0 ] & good[ 1 ] & good[ 2 ] & good[ 3 ];
		// Saves you from having to write the long if condition statement
		GreatPass = good[ 0 ] && good[ 1 ] && good[ 2 ] && good[ 3 ];
	} while( GreatPass != true );
}
I still notice a few mistakes in your update, like accessing the elements past the size of the good array, remember, the first index starts at 0 and goes to size -1. If size = 4, then the indices are 0,1,2,3 not 1,2,3,4.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply