Search code examples
c++cingetline

Why cin is not getting buffer data after using getline?


To this code:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>

using namespace std;

#define p(a) cout << "|" << a << "|" << endl
int main() {
    
    char a[100];
    char b[100];

    cin.getline(a, 4, '\n');

    cin >> b;

    p(a);
    p(b);
    
    return 0;
}

If my input is "1234"

1234

I have the next output:

|123|
||

but I know that with getline, I get three elements: "123" and it is sending to a variable adding to the end the \0 character. In the same way, the remain characters "4\n" is left in the buffer. Then Why in the next "cin>>" it is not copied to b variable?, Why b is null?


Solution

  • If std::istream::getline can't fit the whole line (and terminating null) into the given buffer, it sets an error flag and becomes unreadable until the error is cleared.

    std::istream::get's fourth overload is a better choice for this use-case as it doesn't raise a flag if the whole line is not consumed.

    Replace

    cin.getline(a, 4, '\n');
    

    with

    cin.get(a, 4, '\n');
    

    Unrelated Recommendation:

    After any IO transaction, test the state of the stream before proceeding so that youy know if it's worth proceeding as planned or if the transaction failed and you'll have to do something else (like clear the error and try it again). For example, you can

    if (cin)
    {
        // safe to act upon the values read
    }
    

    or, because almost all stream functions return the stream for easy chaining of IO,

    if (cin.get(a, 4, '\n'))
    {
        // safe to act upon the values read
    }
    

    Since I mentioned it, chaining is the magic that allows code like

    std::cin >> a >> b >> c;
    

    and with a test for successful reading of a, b, and c

    if (std::cin >> a >> b >> c)
    {
        // safe to do stuff with a, b, and c
    }