As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/
Options

Dipshit-level programming help needed, again! (C++)

Speed RacerSpeed Racer Scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratchscritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratchRegistered User regular
edited May 2011 in Help / Advice Forum
Hopefully you guys can be as helpful and fast as you were last time I asked for help!

So, I'm supposed to make a program that prompts the user for a username and password. It then checks the password string, and if it's under five characters or contains a space, makes them enter a different. Then it stores them both in a different string.

I have been trying to make the password verification thing for hours now and it's like I'm just slamming my dick in a door over and over again. Here's the function I have right now:
string getPassword ()
{ string pass;
int check = 0;

cout << "\n Please enter a password. password must have \n"
<< " at least five characters and may contain no \n"
<< " spaces.\n\n ";

getline(cin, pass);


do
{

getline(cin, pass);

if (pass.length() < 5)
{
cout << "\n\n The password you entered is invalid.\n"
<<" Please try again.\n\n ";
}

else
{
for (int i = 0; i < pass.length(); i++)
{
if (pass == ' ')
{
cout << "\n\n The password you entered is invalid.\n"
<<" Please try again.\n\n ";

}
else
{
if (i == pass.length())
{
return pass;
}
}
}
}
}
while (pass.length() <= 5);

To my eye I don't see why this shouldn't work. It does accurately catch passwords with spaces in them, but it doesn't return the pass variable to main when a valid password is entered. I can't figure it out.

Help would really be appreciated!

Speed Racer on

Posts

  • Options
    L Ron HowardL Ron Howard The duck MinnesotaRegistered User regular
    edited May 2011
    Why do you have two getline(cin,pass)'es?
    Also, don't you want to for(i=0;i<pass.length()-1;i++) ?
    And just to be nitpicky, you have an extra variable that you don't use.

    L Ron Howard on
  • Options
    Speed RacerSpeed Racer Scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratchRegistered User regular
    edited May 2011
    the extra variable was from when I was trying something that didn't work, forgot to delete it

    If I take out the getline(cin, pass) outside of the do while loop, then the loop executes and outputs the invalid password message without giving the user the opportunity to actually enter a password, I don't really get why

    Your suggestion for the for loop doesn't appear to have fixed any thing

    Speed Racer on
  • Options
    Sir Headless VIISir Headless VII Registered User regular
    edited May 2011
    What value for i are you getting at the end for a valid password? does it actaulyl match pass.length()?

    edit: the reason i ask is it is probably going to be 1 more than you think since you start counting sring positions at 0 and length at 1.

    Sir Headless VII on
    Steam - Backpack - Bnet: SirHeadless #1154
    7KEFduI.jpg
  • Options
    Speed RacerSpeed Racer Scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratch scritch scratchRegistered User regular
    edited May 2011
    Yeah, that's definitely part of it

    it's occurred to me that there's no reason to have the return statement in the loop and that that's probably at least part of my problem. It makes more sense to check for both possible errors, and if one of them exists, repeat the loop, and if neither does, end the loop and return pass to main.

    The problem I'm having now is figuring out some way to tell the do-while loop that one of the values for i in the for loop came back as a space.

    Speed Racer on
  • Options
    khainkhain Registered User regular
    edited May 2011
    Your program doesn't return the string becuase i never reaches pass.length due to the condition of your for loop. I would add an additional variable names success that is the condition for the while loop and starts as false, and then after the while loop return the string.

    edit: Is there a reason you aren't just debugging the code with break points? The answer to the questions you've asked in this thread could be solved by walking through your program a single time. This would also probably give you an explanation on why a single cin inside the while loop doesn't work though I think it should.
    edit2: Also can you not use the standard libraries cause there's a str function that allows you to search strings.

    khain on
  • Options
    L Ron HowardL Ron Howard The duck MinnesotaRegistered User regular
    edited May 2011
    if (pass == [whatever ascii is for space] ){
    break;
    }

    The thing I was mainly getting at, was, are you sure that pass.length() is returning the exact length of the string, and not length-1?


    There's a whole better way to do the loop, but I'm a bit tired right now and not thinking extremely clearly on it, which is why I pointed out the extra getline outside of the loop.

    L Ron Howard on
  • Options
    Sir Headless VIISir Headless VII Registered User regular
    edited May 2011
    The program will work if he changes if (i == pass.length()) to if (i == pass.length() - 1) won't it? It's been several years since I last used c++ but the logic seems ok.

    Sir Headless VII on
    Steam - Backpack - Bnet: SirHeadless #1154
    7KEFduI.jpg
  • Options
    BluefootBluefoot Registered User regular
    edited May 2011
    khain wrote: »
    Your program doesn't return the string becuase i never reaches pass.length due to the condition of your for loop. I would add an additional variable names success that is the condition for the while loop and starts as false, and then after the while loop return the string.

    edit: Is there a reason you aren't just debugging the code with break points? The answer to the questions you've asked in this thread could be solved by walking through your program a single time. This would also probably give you an explanation on why a single cin inside the while loop doesn't work though I think it should.
    edit2: Also can you not use the standard libraries cause there's a str function that allows you to search strings.

    For something like this you could even run through it yourself with pencil and paper. Just go line by line, keeping track of the values of all your variables, and you should run across your problem. Helps take some of the mystery out of it.

    Bluefoot on
  • Options
    GrobianGrobian What's on sale? Pliers!Registered User regular
    edited May 2011
    I think you are going at this the wrong way. It would help to structure the program more. The problem of course is solvable in a single function, but I think it's clearer if you separate the different things you have to do.

    The way I see it, you have two different tasks:
    1) prompting the user for a password until you get a valid one
    2) testing if a given string is a valid password

    I would put those things in two functions. That simplifies your "read" function to this pseudocode:
    - output prompt text
    - read user input
    - while userinput is no valid password:
    ---- output second prompt text
    ---- read user input
    - endwhile
    - return input string

    in real code this could be something like:
    string readPassword()
    {
       string password;
       cout << "\n Please enter a password. password must have at least five characters and may contain no spaces.\n\n ";
    
       getline(cin, password);
    
       while (testPassword(password) == false)
       {
          cout << "\n\n The password you entered is invalid. Please try again.\n\n ";
          getline(cin, password);
       }
    
       return password;
    }
    

    The second task is also very simple in pseudocode:
    - test string for length < 5
    - for each letter in the string:
    ---- test if letter is ' '
    - endfor

    Again the code:
    bool testPassword(string password)
    {
       // this function tests whether the parameter sting is a valid password
       // a valid password contains no spaces and has a length of at least 5
    
       if (password.length() < 5)
          return false;
    
       for (int i = 0; i < password.length(); i++)
       {
          if (password[i] == ' ')
             return false;
       }
    
       return true;
    }
    


    I think your holdup was defining a clear outer loop, because you had to test for two different things. You can of course break out of any loop with "return" or "break" but that makes the structure of the code more complicated and it's harder to see how you go through it.


    Note: there's lots of ways to solve this problem and I just presented my personal approach. Also I don't guarantee there are no errors in the code, I didn't test this and I also didn't think more than 5 minutes about it. You should at least take a hard look at all the numbers in the test function and what value you get from string.length() etc.

    Note2: You may have noticed that I renamed your String to password. I'm not an advocate of theseLongNamesThatManyCplusplusProgrammersUse, but that string is the most important thing in your code, so it should have a good name. Pass could e any number of things, but password makes the intention clear.
    I also inserted a short comment at the beginning of the test function to tell the reader what it does. I didn't even really notice I did it, until I pasted the code here, it's a force of habit for me now. It's a good idea to do that even before you write the code. It helps you get a clear understanding of what the function is supposed to do and if you ever need to look at that code again you'll be thankful. You don't need to put a comment on every line and if you have good function names you only need sparse commenting anyway (it's pretty clear from the name what readPassword is supposed to do) but in some places a comment is just necessary.

    Grobian on
  • Options
    acidlacedpenguinacidlacedpenguin Institutionalized Safe in jail.Registered User regular
    edited May 2011
    What Grobian said. Also if it's a really complicated function I'll usually put in comments the pseudocode of what I intend the function to do, that way if I start to forget what I'm doing I have a clear guide to follow. It also helps with peer review-- people can look at the comment and either "what kind of crack are you smoking, that's all wrong" or "that looks right, but in your code you zigged instead of zagged."

    acidlacedpenguin on
    GT: Acidboogie PSNid: AcidLacedPenguiN
Sign In or Register to comment.