trouble in understanding istream_iterator

  • Thread starter subramanian100in
  • Start date
S

subramanian100in

I am using g++ 3.4.3

Consider the following program x.cpp:

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
istream_iterator<string> isi(cin);
istream_iterator<string> eos;

vector<string> c(isi, eos);

cout << "Displaying input contents:" << endl;
cout << "--------------------------" << endl;

copy(c.begin(),
c.end(),
ostream_iterator<string>(cout, "\n"));

cout << endl;

if (isi == eos)
cout << "end of input stream reached" << endl;
else
cout << "eos not reached" << endl;

string str;

if (cin >> str)
cout << "string read from cin: " << str << endl;
else
cout << "Unable to read a string from cin" << endl;

cout << endl;

vector<string> d(isi, eos);

cout << "Displaying the input second time:" << endl;
cout << "---------------------------------" << endl;

copy(d.begin(),
d.end(),
ostream_iterator<string>(cout, "\n"));

return EXIT_SUCCESS;
}

When I run this program with the following input
1
2
3

the following is printed:

Displaying input contents:
--------------------------
1
2
3

eos not reached
Unable to read a string from cin

Displaying the input second time:
---------------------------------
1

Kindly correct me whereever I am wrong in the following:

In the above program, consider the statement:
vector<string> c(isi, eos);
This vector ctor will construct the object 'c' with three input values
namely '1', '2', '3' which were entered from the standard input. After
this ctor statement, there will NOT be any input contents left in cin.
Am I correct ?
The first 'copy' algorithm will copy the contents of 'c' onto the
standard output. Now consider the statement
if (isi == eos)
Here I thought 'isi' should be equal to 'eos' because there is no
content left in 'cin'. But on the contrary, 'eos not reached' is
printed. I am unable to understand the reason for this.

Now consider the statement
if (cin >> str)
For this, the control goes to the else part(because there is no
content left in the stanadard input stream 'cin') and prints:

Unable to read a string from cin

This is as expected.

Now consder the vector object:
vector<string> d(isi, eos);
Since there is no content left in 'cin', the vector object 'd' should
be empty I thought. However, on the contrary, the subsequent 'copy'
algorithm prints:

1

I am unable to understand how the second vector object d's ctor was
able to read 'isi' to fetch the value '1'. In other words, where does
this value '1' come from ?

Kindly explain.

Thanks
V.Subramanian
 
K

Kai-Uwe Bux

I am using g++ 3.4.3

Consider the following program x.cpp:

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
istream_iterator<string> isi(cin);
istream_iterator<string> eos;

vector<string> c(isi, eos);

cout << "Displaying input contents:" << endl;
cout << "--------------------------" << endl;

copy(c.begin(),
c.end(),
ostream_iterator<string>(cout, "\n"));

cout << endl;

if (isi == eos)
cout << "end of input stream reached" << endl;
else
cout << "eos not reached" << endl;

This test is bogus. The variable isi has not changed.

string str;

if (cin >> str)
cout << "string read from cin: " << str << endl;
else
cout << "Unable to read a string from cin" << endl;

cout << endl;

vector<string> d(isi, eos);

cout << "Displaying the input second time:" << endl;
cout << "---------------------------------" << endl;

copy(d.begin(),
d.end(),
ostream_iterator<string>(cout, "\n"));

return EXIT_SUCCESS;
}

When I run this program with the following input
1
2
3

the following is printed:

Displaying input contents:
--------------------------
1
2
3

eos not reached
Unable to read a string from cin

Displaying the input second time:
---------------------------------
1

Kindly correct me whereever I am wrong in the following:

In the above program, consider the statement:
vector<string> c(isi, eos);
This vector ctor will construct the object 'c' with three input values
namely '1', '2', '3' which were entered from the standard input. After
this ctor statement, there will NOT be any input contents left in cin.
Am I correct ?
Yes.


The first 'copy' algorithm will copy the contents of 'c' onto the
standard output. Now consider the statement
if (isi == eos)
Here I thought 'isi' should be equal to 'eos' because there is no
content left in 'cin'. But on the contrary, 'eos not reached' is
printed. I am unable to understand the reason for this.

You did not change the value of isi. Passing as the first argument to the
constructor of the vector is by value.

Now consider the statement
if (cin >> str)
For this, the control goes to the else part(because there is no
content left in the stanadard input stream 'cin') and prints:

Unable to read a string from cin

This is as expected.

Yes.

Now consder the vector object:
vector<string> d(isi, eos);
Since there is no content left in 'cin', the vector object 'd' should
be empty I thought. However, on the contrary, the subsequent 'copy'
algorithm prints:

1

I am unable to understand how the second vector object d's ctor was
able to read 'isi' to fetch the value '1'. In other words, where does
this value '1' come from ?

Undefined behavior. The input iterator isi has been invalidated in the first
pass through the input, but the now invalid value is still there (in the
variable isi). [24.1.1./3] warns that algorithms using input iterators
should be single pass.


Best

Kai-Uwe Bux
 
S

subramanian100in

* Kai-Uwe Bux said:
I am using g++ 3.4.3
Now consder the vector object:
vector<string> d(isi, eos);
Since there is no content left in 'cin', the vector object 'd' should
be empty I thought. However, on the contrary, the subsequent 'copy'
algorithm prints:

I am unable to understand how the second vector object d's ctor was
able to read 'isi' to fetch the value '1'. In other words, where does
this value '1' come from ?

Undefined behavior. The input iterator isi has been invalidated in the first
pass through the input, but the now invalid value is still there (in the
variable isi). [24.1.1./3] warns that algorithms using input iterators
should be single pass.

