Correction of FAQ - [15.5]

I

Ioannis Vranos

The FAQ at 15.5 mentions:

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5



---------- From the FAQ ----------

Because the eof state may not get set until after a read is attempted past the end of file. That is, reading
the last byte from a file might not set the eof state. E.g., suppose the input stream is mapped to a keyboard
— in that case it's not even theoretically possible for the C++ library to predict whether or not the
character that the user just typed will be the last character.

For example, the following code might have an off-by-one error with the count i:

int i = 0;
while (! std::cin.eof()) { // WRONG! (not reliable)
std::cin >> x;
++i;
// Work with x ...
}

What you really need is:

int i = 0;
while (std::cin >> x) { // RIGHT! (reliable)
++i;
// Work with x ...
}

----------------------------------


At the last while condition, when the last character is read, EOF will not have been read, so the condition
will not evaluate to true, variable i will be incremented, and object x will be processed.


Then, when EOF will be read, the condition while (std::cin >> x) will still not evaluate to true, and variable
i will be incremented again, and object x will be processed again.



Then, when EOF will be read again, the condition while (std::cin >> x) will evaluate to true.


Therefore, I think the last code should be corrected to:


int i = 0;
while (std::cin >> x and not std::cin.eof()) { // RIGHT! (reliable)
++i;
// Work with x ...
}



or better to:


int i = 0;
while (std::cin.good()) { // RIGHT! (reliable)

std::cin >> x

++i;

// Work with x ...
}



--
Ioannis A. Vranos

C95 / C++03 Developer

http://www.cpp-software.net
 
A

Alf P. Steinbach

Hm, last time I helped you with your BCD question, then you responded by posting
an article calling me a troll, so I'm less than very much inclined to help you
here. However, it would be silly of me to bear grudges. So.


* Ioannis Vranos:
The FAQ at 15.5 mentions:

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5



---------- From the FAQ ----------

Because the eof state may not get set until after a read is attempted
past the end of file. That is, reading the last byte from a file might
not set the eof state. E.g., suppose the input stream is mapped to a
keyboard — in that case it's not even theoretically possible for the C++
library to predict whether or not the character that the user just typed
will be the last character.

For example, the following code might have an off-by-one error with the
count i:

int i = 0;
while (! std::cin.eof()) { // WRONG! (not reliable)
std::cin >> x;
++i;
// Work with x ...
}

What you really need is:

int i = 0;
while (std::cin >> x) { // RIGHT! (reliable)
++i;
// Work with x ...
}

----------------------------------


At the last while condition, when the last character is read, EOF will
not have been read, so the condition will not evaluate to true, variable
i will be incremented, and object x will be processed.
OK.


Then, when EOF will be read, the condition while (std::cin >> x) will
still not evaluate to true, and variable i will be incremented again,
and object x will be processed again.

No. When a read is attempted past the end of the file, then eof and failbit are
set. eof because eof has been detected, and failbit because the read failed. The
while loop continuation condition 'std::cin >> x' is just the stream object,
which via an indirect conversion to bool is equivalent to '!(std::cin >>
x).fail()', testing the failbit. So, since fail() is now 'true', it evaluates to
'false', terminating the loop.

Then, when EOF will be read again, the condition while (std::cin >> x)
will evaluate to true.


Therefore, I think the last code should be corrected to:


int i = 0;
while (std::cin >> x and not std::cin.eof()) { // RIGHT! (reliable)
++i;
// Work with x ...
}

Nope, see above.

or better to:


int i = 0;
while (std::cin.good()) { // RIGHT! (reliable)

std::cin >> x

++i;

// Work with x ...
}

Nope, for two reasons. First, s.good() is not the negation of s.fail(). Second,
this code fails to check whether the read of x succeeded or not before using x.


Cheers & hth.,

- Alf
 
I

Ioannis Vranos

Alf said:
Hm, last time I helped you with your BCD question, then you responded by
posting an article calling me a troll, so I'm less than very much
inclined to help you here. However, it would be silly of me to bear
grudges. So.


* Ioannis Vranos:

No. When a read is attempted past the end of the file, then eof and
failbit are set. eof because eof has been detected, and failbit because
the read failed. The while loop continuation condition 'std::cin >> x'
is just the stream object, which via an indirect conversion to bool is
equivalent to '!(std::cin >> x).fail()', testing the failbit. So, since
fail() is now 'true', it evaluates to 'false', terminating the loop.



Nope, see above.



