Search code examples
c++c++11istream-iterator

istream_iterator consumes too much from stream


I get the following input from stdin:

2
5
2 1 5 3 4
5
2 5 1 3 4

The first line represents the number of queues (let's call this value n). Then, for each queue, on the first line there is a value l that is denoting the length of the queue, followed by the actual queue.

I am trying to put the queues in a vector using an istream_iterator as follows:

using namespace std;
int n{};
int l{};
typedef std::istream_iterator<int> input_iterator;
cin >> n;
cout<< "n: " << n << "\n";
for(int i = 0; i < n ; ++i){

    cin >> l;
    cout << "l: " << l << "\n";
    std::vector<int> queue;
    int counter = 0;
    for (input_iterator it(cin); counter < l && it != input_iterator(); ++it){
        queue.push_back((*it));
        ++counter;
    }
    cout<< "Queue: ";
    std::copy(queue.begin(), queue.end(), 
                  std::ostream_iterator<int>(std::cout, " "));
    cout << "\n";
}

This code produces the following output:

n: 2
l: 5
Queue: 2 1 5 3 4 
l: 2
Queue: 5 1 

As you can see the first queue is read correctly. But the second l should be 5, not 2.

What is happening to the 5? Is it consumed by the iterator? Where did i make an error?


Solution

  • Your problem is that your for-loop leaves i in a position next to the last element of the queue. So when calling operator>> to acquire the next value for l, you are one "reading step" too far.

    To avoid the problem, you can use the same iterator for all your reading operations -- and rename it to avoid name collision with the variable i in the outer loop, like this:

    using namespace std;
    int n{};
    int l{};
    typedef std::istream_iterator<int> input_iterator;
    cin >> n;
    cout<< "n: " << n << "\n";
    input_iterator it(cin);
    for(int i = 0; i < n ; ++i){
    
        l = *(it++);
        cout << "l: " << l << "\n";
        std::vector<int> queue;
        int counter = 0;
        while( counter < l && it != input_iterator() ){
            queue.push_back(*(it++));
            ++counter;
        }
        cout<< "Queue: ";
        std::copy(queue.begin(), queue.end(), 
                      std::ostream_iterator<int>(std::cout, " "));
        cout << "\n";
    }