Fe Qlw
Fe Qlw

Reputation: 39

Weird behavior when using cin.ignore and cin.clear CPP

I learned that cin.clear() clears the error flag, so the cin operations will work well, and cin.ignore() to extract characters from the stream. So I tried this code:

#include <iostream>
#include <string>
int main()
{
    std::string s;
    std::cin >> s;
    std::cout << s;
    std::cin.clear();
    std::cin.ignore(1000, '\n');
    std::getline(std::cin, s);
    std::getline(std::cin, s);
    std::cout << s;
    system("pause");
    return 0;
}

It works well. For three inputs:

I
AM
TRY

The output will be:

I 
TRY

But if I change it to be:

#include <iostream>
#include <string>
int main()
{
    std::string s;
    std::cin >> s;
    std::cout << s;
    std::cin.clear();
    std::cin.ignore(1000, '\n');
    std::getline(std::cin, s);
    std::cin.clear(); // New code
    std::cin.ignore(1000, '\n');  // New code
    std::getline(std::cin, s);
    std::cout << s;
    system("pause");
    return 0;
}

I will need to enter four inputs!

How does it make any sense that when I add the code above, I will need to enter:

I
AM
NOW
TRY

To get the same output? For some reason it requires one input more.

Upvotes: 2

Views: 278

Answers (1)

user
user

Reputation: 944

Consider you intput I AM TRY NOW every time.

#include <iostream>
#include <string>
int main()
{
    std::string s;
    std::cin >> s;
    std::cout << s; //-> outputs "I"
    std::cin.clear();
    std::cin.ignore(1000, '\n');//consumes all that follows "I"
    std::getline(std::cin, s); //-> get the whole "I AM TRY NOW" inside s
    std::cin.clear(); 
    std::cin.ignore(1000, '\n');  //Your cin is empty (because you took the whole line with getline(), not just part of the line, the stream has no character left in it and this cin.ignore() call is the reason you need 1 more input, because calling cin.ignore() en empty stream does that.
    std::getline(std::cin, s); //-> overwrites the previous std::getline(std::cin, s);
        std::cout << s; //outputs the whole line : "I AM TRY NOW"
        system("pause");
        return 0;
}

Because you call cin.ignore(1000, '\n'); on an empty stream, you get one more input with the second code sample. Try this

int main()
{
    std::string s;
    std::cin.ignore(1000, '\n');  // New code
system("pause");
}

It will require an input whereas this :

int main()
{
    std::string s;
    cin >> s;
    std::cin.ignore(1000, '\n');  // New code
    system("pause");
}

Will also require a single input if you enter I the newline will be the discarded character, if you enter I AM TRY then AM TRY and the newline will be discarded

int main()
{
    std::string s;
    cin >> s;
    std::cin.ignore(1000, '\n');  // New code
    std::cin.ignore(1000, '\n');  // requires second input
    system("pause");
}

Will require two inputs because at the second cin.ignore call, there is an empty cin stram.

Upvotes: 1

Related Questions