Topic: operator>> (istream &, char *) - bug in library ?


Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/03/09
Raw View
Steve Clamage wrote:
>
> Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>
> >Just to see if I understand stream states correctly:
>
> >If called with an arbitrary istream, will every assertion in the
> >following function be guaranteed not to trigger?

[...]

> >  assert(s.clear(), s.good());
> >    // after clearing a stream, it is always good.
> >}
>
> Not quite.  If there is no buffer associated with the stream,
> calling clear will set the bad bit.

Is this the only way clear can fail? That is, is the following
assertion guaranteed?

  assert(s.clear(), s.good() || !s.rdbuf());


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stephen.Clamage@Sun.COM (Steve Clamage)
Date: 1999/03/09
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>Steve Clamage wrote:
>> Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>> >  assert(s.clear(), s.good());
>> >    // after clearing a stream, it is always good.
>> >}
>>
>> Not quite.  If there is no buffer associated with the stream,
>> calling clear will set the bad bit.

>Is this the only way clear can fail? That is, is the following
>assertion guaranteed?

>  assert(s.clear(), s.good() || !s.rdbuf());

I think so.

Implementations of "classic" iostreams typically had an additional
state bit "hardfail", representing an unrecoverable error (perhaps
a disk failure, broken tape, or disconnected modem). The clear()
function did not clear it, and the fail() and bad() functions tested
it. I don't think the standard allows a hardfail bit.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com(Steve Clamage)
Date: 1999/03/03
Raw View
Janis Papanagnou <Janis.Papanagnou@pc-plus.de> writes:

>Steve Clamage wrote:
>>
>> The "good" state means that none of "fail", "bad", or "eof"
>> states is set. Exactly when eof beocomes true is unspecified.

>That's a pity.

There isn't a lot of choice. The stream state and its testing
mechanism is in the base class common to all streams. Any
requirements on eof must apply to all possible kinds of streams.
In general, you can't know whether the last character encountered
is really the last character in the stream.

Example: Suppose we request 1 character of input, and the input
succeeds. Did we read the last character of the stream? If the
stream is a disk file, you could know. If the input is from a
keyboard or modem, you might have to wait an aribitrarily long
time to find out whether more characters are going to be available,
even though you don't need to see any more characters to complete
the current operation.

You just have to realize what eof means:
    If true, no more input is available.
    If false, you don't know whether more input is available.
If you want to know whether more characters are really available
before committing to a new input operation, try to read one
character, and push it back if the input succeeds.

>> If an input operation results in "fail", you can then test
>> for eof to see if that was the reason for the failure.

>So eof() is *only* well defined in the case when fail() is true.

No, that is not the case. Whether or not an operation succeeded,
you don't know any more than what I stated above.

If eof is true after a failure, the failure could be due to no more
input being available, or to a premature eof (incomplete data set),
or to hitting eof simultaneously with finding an invalid character
for the input being performed. If you want to know which of these
is really the case, you need a more elaborate technique than
simply testing the stream state.

All of this is true for stdio, by the way. For iostreams, C++
adopted the C model of input/output.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/03/04
Raw View
James.Kanze@dresdner-bank.com wrote:

[...]

> It's conforming.  Basically, ios::good() only returns 1 if *all* bits
> are 0, including eofbit.  And when the last read has succeeded, but the
> next will fail, the status of eofbit is not defined.

Just to see if I understand stream states correctly:

If called with an arbitrary istream, will every assertion in the
following function be guaranteed not to trigger?

void f(istream& s)
{
  char c;

  assert(s.good() || s.bad() || s.fail() || s.eof());
    // one of the flags is always true

  assert(!s.good() || (s >> c, !s.fail() || s.eof() || s.bad() ));
    // on a good stream, a char read can fail only either because
    // of eof or because the stream gets bad

  assert(s.good() || (s >> c, s.fail()));
    // reading from a non-good stream will alwais fail

  assert(s.clear(), s.good());
    // after clearing a stream, it is always good.
}


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stephen.Clamage@eng.sun.com (Steve Clamage)
Date: 1999/03/04
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:

>Just to see if I understand stream states correctly:

>If called with an arbitrary istream, will every assertion in the
>following function be guaranteed not to trigger?

