Thread: Two problems with std::cin.getline()

  1. #1
    Registered User
    Join Date
    Jun 2004
    Posts
    124

    Two problems with std::cin.getline()

    I am having two issues with the std::cin.getline() function.

    Here is the relevant portion of my code:
    Code:
    std::cout << "Enter administrator password to unlock the database file" << std::endl;
    		
    while (!datafileVerified)
    {
        std::cin.getline(adminPassword, MAX_PASSWORD_LENGTH+1);
        passLength = std::cin.gcount() - 1;
        datafileVerified = verifyDatafile(adminPassword);
        if (!datafileVerified) { std::cout << "Incorrect admin password, try again" << std::endl; }
    }
    MAX_PASSWORD_LENGTH is 16 so cin.getline() should accept 17 characters (16 + NULL).

    First question:
    When I input 16 characters or fewer cin.gcount() - 1 returns the correct number of characters (I don't want the NULL counted, hence the -1). So if I put in 16 characters gcount() - 1 gives returns 16. If; however, I input 17+ characters then gcount() -1 always returns 15. I put in more and it gives me less. What gives?

    Second question:
    When I put in an incorrect password, the call to verifyDatafile will fail and return 0. The variable datafileVerified is initialized to 0. If I input 16 or fewer characters this block of code works as expected, if the password is incorrect it continues to prompt the user for the password again. If; however, I input 17+ characters it skips the cin.getline() every time it goes through the loop and simply loops infinitely! What gives?

    Thanks.

  2. #2
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Why don't you just use the getline() function and use std::string instead anyway?

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If you give getline 17 as a parameter, it will not read more than 16 characters in. And, as you correctly noticed, 16-1 equals 15.

    Also, if you type in extra characters, the characters not read in will still be there in the next iteration of the while loop. (You shouldn't see an infinite loop -- 16 to 31 characters should give you two iterations, 32 to 47 three, etc.)

  4. #4
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    I am not trying to say something discouraging, but given how you seem to have a lot of confusion about char buffers why not just use std::strings? Its more robust for this type of application anyway. Unless 16 is a magic number for some sort of encryption you have implemented (perhaps you have colaberated with Kevin and his encryption technique that would require 5000+ years for a large amount of data to be decrypted).

  5. #5
    Registered User
    Join Date
    Jun 2004
    Posts
    124
    Quote Originally Posted by tabstop View Post
    If you give getline 17 as a parameter, it will not read more than 16 characters in. And, as you correctly noticed, 16-1 equals 15.

    Also, if you type in extra characters, the characters not read in will still be there in the next iteration of the while loop. (You shouldn't see an infinite loop -- 16 to 31 characters should give you two iterations, 32 to 47 three, etc.)
    Ok, I had an inkling that might be the issue. Is there anyway to flush stdin to get rid of any extra input?

  6. #6
    Registered User
    Join Date
    Jun 2004
    Posts
    124
    Quote Originally Posted by master5001 View Post
    I am not trying to say something discouraging, but given how you seem to have a lot of confusion about char buffers why not just use std::strings? Its more robust for this type of application anyway. Unless 16 is a magic number for some sort of encryption you have implemented (perhaps you have colaberated with Kevin and his encryption technique that would require 5000+ years for a large amount of data to be decrypted).
    I've already dedicated too much time to this program to replace all my char buffers with std::string. I know how char buffers work. I was mainly hoping there was a way to discard extraneous input from stdin after a call to cin.getline().

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    cin.ignore()

  8. #8
    Registered User
    Join Date
    Jun 2004
    Posts
    124
    Quote Originally Posted by tabstop View Post
    cin.ignore()
    cin.ignore() asks for a number of characters to ignore. Is it safe to pass a huge number like INT_MAX to it?

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Wouldn't know why not. Be sure to use it only when you know there's extra input, though.

  10. #10
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Such things can always be tried, you know. Particularly when you ask a question that is somewhere between obvious and implementation specific.

  11. #11
    Registered User
    Join Date
    Jun 2004
    Posts
    124
    Quote Originally Posted by tabstop View Post
    Wouldn't know why not. Be sure to use it only when you know there's extra input, though.
    Er...I can never *know* there's going to be extra input. I mean...there has to be a way to accept input safely in C++. There has to be a way to allow for input into a buffer with a fixed upper bound that doesn't break when someone tries to overflow it. I mean...right? It has to exist! I thought cin.getline() was the answer. What should I use instead?

  12. #12
    Registered User
    Join Date
    Jun 2004
    Posts
    124
    Quote Originally Posted by master5001 View Post
    Such things can always be tried, you know. Particularly when you ask a question that is somewhere between obvious and implementation specific.
    The point of asking for help in a forum is to gain the benefit of peoples' experiences. I'm not going to input 2 million some odd characters to see if it breaks if someone else already knows the answer.

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You need to know whether the \n was found and discarded, so you want to use the input operation that doesn't actually discard the \n character. That input operation is "get". (Of course, this means that you have to discard the \n yourself, but hey.)

  14. #14
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    INT_MAX is not that large and in cases like these, if it works once, it works always.

    At any rate, yes, there is a way, call

    ignore(<big_number>, '\n');

    The default sequence delimiter is EOF, but you can use other things, as shown.

  15. #15
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Fair enough, max. I would think of it this way: is it a case of all your input is desireable except for the pesky new line at the end of each line? Is it always "pesky" and never "useful?" Sometimes there are instances where you may want to skip a character. Like a colon or a dash or whatever. So generally speaking, skipping all of them is fine unless your implmentation requires a character to only be skipped in a set interval.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. No clue how to make a code to solve problems!
    By ctnzn in forum C Programming
    Replies: 8
    Last Post: 10-16-2008, 02:59 AM
  2. C Pointers Problems
    By mhelal in forum C Programming
    Replies: 8
    Last Post: 01-10-2007, 06:35 AM
  3. Rendering problems (DirectX?)
    By OnionKnight in forum Tech Board
    Replies: 0
    Last Post: 08-17-2006, 12:17 PM
  4. contest problems on my site
    By DavidP in forum Contests Board
    Replies: 4
    Last Post: 01-10-2004, 09:19 PM
  5. DJGPP problems
    By stormswift in forum C Programming
    Replies: 2
    Last Post: 02-26-2002, 04:35 PM