Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Strstream and detection of EOF

23 views
Skip to first unread message

Ron

unread,
Dec 27, 2011, 3:54:19 PM12/27/11
to
Hello, I am a new user of Open Watcom and I have a question:

Can anyone tell me why the following code does
not seem to detect EOF, thus producing an extra P?

/* This program shows how to read the contents of any
array that contains text. */
#include <strstrea.h>
#include <iostream.h>

int main()
{
char s[] = "abcdefghijklmnop";

istrstream ins(s);

char ch;

//This will read the contents of any type of array.
while(!ins.eof()) {
ins.get(ch);
cout << ch; //shows a duplicate p, eof()
//not active on (strstrmbuf) __get_ptr == __get_end ("")
}

return 0;
}

Thanks and regards,
Ron K

Roald Ribe

unread,
Dec 28, 2011, 12:50:54 PM12/28/11
to
I have not tested it, but from one reading of the program the loop looks like
it should be a do/while(!EOF) rather than what it is now.
The problem with it now is that cout << ch will be performed once after
EOF has been reached.
This is not special for OW, would happen in any compiler I expect.

Roald

Roald Ribe

unread,
Dec 28, 2011, 1:25:06 PM12/28/11
to
While reading something else my brain threw a warning :-)
The analysis is correct, but the suggested solution is wrong.
A real solution is this:

ins.get(ch);
while(!ins.eof()) {
cout << ch; //shows a duplicate p, eof()
ins.get(ch);
}

Roald

Paul S. Person

unread,
Dec 28, 2011, 1:32:17 PM12/28/11
to
As Roald Ribe points out, this is one of those cases where you need to
rethink the loop.

Try this first:

ins.get(ch);
> while(!ins.eof()) {
> cout << ch; //shows a duplicate p, eof()
ins.get(ch);
> }

so that the test is done on the character you are planning to output.

A lot of while() loops appear to require an initial step which does
some processing before entering the loop. And a lot of them appear to
require a final step processing the element that triggered exit from
the loop -- not this one, of course. You have to pay attention to the
loop condition and consider it as a boundary condition which may
require special processing.
--
"'If God foreknew that this would happen,
it will happen.'"

Ron

unread,
Dec 28, 2011, 4:27:32 PM12/28/11
to

On 28-Dec-2011, Paul S. Person <pspe...@ix.netscom.com.invalid> wrote:

> As Roald Ribe points out, this is one of those cases where you need to
> rethink the loop.
>
> Try this first:
>
> ins.get(ch);
> > while(!ins.eof()) {
> > cout << ch; //shows a duplicate p, eof()
> ins.get(ch);
> > }
>
> so that the test is done on the character you are planning to output.

Thanks Paul and Roald for the quick response. The code above does solve the
problem of the duplicate p. However, when I initially started looking at
this I compared it with some textbook examples of "normal" stream writing.
The "normal" get() method is illustrated in binary mode where "when the end
of file is reached, the stream associated with the file becomes zero." This
implies that the eof flag is set when the last byte is read. Any thoughts on
the ability of get() to know when the __get_ptr == __get_end?

Best regards,
Ron

E. S. Fabian

unread,
Dec 28, 2011, 6:54:50 PM12/28/11
to
| I compared it with some textbook examples of
| "normal" stream writing. The "normal" get() method is illustrated in
| binary mode where "when the end of file is reached, the stream
| associated with the file becomes zero." This implies that the eof
| flag is set when the last byte is read. Any thoughts on the ability
| of get() to know when the __get_ptr == __get_end?

I believe you misinterpreted the phrase "when the end of file is reached,
the stream associated with the file becomes zero." When you read one byte at
a time, e.g., using get(), getting the last byte is like an elevator
reaching the bottom floor. It does not fail to proceed further unless you
try to go "down". Analogously, when you get() the last character of the file
/ stream, it is a valid character, and EOF indications are not set - what if
you were "throwing an exception" on EOF? You'd lose the last valid
character. Only when you try to read PAST the EOF is the flag set. This is
similar to requesting to read 5 bytes when reading a file in blocks, and
there are at least 5 bytes left before EOF.
--
HTH, Steve


Roald Ribe

unread,
Dec 28, 2011, 11:14:57 PM12/28/11
to
No. It implies only that the EOF flag is set when the end of file is reached.
When is that? When you read _beyond_ the last character in the "file".
In C (no ++) the loop would look like this:
while((c=getc(file)) != EOF) {
putc(c);
}

To put that into practice, one could rewrite your C++ loop to:
while(ins.get(ch) && (ins.eof()==FALSE)) {
cout << ch;
}

But that might get you into problems with a binary file/stream.

Roald

Ron

unread,
Dec 29, 2011, 8:09:15 PM12/29/11
to

On 28-Dec-2011, "Roald Ribe" <roald...@hotmail.com> wrote:

> To put that into practice, one could rewrite your C++ loop to:
> while(ins.get(ch) && (ins.eof()==FALSE)) {
> cout << ch;
> }
>
> But that might get you into problems with a binary file/stream.

That's interesting: so the get happens first and therefore eof should be set
when ==FALSE is evaluated. Here is a similar issue with istrstream I/O that
I encountered by accidentally omitting the unsetf(ios::skipws).

/* This program shows how to read the contents of any
array that contains text. */
#include <strstrea.h>
#include <iostream.h>

int main()
{
char s[] = "10.23 this is a test !#?@\n";

istrstream ins(s);

char ch;

/* This will read and display the contents
of any text array. */
// ins.unsetf(ios::skipws); //don't skip spaces
while(ins) { //0 when end of array is reached
ins >> ch;
cout << ch; //shows a duplicate @ without unsetf skipws command
}

return 0;
}

Best regards, Ron

Steve Fabian

unread,
Dec 29, 2011, 9:14:22 PM12/29/11
to
Think of get() this way. You have a text string of unknown length in
Braille. get() moves your finger to the next character if it exists, but
that does detect yet whether or not there is yet another one. Only when
another get() moves your finger to where is no character do you know you are
done - i.e., EOF.


Kevin G. Rhoads

unread,
Dec 30, 2011, 10:55:23 AM12/30/11
to
>You have a text string of unknown length in
>Braille. get() moves your finger to the next character if it exists,

Oooh, good one. I'm a strong believer in the use of good analogies in teaching,
and this one is a good one. Thank you, Steve!
0 new messages