>void f(istream& s)
>{
>  char c;

>  assert(s.good() || s.bad() || s.fail() || s.eof());
>    // one of the flags is always true

Yes. In addition, fail() returns true if the badbit is set.
Thus, fail()||bad() is equivalent to just fail().

>  assert(!s.good() || (s >> c, !s.fail() || s.eof() || s.bad() ));
>    // on a good stream, a char read can fail only either because
>    // of eof or because the stream gets bad

Yes.

>  assert(s.good() || (s >> c, s.fail()));
>    // reading from a non-good stream will always fail

Yes.

>  assert(s.clear(), s.good());
>    // after clearing a stream, it is always good.
>}

Not quite.  If there is no buffer associated with the stream,
calling clear will set the bad bit.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Janis Papanagnou <Janis.Papanagnou@pc-plus.de>
Date: 1999/03/02
Raw View
I made the following observation, and I think the behaviour of the
istrstream operator>> behaves buggy with strings (see *** below):

    char c;  istrstream is ("x");
    is >> c;  cerr << is.good() << endl;      // 1 - OK
    is >> c;  cerr << is.good() << endl;      // 0 - OK, eof

    int i;  istrstream is ("123");
    is >> i;  cerr << is.good() << endl;      // 1 - OK
    is >> i;  cerr << is.good() << endl;      // 0 - OK, eof

    char s [42];  istrstream is ("word");
    is >> s;  cerr << is.good() << endl;      // 0 - BUG !?   ***
    is >> s;  cerr << is.good() << endl;      // 0 - OK, eof

Reading in a 'string' type gives the same output, because it relies
directly on the char* implementation in our library.

My expecation would be, that reading a "word" once should keep the
state of the stream good, but our compiler sets the eof flag.
And please compare the behaviour with the integer example "123",
that works as expected, indeed.
The (old) draft standard document does not say anything about that.

On the other hand, when the istrstreams are initialized with data
terminated by a newline:

    istrstream is ("x\n");
    istrstream is ("123\n");
    istrstream is ("word\n");

everything works as expected (output is: 1 0 1 0 1 0).

Could someone please enlighten me, whether the behaviour is a bug
or conforming to the standard.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1999/03/02
Raw View
Janis Papanagnou <Janis.Papanagnou@pc-plus.de> writes:


>I made the following observation, and I think the behaviour of the
>istrstream operator>> behaves buggy with strings (see *** below):

>    char c;  istrstream is ("x");
>    is >> c;  cerr << is.good() << endl;      // 1 - OK
>    is >> c;  cerr << is.good() << endl;      // 0 - OK, eof

>    int i;  istrstream is ("123");
>    is >> i;  cerr << is.good() << endl;      // 1 - OK
>    is >> i;  cerr << is.good() << endl;      // 0 - OK, eof

>    char s [42];  istrstream is ("word");
>    is >> s;  cerr << is.good() << endl;      // 0 - BUG !?   ***
>    is >> s;  cerr << is.good() << endl;      // 0 - OK, eof

The behavior you see is not wrong.

The "good" state means that none of "fail", "bad", or "eof"
states is set. Exactly when eof beocomes true is unspecified.
That is, the stream can report eof after reading the last
character of a stream, or wait until attempting the next read.

Consequently, you should not usually test eof after a read,
but only before the next read. Eof being true tells you nothing
about whether the previous read was successful. If eof is
true, the next read will fail, and that's all it means.

Since "good" depends on eof, good being false tells you nothing
about whether a previous read succeeded, and you should test
for that state only *before* attempting to read, not after.

The appropriate test *after* an input operation is "fail".
Fail does not depend on eof, but reports only whether the
previous operation succeeded.

If an input operation results in "fail", you can then test
for eof to see if that was the reason for the failure.

Testing the stream directly, such as
 if( mystream ) ...
 if( !mystream ) ...
is equivalent to testing "fail".

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Janis Papanagnou <Janis.Papanagnou@pc-plus.de>
Date: 1999/03/03
Raw View
Steve Clamage wrote:
>
> Janis Papanagnou <Janis.Papanagnou@pc-plus.de> writes:
> [...]
>
> The behavior you see is not wrong.
>
> The "good" state means that none of "fail", "bad", or "eof"
> states is set. Exactly when eof beocomes true is unspecified.

