c++ioiostreamstreambuf

How to prevent `std::cin` or `\n` from flushing the buffer of `std::cout`?


Let's imagine my program needs input from the user at different times. I want this input to prevent flushing the cout buffer. Can I set cin and cout on different stream buffers?

Example in question: a program that reads two numbers in a line, n1 n2, and depending on the first number being either 0, 1, or 2:

The MWE is:

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int size, n1, n2;
    vector<int> v;
    cin >> size;

    while(size--){
        cin >> n1;

        if (n1 == 0)
        {
            cin >> n2;
            v.push_back(n2);
        }
        else if (n1 == 1)
        {
            cin >> n2;
            cout << v[n2] << '\n';
        }   
        else if (n1 == 2)
            v.pop_back();
    }

return 0;
}

Say I have this test input

8
0 1
0 2
0 3
2
0 4
1 0
1 1
1 2

correct output should be

1
2
4

The program above yields outputs interspersed with the input lines instead.

But I would like them all printed together at end program, without using different means e.g. storing them in some container etc.

So I think I should operate on the buffer, but how?


Solution

  • You could write to your own std::stringstream buffer, and then output that to std::cout when you're ready.

    MWE:

    #include <iostream>
    #include <sstream>
    #include <stdexcept>
    #include <vector>
    
    using std::cin;
    using std::cout;
    using std::istream;
    using std::runtime_error;
    using std::stringstream;
    using std::vector;
    
    static auto get_int(istream& in) -> int {
        int n;
        if (!(in >> n)) {
            throw runtime_error("bad input");
        }
        return n;
    }
    
    int main() {
        auto ss = stringstream();
        auto v = vector<int>();
        auto size = get_int(cin);
    
        while(size--) {
            auto n1 = get_int(cin);
    
            if (n1 == 0) {
                auto n2 = get_int(cin);
                v.push_back(n2);
            } else if (n1 == 1) {
                auto n2 = get_int(cin);
                ss << v[n2] << '\n';
            } else if (n1 == 2) {
                v.pop_back();
            }
        }
    
        cout << ss.str();
    }