Thread: Another big issue

  1. #1
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30

    Another big issue

    Basically, what I am required to do is get a number of passwords from the user, entering ! to quit. The password must be 6 or more characters in length, must have 1 upper case, one lower case and one number. For some reason, I can't get the character check to work. The program just freaks out and displays a bunch of characters. Can someone point me in the right direction???

    Attempt:

    Code:
    #include <iostream>
    #include <iomanip>
    
    
    char isDigit (char);
    char isUpper (char);
    char isLower (char);
    char ch;
    int error, valid, size;
    bool func1, func2, func3;
    
    
    using namespace std; 
    
    
    int main () 
    {
    	do
    	{
    		do
    		{
    		error = 0;
    		cout << "Enter password, ! at the beginning of the line to end" << endl;
    		cin.get( ch );
    		
    			for ( ch != 0; ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) ; ch++ )
      			{
    				isDigit (ch);
    				isUpper (ch);
    				islower (ch);
    				size ++;
    				cout << ch << endl;
    			}
    			
    			while ( size = 0 or size >= 5 )
    			{
    				cout << "invalid password, not long enough" << endl;
    				error ++;
    			}		
    				
    		func1 = isDigit;
    		func2 = isUpper;
    		func3 = isLower;
    		
    		if (func1 = true)
    		{
    			if(func2 = true)
    			{
    				if (func3 = true)
    				{
    					cout << "Valid password";
    					valid++;
    				}
    			}
    		}
    		
    		if (func1 = false)
    		{
    			cout << "Invalid Password, need digits" << endl;
    			error++;
    		}
    		
    		if (func2 = false)
    		{
    			cout << "Invalid Password, need upper case letter" << endl;
    			error++;
    		}		
    		
    		if (func3 = false)
    		{
    			cout << "Invalid Password, need lower case letter" << endl;
    			error++;
    		}
    		
    		cout << "Number of valid passwords: " << valid << endl;
    		cout << "Number of invalid passwords: " << error << endl;
    				
    		}while (ch != '!');
    	}while (ch != '/n');
    }
    
    
    char isDigit( char ch )
    {
    	bool num;
    	
    	if (ch >= '0' && ch <= '9' )
    	{
    		num = true;
    		return num;
    	}
    	if (ch <= '0' && ch >= '9' )
    	{
    		num = false;
    		return num;
    	}
    }
    
    
    char isUpper( char ch )
    {
    	bool num;
    	
    	if (ch >= 65 && ch <= 90 )
    	{
    		num = true;
    		return num;
    	}
    	if (ch <= 65 && ch >= 90 )
    	{
    		num = false;
    		return num;
    	}
    }
    
    
    char isLower( char ch )
    {
    	bool num;
    	
    	if (ch >= 97 && ch <= 122 )
    	{
    		num = true;
    		return num;
    	}
    	if (ch <= 97 && ch >= 122 )
    	{
    		num = false;
    		return num;
    	}
    }
    EDIT: Also, I'm trying my best to do this without arrays again since we just learned it before spring break. Our teacher gave us the option to do it with them, but before they're required, I want to try them without.
    Last edited by albireo; 03-18-2014 at 02:03 PM.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Look at the following snippet:

    Code:
                while ( size = 0 or size >= 5 )
                {
                    cout << "invalid password, not long enough" << endl;
                    error ++;
                }
    There are several things wrong with the the code above. First since you are using the assignment operator= and therefore assigning the value of zero to size you will always enter this loop. Perhaps you meant to use the comparison operator==?

    The next major thing wrong with this snippet is that once you enter that loop there is no way to exit the loop.

    Next what exactly are you trying to accomplish in the following loop?
    Code:
                for ( ch != 0; ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) ; ch++ )
    Remember ch is a single character so why would you want to increment this single character? Also inside this loop you will never have a "digit" you will only have "letters", because anything else and the loop won't execute.

    You really should use more descriptive variable names for your funcX variables, perhaps something like haveDigit, haveUpper, haveLower.

    Jim

  3. #3
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30
    For the function names, that's something she made us name them. Literally copied and pasted the first line into the code.

    I changed the while loop, yeah sorry, I meant to put == I keep getting confused as to when to use = or ==, the same with ' or ". Lol.

    For the ch !=0 loop, I'm trying to make a loop that, for the first character, so long as it is a letter or number, goes through the three functions, returns true of false for each of the three functions, then moves onto the next character in the loop. I read somewhere that ch++ would do that somewhere in the loop, but I guess I was wrong. That's the jist of what I was wanting/hoping to do :/

    For the cout << ch; part, we are supposed to redisplay the "password" that we entered before. Once I switched the = to == and switched my for loop to a while loop, all I'm getting is a constant stream of the first character I enter, and it doesn't move on to the second character. Progress atleast

    Code:
    while ( ch != 0 and ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')))
    Essentially, what i'm trying to figure out, how do i structure this to make it do one character, then move to the second. If i can get this down, i guess the rest of the program is just structure issues.
    Last edited by albireo; 03-18-2014 at 02:23 PM.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    You need to re-read my first post. Once you enter that while() loop there is no way to exit.

    Also this next part is very important: ch is a single character, you seem to think it is an array of characters.

    I recommend you first get the entire pass word into a string before you try to check that the password is valid.


    Jim

  5. #5
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30
    Quote Originally Posted by jimblumberg View Post
    You need to re-read my first post. Once you enter that while() loop there is no way to exit.

    Also this next part is very important: ch is a single character, you seem to think it is an array of characters.

    I recommend you first get the entire pass word into a string before you try to check that the password is valid.


    Jim
    I believe I know what you're saying, but I'm confused on how I would do it

    Cin.get(ch) was something our teacher gave to us on the assignment and said it would help. She didn't go well into explaining it however, other than it would be able to pick apart the different characters of a sting

  6. #6
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30
    Not sure why, but its no longer allowing me to edit my posts D: ... sorry for the double post.

    Basically, I dont know how do make a command to pick apart my string character by character to run these tests. Is there a way out there to do this? Not assuming im using an array. I'm trying not to.

  7. #7
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30
    Final post until a reply comes in... Again, sorry for the triple post, but since I logged off, it no longer allows me to edit my post...

    I rearranged my code to where I am now actually getting functional code. My issue is two things....

    First, while each of my functions do work, they only work for the first letter of ch... These are not continuing for the rest of the letters. I resulted to finally simply using an array for these things... In our instructions we are not allowed to use isupper, islower, or isdigit in our code. We are supposed to basically code our own versions of these codes. Nothing is seemingly happening...

    Code:
    #include <iostream>
    #include <iomanip>
    #include <cstdlib>
    #include <string.h>
    
    
    bool isDigit (char []);
    bool isUpper (char []);
    bool isLower (char []);
    const int size = 100;
    int error, valid;
    
    
    using namespace std; 
    
    
    int main () 
    {
    	char ch[size];
    	int sum;
    	cout << "Enter password, ! at the beginning of the line to end" << endl;
    	cin.get(ch, size);
    	sum=isDigit(ch)+isUpper(ch)+isLower(ch);
    	cout << ch << endl;
    		while (sum < 3)
    			{
    				if(!isDigit(ch))
    				{
    					cout << "invalid password, missing digit" <<endl;
    					error++;
    				}
    				if(!isUpper(ch))
    				{
    					cout << "invalid password, missing uppercase letter" <<endl;
    					error++;
    				}
    				if(!isLower(ch))
    				{
    					cout << "invalid password, missing lowercase letter" <<endl;
    					error++;		
    				}
    			cin.getline(ch, size);
    			sum=isDigit(ch)+isUpper(ch)+isLower(ch);	
    			}
    			while (sum = 0)
    			{
    			cout << "Valid password";
    			valid++;
    			}
    	return 0;
    }
    
    
    bool isDigit( char ch [])
    {
    	for ( int count = 0; count < size; count++)
    	{
        if (ch [count] >= '0' && ch[count] <= '9' )
    	return true;
      	else return false;
      	}
    }
     
     
    bool isUpper( char ch [] )
    {
    	for ( int count = 0; count < size; count++)
    	{
        if (ch [count] >= 'A' && ch [count] <= 'Z' )
    	return true;
    	else return false;
    	}
    }
     
     
    bool isLower( char ch [])
    {
    	for ( int count = 0; count < size; count++)
    	{
        if (ch [count] >= 'a' && ch [count] <= 'z' )
    	return true;
    	else return false;
    	}
    }
    God bless anyone who can help out... I plan on going back and entering in the while loops for the ! character to end and the /n character to end. There is a secondary issue however. Any time I write

    Code:
    while (ch != '!')
    or the same thing for /n... I get some sort of converting error. Is there any way to do this in a while/do..while loop so that I can force this to end when I type "!" since ch is now an array???

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Let's examine this function:
    Code:
    bool isDigit( char ch [])
    {
        for ( int count = 0; count < size; count++)
        {
        if (ch [count] >= '0' && ch[count] <= '9' )
        return true;
        else return false;
        }
    }
    Suppose we call the above function like this:
    Code:
    char text[] = "123?";
    if (isDigit(text))
    {
        std::cout << "only digits here!" << std::endl;
    }
    else
    {
        std::cout << "contaminated by a non-digit" << std::endl;
    }
    So, ch in isDigit points to the first character of text. count = 0, and we start the loop body. ch[0] == '1', '1' >= '0' is true and '1' <= '9' is true, so we return true. Therefore, "only digits here!" is printed.

    Obviously, this is wrong: there is a '?' in text, but we never get to check it because as soon as we find that the first character is a digit, we return. You need to fix this. A similiar fix needs to be applied for isUpper and isLower.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30
    Did you mean something like this?? I think I missunderstood.

    Code:
    int main () 
    {
    	char ch[size];
    	int sum;
    	cout << "Enter password, ! at the beginning of the line to end" << endl;
    	cin.get(ch, size);
    	cout << ch << endl;
    	sum = a+b+c;
    		while (sum <= 3)
    			{
    				char num [] = "1234567890";
    				char lower[] = "abcdefghijklmnopqrstuvwxyz";
    				char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    				if(isDigit(num))
    				{
    					a = isDigit(ch);
    				}
    				else
    				{
    					cout << "Invalid password, missing digit" << endl;
    				}
    				if(isUpper(upper))
    				{
    					b = isUpper(ch);
    				}
    				else
    				{
    					cout << "invalid password, missing uppercase letter" <<endl;
    					error++;
    				}
    				if(isLower(lower))
    				{
    					c = isLower(ch);
    				}
    				else
    				{
    					cout << "invalid password, missing lowercase letter" <<endl;
    					error++;
    				}
    			cin.getline(ch, size);
    			}
    			while (sum = 0)
    			{
    			cout << "Valid password" << endl;
    			valid++;
    			}

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    No, I am saying your implementation of isDigit is wrong. If the string is not empty, then no matter how long is the string, you only ever check the first character and return true or false based on that. If the string is empty, then you don't return anything, which is also a mistake.

    Furthermore, since you did not pass the string length, you should not loop based on size (alone). size is a constant that states the maximum number of characters in the null terminated string (including the null character). Thus, you should loop until you reach a null character, not loop until size.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30
    Oh, I see what you're saying... That's what I was wondering initially was how you base the loops in the functions around the letters in ch rather than just increment size. Right now, as I have the program, if I type in "what" as my password, each of the functions only check if 'w' is a uppercase, lowercase or number, and 'h', 'a', and 't' are left out of the equation. My teacher never really gave us any clues on how to keep going and check each of the next characters, and I have absolutely no idea how to do this.

    EDIT: and also now... for some reason, it's not running my loop twice when i run the program O_o

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Well, you want to check if all the characters in the string are digits. So, start by assuming that this to be true:
    Code:
    bool isDigit(const char str[])
    {
        return true;
    }
    Obviously, if the first character is a non-digit, this will fail. So, check that your assumption holds for the first character, returning false if it does not:
    Code:
    bool isDigit(const char str[])
    {
        if (!(str[0] >= '0' && str[0] <= '9'))
        {
            return false;
        }
        return true;
    }
    But now, if the second character is a non-digit, this still isn't going to work. You need to check your assumption for every character. So, write a loop to check that your assumption holds for each character, returning false if your assumption does not hold:
    Code:
    bool isDigit(const char str[])
    {
        for (int count = 0; str[count] != '\0'; ++count)
        {
            if (!(str[count] >= '0' && str[count] <= '9'))
            {
                return false;
            }
        }
        return true;
    }
    Note that I have taken the liberty of changing the parameter to be a pointer to const char instead, and renamed it to str since ch would be misleading.

    For this to work though, you really need a null terminated string. If I remember correctly, this would not null terminate to give you a null terminated string:
    Code:
    cin.get(ch, size);
    I suggest using getline instead of get.

    By the way, have you been taught about the <string> standard header and the use of std::string objects? If so, then you should use that instead of null terminated strings.

    Oh, and do not use global variables. Your size variable is okay since it is declared const, but you should give it a more descriptive name, e.g., password_max_size.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30
    Quote Originally Posted by laserlight View Post
    Well, you want to check if all the characters in the string are digits. So, start by assuming that this to be true:
    Code:
    bool isDigit(const char str[])
    {
        return true;
    }
    Obviously, if the first character is a non-digit, this will fail. So, check that your assumption holds for the first character, returning false if it does not:
    Code:
    bool isDigit(const char str[])
    {
        if (!(str[0] >= '0' && str[0] <= '9'))
        {
            return false;
        }
        return true;
    }
    But now, if the second character is a non-digit, this still isn't going to work. You need to check your assumption for every character. So, write a loop to check that your assumption holds for each character, returning false if your assumption does not hold:
    Code:
    bool isDigit(const char str[])
    {
        for (int count = 0; str[count] != '\0'; ++count)
        {
            if (!(str[count] >= '0' && str[count] <= '9'))
            {
                return false;
            }
        }
        return true;
    }
    Note that I have taken the liberty of changing the parameter to be a pointer to const char instead, and renamed it to str since ch would be misleading.

    For this to work though, you really need a null terminated string. If I remember correctly, this would not null terminate to give you a null terminated string:
    Code:
    cin.get(ch, size);
    I suggest using getline instead of get.

    By the way, have you been taught about the <string> standard header and the use of std::string objects? If so, then you should use that instead of null terminated strings.

    Oh, and do not use global variables. Your size variable is okay since it is declared const, but you should give it a more descriptive name, e.g., password_max_size.
    I see, arrays are so confusing to me right now. I understand how to fit it in my code, but I'm still not fully understanding the consept of how this
    Code:
         for (int count = 0; str[count] != '\0'; ++count)
    made the code somehow check the entire string inside the array instead of just the first letter. What made it change? Oh, and what does the '\0' do exactly?

    She hasn't taught us about the std::string form yet. I tried playing around with it a little bit earlier, and it came back with a few errors in my code that I didn't quite understand. We just started touching on arrays today and we barely made a dent. She explained a little bit about how they work, and I had to google a little bit more about the internal workings of them and whatnot. I'm still not completely 100% on everything, but I feel a little bit better than I did earlier today :P Thank you for all your help btw!

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    An array is a set of elements, where you can access each element in the set with an index. The index start from 0 and goes to the length (i.e. the number of elements in the set) - 1.
    C strings (the strings you are working with) are a set of characters where the last characters is always '\0'. This is characters that marks the end of the string. If there is no '\0' at the end of the array of characters, then it is not a C string. But you are working with C strings here, so we know there must be such a character.
    Hence, by checking every element in the set, we can find the end of the string by looking for the '\0'.
    Then we simply use indexes to examine each character in the set.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User albireo's Avatar
    Join Date
    Mar 2014
    Posts
    30
    Thank you so much I have one final question. How would you have done this if you hadn't used an array? So that I know for test purposes? I really appreciate all of your guys' help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. bandwidth issue / network issue with wireless device communication
    By vlrk in forum Networking/Device Communication
    Replies: 0
    Last Post: 07-05-2010, 11:52 PM
  2. new issue
    By hiddenprophecy in forum C Programming
    Replies: 3
    Last Post: 04-15-2009, 05:59 PM
  3. DLL issue
    By crazybucky in forum C++ Programming
    Replies: 1
    Last Post: 04-02-2008, 12:12 PM
  4. What is the issue?
    By al_engler in forum C Programming
    Replies: 2
    Last Post: 12-19-2006, 01:54 PM
  5. PHP/IIS Issue
    By ChadJohnson in forum Tech Board
    Replies: 7
    Last Post: 09-25-2005, 11:02 AM