That's a pitty.

> That is, the stream can report eof after reading the last
> character of a stream, or wait until attempting the next read.
>
> Consequently, you should not usually test eof after a read,
> but only before the next read.

That won't change things (see example and your statement below).

> Eof being true tells you nothing
> about whether the previous read was successful. If eof is
> true, the next read will fail, and that's all it means.

The same holds if eof is false: the next read might fail, depending
on the type that is read.

I extend the example and print the states before and after reading
the stream:

    // good() fail() bad() eof()  ->  // G F B E

    char c; istrstream is ("x");
    print_states (is);  is >> c;      // 1 0 0 0
    print_states (is);  is >> c;      // 1 0 0 0
    print_states (is);                // 0 2 0 1

    int i; istrstream is ("123");
    print_states (is);  is >> i;      // 1 0 0 0
    print_states (is);  is >> i;      // 1 0 0 0
    print_states (is);                // 0 2 0 1

    char s [42]; istrstream is ("word");
    print_states (is);  is >> s;      // 1 0 0 0
    print_states (is);  is >> s;      // 0 0 0 1   (***)
    print_states (is);                // 0 2 0 1

Apparently you cannot rely on eof, especially when using arbitrary
types in template instantiations, as I was trying to do !

> Since "good" depends on eof, good being false tells you nothing
> about whether a previous read succeeded, and you should test
> for that state only *before* attempting to read, not after.
>
> The appropriate test *after* an input operation is "fail".
> Fail does not depend on eof, but reports only whether the
> previous operation succeeded.

Using these two flags *instead* of eof is the solution for my problem.
Thank you for the clarification !

> If an input operation results in "fail", you can then test
> for eof to see if that was the reason for the failure.

So eof() is *only* well defined in the case when fail() is true.
That's an important statement.

> Testing the stream directly, such as
>         if( mystream ) ...
>         if( !mystream ) ...
> is equivalent to testing "fail".


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James.Kanze@dresdner-bank.com
Date: 1999/03/03
Raw View
In article <36DBED1B.41C6@pc-plus.de>,
  Janis Papanagnou <Janis.Papanagnou@pc-plus.de> wrote:
>
> I made the following observation, and I think the behaviour of the
> istrstream operator>> behaves buggy with strings (see *** below):
>
>     char c;  istrstream is ("x");
>     is >> c;  cerr << is.good() << endl;      // 1 - OK
>     is >> c;  cerr << is.good() << endl;      // 0 - OK, eof
>
>     int i;  istrstream is ("123");
>     is >> i;  cerr << is.good() << endl;      // 1 - OK
>     is >> i;  cerr << is.good() << endl;      // 0 - OK, eof
>
>     char s [42];  istrstream is ("word");
>     is >> s;  cerr << is.good() << endl;      // 0 - BUG !?   ***
>     is >> s;  cerr << is.good() << endl;      // 0 - OK, eof
>
> Reading in a 'string' type gives the same output, because it relies
> directly on the char* implementation in our library.
>
> My expecation would be, that reading a "word" once should keep the
> state of the stream good, but our compiler sets the eof flag.
> And please compare the behaviour with the integer example "123",
> that works as expected, indeed.
> The (old) draft standard document does not say anything about that.
>
> On the other hand, when the istrstreams are initialized with data
> terminated by a newline:
>
>     istrstream is ("x\n");
>     istrstream is ("123\n");
>     istrstream is ("word\n");
>
> everything works as expected (output is: 1 0 1 0 1 0).
>
> Could someone please enlighten me, whether the behaviour is a bug
> or conforming to the standard.

It's conforming.  Basically, ios::good() only returns 1 if *all* bits
are 0, including eofbit.  And when the last read has succeeded, but the
next will fail, the status of eofbit is not defined.

--
James Kanze                                           GABI Software, S   rl
Conseils en informatique orient    objet  --
                          --  Beratung in industrieller Datenverarbeitung
mailto: kanze@gabi-soft.fr          mailto: James.Kanze@dresdner-bank.com

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]