istream_iterator question

B

Bill Rudolph

The member function basic_ios::eek:perator!() returns the bool result of
the basic_ios::fail() function which is true if either failbit or
badbit is set (This is per p. 616 of TC++PL by B. Stroustrup and p. 34
of Standard C++ IOStreams and Locales by Angelika Langer and Klaus
Kreft).

The implementation of the input stream iterator in the Langer and
Kreft book (see p. 129 to 130) uses the function:

void readElem()
{
if (istp!=0) if(!(*istp>>value)) istp=0;
}

in determining whether or not two istream iterators are equal as in
the following code:

vector<T> v(0);
ifstream f("input.txt");
copy(istream_iterator<T>(f),istream_iterator<T>(),back_inserter(v));

In this example, istream_iterator<T>(f) is equal to
istream_iterator<T>() if istp is equal to 0 for both iterators. istp
is set equal to 0 if the failbit or badbit is set--not if the eofbit
is set.

What happens when the end of file has been reached? Does the loop
continue until a failbit or badbit is set? Would the following code
(which reflects eofbit status) serve as an alternative?

void readElem()
{
istp!=0&&istp->good()?*istp>>value:istp=0;
}
 
J

John Harrison

Bill Rudolph said:
The member function basic_ios::eek:perator!() returns the bool result of
the basic_ios::fail() function which is true if either failbit or
badbit is set (This is per p. 616 of TC++PL by B. Stroustrup and p. 34
of Standard C++ IOStreams and Locales by Angelika Langer and Klaus
Kreft).

The implementation of the input stream iterator in the Langer and
Kreft book (see p. 129 to 130) uses the function:

void readElem()
{
if (istp!=0) if(!(*istp>>value)) istp=0;
}

in determining whether or not two istream iterators are equal as in
the following code:

vector<T> v(0);
ifstream f("input.txt");
copy(istream_iterator<T>(f),istream_iterator<T>(),back_inserter(v));

In this example, istream_iterator<T>(f) is equal to
istream_iterator<T>() if istp is equal to 0 for both iterators. istp
is set equal to 0 if the failbit or badbit is set--not if the eofbit
is set.

What happens when the end of file has been reached? Does the loop
continue until a failbit or badbit is set? Would the following code
(which reflects eofbit status) serve as an alternative?

void readElem()
{
istp!=0&&istp->good()?*istp>>value:istp=0;
}

No that would be wrong. fail refers to the failure to extract an element,
eof refers to a read past the end of file. It is possible for eof to be true
when fail is false. For instance suppose that last item in a file is an
integer with no following whitespace, then in order to read the integer the
program is going to have to read past the end of the file, setting eof to
true, but an element has still been extracted so fail is false and
processing should continue.

john
 
B

Bill Rudolph

John Harrison said:
No that would be wrong. fail refers to the failure to extract an element,
eof refers to a read past the end of file. It is possible for eof to be true
when fail is false. For instance suppose that last item in a file is an
integer with no following whitespace, then in order to read the integer the
program is going to have to read past the end of the file, setting eof to
true, but an element has still been extracted so fail is false and
processing should continue.

I assume that you are referring to my alternative readElem().

Assume the Langer and Kreft implementation (p. 130) of
istream_iterator::eek:perator++(int)

istream_iterator istream_iterator::eek:perator++(int)
{
istream_iterator tmp=*this;
readElem();
return tmp;
}

and the Stroustrup implementation (p. 529) of std::copy

Out copy(In first,In last,Out res)
{
while (first!=last) *res++=*first++;
return res;
}

Suppose that the last item in a file is an integer with no following
whitespace. That is, the file ends with 98 12345<eof>.

In std::copy, first does not equal last and *first++ is called. A
temporary istream_iterator named tmp is created in which istp points
to the same stream and value equals 98. istream_iterator::readElem()
is called. istp does not equal 0 and therefore *istp>>value is called.
istream_iterator::value is set to 12345. ios_base::eofbit is set but
iosbase::failbit is not set. The function basic_ios::fail() returns
false and !(*istp>>value) returns false. Therefore, istp is not set
equal to 0. The istream_iterator returned from
istream_iterator::eek:perator++(int) is the temporary that was created.

In the next iteration, first does not equal last as istp does not
equal 0. *first++ is called. A temporary is created in which istp
points to the same stream and value equals 12345.
istream_iterator::readElem() is called. istp does not equal 0 and
therefore *istp>>value is called. The extraction fails as there is
nothing to extract. The iosbase::failbit is set, basic_ios::fail()
returns true, and !(*istp>>value) returns true. istp is set equal to
0. The istream_iterator returned from
istream_iterator::eek:perator++(int) is the temporary that was created
that contains value equal to 12345.

