Reputation: 1150
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?
Upvotes: 2
Views: 113
Reputation: 409166
A for
loop is basically just a fancy while
loop.
Lets take this for
loop from your code:
for (input_iterator it(cin); counter < l && it != input_iterator(); ++i){
queue.push_back((*it));
++counter;
}
It is equivalent to the following:
{
input_iterator it(cin);
while (counter < l && it != input_iterator())
{
queue.push_back((*it));
++counter;
++it;
}
}
Notice that last line in the loop, the ++it;
statement? That's what is causing your problem. It will increase the iterator once too many, so after the loop the iterator has read the 5
in the input. The next input operation after the loop will then read the 2
in the next line.
One solution is to keep the iterator, and reuse it inside the outer loop. Perhaps use it for all input.
Another solution, which I hinted about in my comment, is to have for
loop from zero to l
only and not use an iterator at all but only plain cin >> ...
.
Upvotes: 2
Reputation: 15956
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";
}
Upvotes: 2
Reputation: 2048
IANALL, but istream_iterator is to my knowledge allowed to read ahead in its operator++()
. Since you're re-creating an istream iterator for every group (line of numbers) that you read, you're discarding an iterator that has already read the next integer from the input stream.
One solution would be to create the input iterator only once outside of your for-loop and use it throughout.
Upvotes: 2