Best

Kai-Uwe Bux

In the above reply, the following sentence is present:
"The input iterator isi has been invalidated in the first pass through
the input"
Here does 'first pass' refer to the statement
vector<string> c(isi, eos);

Also, kindly clarify how 'isi' could be invalidated at the calling
point of the ctor since we are passing 'isi' by value to the ctor.

Consider the statement
vector<string> d(isi, eos);
Here do you mean to say 'isi' is traversed second time ?

I thought, only within the same algorithm we should not try traverse
the input iterator multiple times. Since we are passing 'isi' by value
to vector ctor in the construction of the objects 'c' and 'd', will
that amount to traversing 'isi' multiple times ?

Since we are passing the input iterator 'isi' by value to the vector
ctor, inside the ctor, only the local copy of that input iterator will
be incremented. Since we do this once in the construction of 'c' and
second time during the construction of 'd', at the calling point of
the ctors we are not traversing multiple times. Is this understanding
of mine is correct?

I am unable to understand this. Kindly clarify, if needed with an
example.

Thanks
V.Subramanian
 
K

Kai-Uwe Bux

* Kai-Uwe Bux said:
I am using g++ 3.4.3
Now consder the vector object:
vector<string> d(isi, eos);
Since there is no content left in 'cin', the vector object 'd' should
be empty I thought. However, on the contrary, the subsequent 'copy'
algorithm prints:

I am unable to understand how the second vector object d's ctor was
able to read 'isi' to fetch the value '1'. In other words, where does
this value '1' come from ?

Undefined behavior. The input iterator isi has been invalidated in the
first pass through the input, but the now invalid value is still there
(in the variable isi). [24.1.1./3] warns that algorithms using input
iterators should be single pass.

Best

Kai-Uwe Bux

In the above reply, the following sentence is present:
"The input iterator isi has been invalidated in the first pass through
the input"
Here does 'first pass' refer to the statement
vector<string> c(isi, eos);
Yes.


Also, kindly clarify how 'isi' could be invalidated at the calling
point of the ctor since we are passing 'isi' by value to the ctor.

See how Table 72 of the standard specifies the post-condition of ++r:

post: any copies of the previous value of r are no longer required either
to be dereferenceable or to be in the domain of ==
Consider the statement
vector<string> d(isi, eos);
Here do you mean to say 'isi' is traversed second time ?
Yes.

I thought, only within the same algorithm we should not try traverse
the input iterator multiple times.

Depends what you mean by "algorithm". The post-condition from above makes it
pretty clear, that the program as a whole is the "algorithm".
Since we are passing 'isi' by value
to vector ctor in the construction of the objects 'c' and 'd', will
that amount to traversing 'isi' multiple times ?
Yes.

Since we are passing the input iterator 'isi' by value to the vector
ctor, inside the ctor, only the local copy of that input iterator will
be incremented. Since we do this once in the construction of 'c' and
second time during the construction of 'd', at the calling point of
the ctors we are not traversing multiple times. Is this understanding
of mine is correct?

No.

See the post-condition above. Note in particular how is says "any copies".
That way, even though isi retains its value, it is still invalidated for
further use.
I am unable to understand this. Kindly clarify, if needed with an
example.

Your example is just fine. It illustrates the provisions of the standard by
exhibiting undefined behavior in exactly the right place.


Best

Kai-Uwe Bux
 
S

subramanian100in

Now consider the following modified program x.cpp:

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
istream_iterator<string> isi(cin);
istream_iterator<string> eos;

vector<string> c(isi, eos);

cout << "Displaying input contents:" << endl;
cout << "--------------------------" << endl;

copy(c.begin(),
c.end(),
ostream_iterator<string>(cout, "\n"));

cout << endl;

cin.clear();

vector<string> d(isi, eos);

cout << "Displaying the input second time:" << endl;
cout << "---------------------------------" << endl;

copy(d.begin(),
d.end(),
ostream_iterator<string>(cout, "\n"));

return EXIT_SUCCESS;

}

In this modified program I have added
cin.clear();
between the first vector object construction viz:
vector<string> c(isi, eos);
and the second vector object construction viz:
vector<string> d(isi, eos);

In this case also, is the istream_iterator 'isi' invalidated(when I
pass it to the ctor for 'd') thereby invoking undefined behavior ?

Kindly explain.

Thanks
V.Subramanian
 
K

Kai-Uwe Bux

Now consider the following modified program x.cpp:

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
istream_iterator<string> isi(cin);
istream_iterator<string> eos;

vector<string> c(isi, eos);

cout << "Displaying input contents:" << endl;
cout << "--------------------------" << endl;

copy(c.begin(),
c.end(),
ostream_iterator<string>(cout, "\n"));

cout << endl;

cin.clear();

vector<string> d(isi, eos);

cout << "Displaying the input second time:" << endl;
cout << "---------------------------------" << endl;

copy(d.begin(),
d.end(),
ostream_iterator<string>(cout, "\n"));

return EXIT_SUCCESS;

}

In this modified program I have added
cin.clear();
between the first vector object construction viz:
vector<string> c(isi, eos);
and the second vector object construction viz:
vector<string> d(isi, eos);

In this case also, is the istream_iterator 'isi' invalidated(when I
pass it to the ctor for 'd') thereby invoking undefined behavior ?

Yes, the behavior is still undefined: the call cin.clear() does not change
the fact that you are dereferencing a copy of isi in the construction of d
after incrementing a copy during construction of c.


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,757
Messages
2,569,543
Members
45,026
Latest member
camilin05

Latest Threads

Top