Nope, for two reasons. First, s.good() is not the negation of s.fail().
Second, this code fails to check whether the read of x succeeded or not
before using x.


Cheers & hth.,



You are a troll.



--
Ioannis A. Vranos

C95 / C++03 Developer

http://www.cpp-software.net
 
B

Bart van Ingen Schenau

Ioannis said:
The FAQ at 15.5 mentions:

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5

---------- From the FAQ ----------

Because the eof state may not get set until after a read is attempted
past the end of file. That is, reading the last byte from a file might
not set the eof state. E.g., suppose the input stream is mapped to a
keyboard ? in that case it's not even theoretically possible for the
C++ library to predict whether or not the character that the user just
typed will be the last character.

For example, the following code might have an off-by-one error with
the count i:

int i = 0;
while (! std::cin.eof()) { // WRONG! (not reliable)
std::cin >> x;
++i;
// Work with x ...
}

What you really need is:

int i = 0;
while (std::cin >> x) { // RIGHT! (reliable)
++i;
// Work with x ...
}

----------------------------------


At the last while condition, when the last character is read, EOF will
not have been read, so the condition will not evaluate to true,
variable i will be incremented, and object x will be processed.
Yes.


Then, when EOF will be read, the condition while (std::cin >> x) will
still not evaluate to true, and variable i will be incremented again,
and object x will be processed again.

No. If the remainder of the stream can not be converted to a value of
the type of x, then the condition while (std::cin >> x) will evaluate to
false, because operator>> caused the failbit to be set. The loop will be
exited.
Then, when EOF will be read again, the condition while (std::cin >> x)
will evaluate to true.


Therefore, I think the last code should be corrected to:


int i = 0;
while (std::cin >> x and not std::cin.eof()) { // RIGHT!
(reliable)
++i;
// Work with x ...
}

No, this is not reliable. There is a situation where std::cin.eof()
returns true, but std::cin >> x also was able to successfully read a new
value for x from the stream.

operator>> works like this:
1. Determine a scanf-equivalent conversion specifier for the type being
read.
2. Extract characters from the stream until either EOF is reached or the
next character does not fit the conversion.
3. Convert the extracted characters and set the flags. Two flags can be
set independently of each other:
3a. If no characters were extracted or the conversion failed, the
failbit is set.
3b. If step 2 ended on the EOF condition, the eofbit is set.

If, for example, the stream std::cin contains the characters "123" and
after the '3' it immediately signals EOF, then
int x = 0;
std::cin >> x;
would store the number 123 in x and set the eofbit in std::cin.
In your loop above, the number 123 would not get processed.
or better to:


int i = 0;
while (std::cin.good()) { // RIGHT! (reliable)

std::cin >> x

If std::cin only contains whitespace, this read operation will fail,
causing the previous value of x to be processed twice.
++i;

// Work with x ...
}
Bart v Ingen Schenau
 
I

Ioannis Vranos

Ioannis said:
The FAQ at 15.5 mentions:

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5



---------- From the FAQ ----------

Because the eof state may not get set until after a read is attempted
past the end of file. That is, reading the last byte from a file might
not set the eof state. E.g., suppose the input stream is mapped to a
keyboard — in that case it's not even theoretically possible for the C++
library to predict whether or not the character that the user just typed
will be the last character.

For example, the following code might have an off-by-one error with the
count i:

int i = 0;
while (! std::cin.eof()) { // WRONG! (not reliable)
std::cin >> x;
++i;
// Work with x ...
}

What you really need is:

int i = 0;
while (std::cin >> x) { // RIGHT! (reliable)
++i;
// Work with x ...
}

----------------------------------


At the last while condition, when the last character is read, EOF will
not have been read, so the condition will not evaluate to true, variable
i will be incremented, and object x will be processed.


Then, when EOF will be read, the condition while (std::cin >> x) will
still not evaluate to true, and variable i will be incremented again,
and object x will be processed again.



Then, when EOF will be read again, the condition while (std::cin >> x)
will evaluate to true.


Therefore, I think the last code should be corrected to:


int i = 0;
while (std::cin >> x and not std::cin.eof()) { // RIGHT! (reliable)
++i;
// Work with x ...
}



or better to:


int i = 0;
while (std::cin.good()) { // RIGHT! (reliable)

std::cin >> x

++i;

// Work with x ...
}


I am wrong.



--
Ioannis A. Vranos

C95 / C++03 Developer

http://www.cpp-software.net
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top