Forrest Gump
Forrest Gump

Reputation: 81

issues with getline() and input stream

Code

#include<iostream>
int main()
{
    char s[20];
    char ch;
    
    std::cin.getline(s,10);
    std::cout<<"x"<<s<<"x"<<"\n";
    
    std::cin>>ch;
    std::cout<<"x"<<ch<<"x";
    
    std::cin>>ch;
    std::cout<<"x"<<ch<<"x";
    
    std::cin>>ch;
    std::cout<<"x"<<ch<<"x";
}

Output-1

bonaparte    // I entered these 9 characters as input
xbonapartex
a            //  input
xax
b            // input
xbx
c            // input
xcx

Output-2

bonaparte2    // I entered these 10 characters as input
xbonapartex
x x
x x
x x

I just entered one extra letter means total 10 char through keyboard bonaparte2 compared to 1st output.

According to me getline is going to extract 9 characters and add '\0' and store in string s. So stream remains with characters 2 and \n. so first cin>>ch should take 2 and print x2x.

Now 2nd cin>>ch should ignores \n as it is leading whitespace character but none of this is happening. Program is not asking from input from keyboard.

Upvotes: 2

Views: 254

Answers (2)

Ted Lyngmo
Ted Lyngmo

Reputation: 117658

In Output-2, std::cin.getline(s,10); fails (because it can't read a complete line). It then sets the stream in a failed state and all subsequent extractions will also fail (unless you clear() the stream).

if(not std::cin.getline(s, 10)) { // an empty string is considered ok
    if(std::cin.eof()) {
        std::cout << "end of file / input closed\n";
        return 1;
    }
    if(std::cin.bad()) {
        std::cout << "a non-recoverable error has occurred\n";
        return 1;
    }
    // failbit
    std::cout << "Too long string entered\n";
    std::cin.clear();
}

If you don't want the stream to be set in a failed state when a newline is not found within the first 9 characters read, you can use the below instead. Note that it may still set eofbit or failbit for reasons illustrated below:

if(not std::cin.get(s, 10)) {   // an empty string sets failbit
    if(std::cin.eof()) {
        std::cout << "end of file / input closed\n";
        return 1;
    }
    if(std::cin.bad()) {
        std::cout << "a non-recoverable error has occurred\n";
        return 1;
    }
    // failbit
    std::cout << "No string entered\n";
    std::cin.clear();
}

Upvotes: 1

silverfox
silverfox

Reputation: 1662

In std::cin.getline(s,10);, as the input is bigger than stream_size provided, istream::getline sets the stream into a fail state, and that prevents further input.

It can easily be fixed with std::cin.clear(). Using std::string to store the input and let it handle the length will also be an alternative.

Related :

Upvotes: 2

Related Questions