In the next iteration, first equals last as istp equals 0 and res is
returned from the copy function.

Is this the correct interpretation of what happens when the end of the
file is reached? If so, I don't see anything wrong with the
alternative:

void readElem()
{
istp!=0&&istp->good()?*istp>>value:istp=0;
}
 
J

John Harrison

Bill Rudolph said:
"John Harrison" <[email protected]> wrote in message

I assume that you are referring to my alternative readElem().

Assume the Langer and Kreft implementation (p. 130) of
istream_iterator::eek:perator++(int)

istream_iterator istream_iterator::eek:perator++(int)
{
istream_iterator tmp=*this;
readElem();
return tmp;
}

and the Stroustrup implementation (p. 529) of std::copy

Out copy(In first,In last,Out res)
{
while (first!=last) *res++=*first++;
return res;
}

Suppose that the last item in a file is an integer with no following
whitespace. That is, the file ends with 98 12345<eof>.

In std::copy, first does not equal last and *first++ is called. A
temporary istream_iterator named tmp is created in which istp points
to the same stream and value equals 98. istream_iterator::readElem()
is called. istp does not equal 0 and therefore *istp>>value is called.
istream_iterator::value is set to 12345. ios_base::eofbit is set but
iosbase::failbit is not set. The function basic_ios::fail() returns
false and !(*istp>>value) returns false. Therefore, istp is not set
equal to 0. The istream_iterator returned from
istream_iterator::eek:perator++(int) is the temporary that was created.

In the next iteration, first does not equal last as istp does not
equal 0. *first++ is called. A temporary is created in which istp
points to the same stream and value equals 12345.
istream_iterator::readElem() is called. istp does not equal 0 and
therefore *istp>>value is called. The extraction fails as there is
nothing to extract. The iosbase::failbit is set, basic_ios::fail()
returns true, and !(*istp>>value) returns true. istp is set equal to
0. The istream_iterator returned from
istream_iterator::eek:perator++(int) is the temporary that was created
that contains value equal to 12345.

In the next iteration, first equals last as istp equals 0 and res is
returned from the copy function.

Is this the correct interpretation of what happens when the end of the
file is reached? If so, I don't see anything wrong with the
alternative:

void readElem()
{
istp!=0&&istp->good()?*istp>>value:istp=0;
}

Yes I think your interpretation is correct, but I still think your version
of readElem will cause the copy loop to terminate wrongly in some
situations. It just feels wrong to be using the eof bit in this situation,
whether a value has bee extracted it the important issue.

But I could easily be wrong, why not code it up and find out?

john
 
B

Bill Rudolph

John Harrison said:
Yes I think your interpretation is correct, but I still think your version
of readElem will cause the copy loop to terminate wrongly in some
situations.

Assume the readElem() from the Langer and Kreft implementation. That
is,

void readElem()
{
if (istp!=0) if(!(*istp>>value)) istp=0;
}

An example of extracting an integer was illustrated. Suppose though,
that something else was extracted, say a BookCharacter using:

istream&
operator>>(istream& is,BookCharacter& t)
{
return !is.good()?is:t.input(is);
//or return is.good()?t.input(is):is;
}

Also, assume that the last item of the stream has been extracted. As
before, istp does not equal 0. ios_base::eofbit is set but
iosbase::failbit is not set. The istream_iterator returned from
istream_iterator::eek:perator++(int) is the temporary that was created.

In the next iteration, first does not equal last as istp does not
equal 0. *first++ is called. A temporary is created in which istp
points to the same stream and value is a copy of the object which
contains the last item extracted from the stream.
istream_iterator::readElem() is called. istp does not equal 0 and
therefore *istp>>value --i.e., the function istream&
operator>>(istream&,BookCharacter&)--is called. !is.good() is true as
ios_base::eofbit has been set. Therefore istream& is returned.
(!(*istp>>value)) is false as neither ios_base::failbit nor
ios_base::badbit has been set. istp is not set to 0. The
istream_iterator returned from istream_iterator::eek:perator++(int) is
the temporary that was created.

With this extractor, there is a loop that continues until there is a
crash due to insufficient memory. istp is 0. value is the object that
contains the last item extracted.

Is this interpretation correct? My version of readElem would not
cause this copy loop to terminate wrongly in this circumstance.
 

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,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top