[boost-users] istream_iterator question

Hello,
I don't know why the following code does not work as expected.
I hope the guru's here could lend me a hand.
For a test data file:
3
1 2
3 4
5 6
2
1.2 4.3 234.2
3.5656 67.88 345.3
<eof>
and 2 simple test helper class:
struct a
{ int i, j; };
std::istream& operator>>(std::istream& in, a & p)
{ in >> p.i >> p.j; return in; }
std::ostream& operator<<(std::ostream& out, const a & p)
{ out << p.i << " " << p.j; return out; }
struct b
{ float i, j, k; };
std::istream& operator>>(std::istream& in, b & p)
{ in >> p.i >> p.j >> p.k; return in; }
std::ostream& operator<<(std::ostream& out, const b & p)
{ out << p.i << " " << p.j << " " << p.k; return out; }
Here is version 1, quite trivial and works just ok.
std::ifstream is("./test.txt")
int n;
is >> n;
std::cout << "n=" << n << "\n";
for(int i=0; i

Max escribió:
Hello,
I don't know why the following code does not work as expected. I hope the guru's here could lend me a hand.
For a test data file: 3 1 2 3 4 5 6
2 1.2 4.3 234.2 3.5656 67.88 345.3 <eof>
and 2 simple test helper class:
struct a { int i, j; }; std::istream& operator>>(std::istream& in, a & p) { in >> p.i >> p.j; return in; } std::ostream& operator<<(std::ostream& out, const a & p) { out << p.i << " " << p.j; return out; }
struct b { float i, j, k; }; std::istream& operator>>(std::istream& in, b & p) { in >> p.i >> p.j >> p.k; return in; } std::ostream& operator<<(std::ostream& out, const b & p) { out << p.i << " " << p.j << " " << p.k; return out; } [Snip]
copy_n is defined as:
template
OutputIterator copy_n( InputIterator first, InputIterator last, Size n, OutputIterator result) { // copies the first `n' items from `first' to `result'. Returns // the value of `result' after inserting the `n' items. // it ends before n iterations, if the last iterator is reached while( n-- && first != last) { *result = *first; ++first; ++result; } return result; }
Change your copy_n() as follows:
template

Hello,
I don't know why the following code does not work as expected. I hope the guru's here could lend me a hand.
For a test data file: 3 1 2 3 4 5 6
2 1.2 4.3 234.2 3.5656 67.88 345.3 <eof>
and 2 simple test helper class:
struct a { int i, j; }; std::istream& operator>>(std::istream& in, a & p) { in >> p.i >> p.j; return in; } std::ostream& operator<<(std::ostream& out, const a & p) { out << p.i << " " << p.j; return out; }
struct b { float i, j, k; }; std::istream& operator>>(std::istream& in, b & p) { in >> p.i >> p.j >> p.k; return in; } std::ostream& operator<<(std::ostream& out, const b & p) { out << p.i << " " << p.j << " " << p.k; return out; } [Snip]
copy_n is defined as:
template
OutputIterator copy_n( InputIterator first, InputIterator last, Size n, OutputIterator result) { // copies the first `n' items from `first' to `result'. Returns // the value of `result' after inserting the `n' items. // it ends before n iterations, if the last iterator is reached while( n-- && first != last) { *result = *first; ++first; ++result; } return result; } Change your copy_n() as follows:
template
OutputIterator copy_n( InputIterator first, InputIterator last, Size n, OutputIterator result) { // copies the first `n' items from `first' to `result'. Returns // the value of `result' after inserting the `n' items. // it ends before n iterations, if the last iterator is reached while( n-- && first != last) { *result = *first; if (n) ++first; ++result; } return result; } Regards, Dmitry
Hello Dmitry,
I really appreciate your help on such a naive question!
I'm prepared to getting no response from the list, for my
message is really a little bit lengthy, and somewhat off
the main stream of the list, I'm afraid. :-)
With your code change, the test code runs as expected,
so does my real program. But I just don't know why.
In fact, the copy_n function is a safe version of another
one:
template

Hello,
I hope I could get the attention and, hopefully, help from the guru's
like Steven Watanabe, et al. :-)
After careful analysis of the source code, I get the conclusion:
The absence of 'if(n)' is not the beef of the problem. On the contrary,
even though it could make the code bahave as expected, it will break
other code using ordinary iterators (that means iterators other than
istream_iterator).
Original version (without 'if(n)') of both copy_n are logically correct,
which have been domenstrated. The design of istream_iterator makes
its behavior generally as same as an iterator, but will break the simple
test code in my OP. I think this is a desing flaw.
The definition of istream_iterator that comes with VS2008 is
as follows (simplified and unrelated part omitted):
template
Hello,
I don't know why the following code does not work as expected. I hope the guru's here could lend me a hand.
For a test data file: 3 1 2 3 4 5 6
2 1.2 4.3 234.2 3.5656 67.88 345.3 <eof>
and 2 simple test helper class:
struct a { int i, j; }; std::istream& operator>>(std::istream& in, a & p) { in >> p.i >> p.j; return in; } std::ostream& operator<<(std::ostream& out, const a & p) { out << p.i << " " << p.j; return out; }
struct b { float i, j, k; }; std::istream& operator>>(std::istream& in, b & p) { in >> p.i >> p.j >> p.k; return in; } std::ostream& operator<<(std::ostream& out, const b & p) { out << p.i << " " << p.j << " " << p.k; return out; } [Snip]
copy_n is defined as:
template
OutputIterator copy_n( InputIterator first, InputIterator last, Size n, OutputIterator result) { // copies the first `n' items from `first' to `result'. Returns // the value of `result' after inserting the `n' items. // it ends before n iterations, if the last iterator is reached while( n-- && first != last) { *result = *first; ++first; ++result; } return result; } Change your copy_n() as follows:
template
OutputIterator copy_n( InputIterator first, InputIterator last, Size n, OutputIterator result) { // copies the first `n' items from `first' to `result'. Returns // the value of `result' after inserting the `n' items. // it ends before n iterations, if the last iterator is reached while( n-- && first != last) { *result = *first; if (n) ++first; ++result; } return result; } Regards, Dmitry
Hello Dmitry,
I really appreciate your help on such a naive question!
I'm prepared to getting no response from the list, for my
message is really a little bit lengthy, and somewhat off
the main stream of the list, I'm afraid. :-)
With your code change, the test code runs as expected,
so does my real program. But I just don't know why.
In fact, the copy_n function is a safe version of another
one:
template

Please ignore the previous post due to some typo may lead
to misunderstanding. Sorry for the noise.
Hello,
I hope I could get the attention and, hopefully, help from the guru's
like Steven Watanabe, et al. :-)
After careful analysis of the source code, I get the conclusion:
The absence of 'if(n)' is not the beef of the problem. On the contrary,
even though it could make the code bahave as expected, it will break
other code using ordinary iterators (that means iterators other than
istream_iterator).
Original version (without 'if(n)') of both copy_n are logically correct,
which have been domenstrated. The design of istream_iterator makes
its behavior generally as same as an iterator, but will break the simple
test code in my OP. I think this is a design flaw.
The definition of istream_iterator that comes with VS2008 is
as follows (simplified and unrelated part omitted):
template
Hello,
I don't know why the following code does not work as expected. I hope the guru's here could lend me a hand.
For a test data file: 3 1 2 3 4 5 6
2 1.2 4.3 234.2 3.5656 67.88 345.3 <eof>
and 2 simple test helper class:
struct a { int i, j; }; std::istream& operator>>(std::istream& in, a & p) { in >> p.i >> p.j; return in; } std::ostream& operator<<(std::ostream& out, const a & p) { out << p.i << " " << p.j; return out; }
struct b { float i, j, k; }; std::istream& operator>>(std::istream& in, b & p) { in >> p.i >> p.j >> p.k; return in; } std::ostream& operator<<(std::ostream& out, const b & p) { out << p.i << " " << p.j << " " << p.k; return out; } [Snip]
copy_n is defined as:
template
OutputIterator copy_n( InputIterator first, InputIterator last, Size n, OutputIterator result) { // copies the first `n' items from `first' to `result'. Returns // the value of `result' after inserting the `n' items. // it ends before n iterations, if the last iterator is reached while( n-- && first != last) { *result = *first; ++first; ++result; } return result; } Change your copy_n() as follows:
template
OutputIterator copy_n( InputIterator first, InputIterator last, Size n, OutputIterator result) { // copies the first `n' items from `first' to `result'. Returns // the value of `result' after inserting the `n' items. // it ends before n iterations, if the last iterator is reached while( n-- && first != last) { *result = *first; if (n) ++first; ++result; } return result; } Regards, Dmitry
Hello Dmitry,
I really appreciate your help on such a naive question!
I'm prepared to getting no response from the list, for my
message is really a little bit lengthy, and somewhat off
the main stream of the list, I'm afraid. :-)
With your code change, the test code runs as expected,
so does my real program. But I just don't know why.
In fact, the copy_n function is a safe version of another
one:
template

AMDG Max wrote:
const _Ty& operator*() const { // return designated value return (_Myval); }
_Myt& operator++() { // preincrement _Getval(); return (*this); }
IMO, it should be modified as:
const _Ty& operator*() //const { // return designated value _Getval(); return (_Myval); }
_Myt& operator++() { // preincrement return (*this); }
The main problem of the current design of istream_iterator is that it always swallow one extra object, of the template parameter type, prepared for the coming * or -> operator. This makes the coming plain >> operator a distance forward of where it shoud be.
I've tested with this modification and found it works well. Please note that I've simply commented out the trailing const qualifier for the * and -> operator, to make things simpler and more straightforward. Obviously, furthur modification is to be made to make the code to a product level.
I want to know whether this change makes sense?
Well, it solves your problem, but it creates other problems instead. For example, what should this do: std::istream_iterator<int> iter(std::cin); std::advance(iter, 10); Or this: std::istream_iterator<int> iter(std::cin); if(*iter != 10) { std::cout << *iter; } In Christ, Steven Watanabe

hello Steven, I do appreciate your prompt reply.
AMDG Well, it solves your problem, but it creates other problems instead.
For example, what should this do: std::istream_iterator<int> iter(std::cin); std::advance(iter, 10);
Or this: std::istream_iterator<int> iter(std::cin); if(*iter != 10) { std::cout << *iter; }
In Christ, Steven Watanabe
Yes, my simple modification is obviously not complete and will cause other problems including those you mentioned. But I believe we are not at the situation that we should bear one of the two kinds of problems. There must be a sound solution, I guess. Or, in other words, in the situation as that I mentioned in my first post, should I use the ugly-looking explicit for loops instead of using the seemingly elegant iterator adaptor approach? :-) Thanks again for your time, Steven. B/Rgds Max
participants (3)
-
Dmitry Bufistov
-
Max
-
Steven Watanabe