ALXGTV
ALXGTV

Reputation: 362

c++ How to fix std::cin bug or work around it

I'm using Apple LLVM 3.0 and apparently there is a bug with std::getline and cin.getline, which requires the user to push enter twice in order for the std::getline function to return control back to program. Take this sample code for example:

int main(int argc, const char * argv[]) {
    using namespace std;

    string str;

    cout << "Enter some text: ";
    getline(cin, str);

    cout << "\nYou Entered: " << str;

    return 0;
}

Result:

Enter some text: hello world

I press enter once and the program is still running and waiting for input. I have to push enter again in order for the program to stop asking for input and continue execution.

I've searched for answers and this is apparently a bug in libc++, a similar bug also present in MS VC++ 6.0 (I think).

I tried a workaround by implementing my own getline function using cin.get(char) and returns when it encounters a '\n' or '\r' character. Here is the code below:

std::istream& getline(std::istream &in, std::string &str) {
    char ch;

    str.clear();

    while (in.get(ch) && ch != '\n' && ch != '\r') {
        str += ch;
    }

    return in;
}

Unfortunately I still have the same problem as the first new line character is not returned by in.get hence the program once again hangs waiting for the user to push enter for the second time. Is there any workaround or solution to this problem without resorting to good old C-style fgets(stdin, buffer, bufsize).

Upvotes: 1

Views: 1421

Answers (2)

Marshall Clow
Marshall Clow

Reputation: 16660

I just tried this using the latest release of Xcode and Apple's LLVM, and couldn't reproduce this. (i.e, I only had to hit return once)

$ clang++ --version
Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

I built it like this:

$ clang++ -stdlib=libc++ so.cpp

Upvotes: 1

ALXGTV
ALXGTV

Reputation: 362

This is the only workaround I have found so far. Here's my own version of getline:

std::istream& getline(std::istream &in, std::string &str) {
    char chr;
    std::ios_base::fmtflags flags = in.flags();

    str.clear();

    while ((in >> std::noskipws >> chr) && (chr != '\n') && (chr != '\r')) {
        str += chr;
    }

    in.flags(flags);
    return in;
}

The above function works as std::getline is expected to, it returns after the first enter is pushed.

Upvotes: 1

Related Questions