 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Jeff Guest
|
Posted: Mon Dec 15, 2003 10:23 am Post subject: Accelerated c++ ch4 question, read_hw function |
|
|
Hello,
I'm working through the book Accelerated C++ (2nd printing), and have
found a possible problem in Chapter 4 ... at least, that's how it
looks to me.
The program in this section involves creating a function to read an
arbitrary amount of input into a vector<double> (sec 4.1.3). Quote:
"There is a problem in designing the behaviour of such a function: It
needs to return two values at once. One value is, of course, the
homework grades that it read. The other is an indication of whether
the attempted input was successful."
The authors propose:
istream& read_hw(istream& in, vector<double>& hw) {
// do stuff
return in;
}
This allows the user to check the state of the stream to see if the
the read was successful. As the say, this function allows the caller
to write:
if (read_hw(cin, homework)) { /* ... */ }
However (and here's the problem I see), read_hw is implemented as
follows (pg 57):
istream& read_hw(istream& in, vector<double>& hw)
{
if (in) {
hw.clear();
double x;
while (in >> x)
hw.push_back(x);
in.clear(); // clear the stream so that input will work for the
next student
}
return in;
}
Since the stream is cleared (error state is reset) with the call
in.clear(), won't read_hw /always/ return "true" (so to speak - I know
that it's not really a boolean)? In other words, wouldn't the user
call
if (read_hw(cin, homework)) { /* ... successful read code ... */ }
/always/ excute the "successful read code" block?
In other words, it seems to me that the function doesn't really return
2 values, it just modifies the vector and resets the error state of
the istream (the caller isn't really notified if the read was
successful or not).
I'd appreciate any insight into this.
Jeff
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Mon Dec 15, 2003 3:46 pm Post subject: Re: Accelerated c++ ch4 question, read_hw function |
|
|
In article <7b01eaf3.0312142010.19974ef4 (AT) posting (DOT) google.com>, Jeff
<jeffz_2002 (AT) yahoo (DOT) com> writes
| Quote: | The program in this section involves creating a function to read an
arbitrary amount of input into a vector<double> (sec 4.1.3). Quote:
"There is a problem in designing the behaviour of such a function: It
needs to return two values at once. One value is, of course, the
homework grades that it read. The other is an indication of whether
the attempted input was successful."
The authors propose:
istream& read_hw(istream& in, vector<double>& hw) {
// do stuff
return in;
}
This allows the user to check the state of the stream to see if the
the read was successful. As the say, this function allows the caller
to write:
if (read_hw(cin, homework)) { /* ... */ }
However (and here's the problem I see), read_hw is implemented as
follows (pg 57):
istream& read_hw(istream& in, vector<double>& hw)
{
if (in) {
hw.clear();
double x;
while (in >> x)
hw.push_back(x);
in.clear(); // clear the stream so that input will work for the
next student
}
return in;
}
Writing robust input code, particular where console input may be |
involved, is a tedious task requiring lots of fiddly detail as well as
making design decisions.
For example input may fail because of end of file, that is fine and in a
case such as the above we should clear the flag and return. However what
about the cases where input fails for some other reason, should we not
be handling that case differently? The above does not do that. But it is
simple implementation code and will certainly work in most contexts
(personally I would like to special case the circumstance where there is
no accepted input because otherwise the caller of the function has to
detect that the vector is empty rather than assume that it is not.
There are many issue with the actual implementation, but a strong point
is that the programmer can work on those in isolation from the caller
and move from something such as the above to something more robust.
For example, I would special case console input (it needs prompts, it
probably needs information about how to end input etc. But I would also
want to do more than just return to the caller if the input was not
usable as a double.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Mon Dec 15, 2003 9:45 pm Post subject: Re: Accelerated c++ ch4 question, read_hw function |
|
|
On 15 Dec 2003 05:23:29 -0500, [email]jeffz_2002 (AT) yahoo (DOT) com[/email] (Jeff) wrote:
| Quote: | I'm working through the book Accelerated C++ (2nd printing), and have
found a possible problem in Chapter 4 ... at least, that's how it
looks to me.
|
Actually, it is just one of those things that all instructors do to
give simple solutions to hard problems for beginners.
| Quote: | The program in this section involves creating a function to read an
arbitrary amount of input into a vector<double> (sec 4.1.3). Quote:
"There is a problem in designing the behaviour of such a function: It
needs to return two values at once. One value is, of course, the
homework grades that it read. The other is an indication of whether
the attempted input was successful."
The authors propose:
istream& read_hw(istream& in, vector<double>& hw) {
// do stuff
return in;
}
This allows the user to check the state of the stream to see if the
the read was successful. As the say, this function allows the caller
to write:
if (read_hw(cin, homework)) { /* ... */ }
|
That would not work, but they did not use it.
| Quote: | However (and here's the problem I see), read_hw is implemented as
follows (pg 57):
istream& read_hw(istream& in, vector<double>& hw)
{
if (in) {
|
This if makes the program work in spite of this questionable function.
| Quote: | hw.clear();
double x;
while (in >> x)
hw.push_back(x);
in.clear(); // clear the stream so that input will work for the
next student
|
The stream had to fail to exit the loop. The failure will be an
attempt to read when either at end of file or at bad data. The actual
assumption is that there will be no bad homeword grades and the read
will fail on trying to read the next students name into an int.
A real solution to the problem would be to use getline to read the
entire line and then create an istringstream to read the pieces for
that student. Errors could then be detected. That is a bit much
for chapter four.
Other attempts to fake it also have cases that will not work.
| Quote: | }
return in;
}
Since the stream is cleared (error state is reset) with the call
in.clear(), won't read_hw /always/ return "true" (so to speak - I know
that it's not really a boolean)? In other words, wouldn't the user
call
if (read_hw(cin, homework)) { /* ... successful read code ... */ }
/always/ excute the "successful read code" block?
In other words, it seems to me that the function doesn't really return
2 values, it just modifies the vector and resets the error state of
the istream (the caller isn't really notified if the read was
successful or not).
|
If you go on to page 62 where the function is used in reading all of the
information for a student, you will see why this works in the program.
The function reads the name and two test grades. If this fails, the
istream will be in a bad condition and the if in read_hw prevents it
from clearing the error condition. The read student then returns the
failed stream to the main program which is doing while (read(cin,
record)). The input loop stops normally at eof because the attempt to
read the next student fails.
This is a beginners book and input with errors is beyond its scope. We
might question the value of using this cute method to detect the end of
a list of homework grades by getting an error but the alternatives are
not all that nice. Valid input is a reasonable assumption for exercises
as the alternative would tripple the size of the book for little value.
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Tue Dec 16, 2003 3:41 pm Post subject: Re: Accelerated c++ ch4 question, read_hw function |
|
|
Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> wrote
| Quote: | For example input may fail because of end of file, that is fine and in
a case such as the above we should clear the flag and return.
|
Should we clear the flag? In the general case, I don't think you should
ever clear eofbit unless you definitly want to retry actually reading
data at the system level -- there are all too many implementations of
filebuf where sgetc will NOT return EOF if it is called a second time.
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Balog Pal Guest
|
Posted: Wed Dec 17, 2003 4:37 pm Post subject: Re: Accelerated c++ ch4 question, read_hw function |
|
|
"Jeff" <jeffz_2002 (AT) yahoo (DOT) com> wrote
| Quote: | The program in this section involves creating a function to read an
arbitrary amount of input into a vector<double> (sec 4.1.3). Quote:
"There is a problem in designing the behaviour of such a function: It
needs to return two values at once. One value is, of course, the
homework grades that it read. The other is an indication of whether
the attempted input was successful."
The authors propose:
istream& read_hw(istream& in, vector<double>& hw) {
// do stuff
return in;
}
This allows the user to check the state of the stream to see if the
the read was successful.
|
Huh. That change really looks awful for the text presented. Returning the
stream as presented here is cool for one reason: to allow chaining calls.
Wrt reporting error the change is redundant, as it returns nothing new,
nothing the user doesn't have. Suppose we change the function to return
void -- the user still has the stream at hand an can as well check its
status. So we could return the vector in place of void. (well, a MOJO-ed
version if we case speed. )
To really address the problem in the text that function should look like
that, but return a bool or int or enum or something like that, reporting the
result.
| Quote: | However (and here's the problem I see), read_hw is implemented as
follows (pg 57): ...
|
| Quote: | istream& read_hw(istream& in, vector<double>& hw)
{
if (in) {
hw.clear();
double x;
while (in >> x)
hw.push_back(x);
in.clear(); // clear the stream so that input will work for the
next student
}
return in;
}
|
When I write a function that returns the stream it's called on, it never
clears the stream, whatever happens. (well, unless it's desc explicitely
states the conditions...) the calles shall examine the stream when it likes
and do what is due. [Typically the user reads a file, and there's a single
check at the end, if everything happened as expected. anything between just
builds on the stickybit error handling.]
I guess this example reads console with interactive user -- sure it needs a
clear() before the next input, I'd put it at the caller site. Also, in the
function I'd clear the vector outside the if -- it's present contents are
sure bad to continue with, and empty state well reflects even the error
condition's result.
Paul
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Thu Dec 18, 2003 8:43 am Post subject: Re: Accelerated c++ ch4 question, read_hw function |
|
|
On 17 Dec 2003 11:37:32 -0500, "Balog Pal" <pasa (AT) lib (DOT) hu> wrote:
| Quote: | "Jeff" <jeffz_2002 (AT) yahoo (DOT) com> wrote in message
news:7b01eaf3.0312142010.19974ef4 (AT) posting (DOT) google.com...
The program in this section involves creating a function to read an
arbitrary amount of input into a vector<double> (sec 4.1.3). Quote:
"There is a problem in designing the behaviour of such a function: It
needs to return two values at once. One value is, of course, the
homework grades that it read. The other is an indication of whether
the attempted input was successful."
The authors propose:
istream& read_hw(istream& in, vector<double>& hw) {
// do stuff
return in;
}
This allows the user to check the state of the stream to see if the
the read was successful.
Huh. That change really looks awful for the text presented. Returning the
stream as presented here is cool for one reason: to allow chaining calls.
|
Change the name to operator>> and the interface is obviously correct.
| Quote: | Wrt reporting error the change is redundant, as it returns nothing new,
nothing the user doesn't have. Suppose we change the function to return
void -- the user still has the stream at hand an can as well check its
status. So we could return the vector in place of void. (well, a MOJO-ed
version if we case speed. )
|
Yep. The code is good, the reasons are nonsense. It is used only on
known valid data, the return is never checked, and the status of the
stream never changes between input and return.
| Quote: | To really address the problem in the text that function should look like
that, but return a bool or int or enum or something like that, reporting the
result.
|
Just like getline?
| Quote: | However (and here's the problem I see), read_hw is implemented as
follows (pg 57): ...
istream& read_hw(istream& in, vector<double>& hw)
{
if (in) {
hw.clear();
double x;
while (in >> x)
hw.push_back(x);
in.clear(); // clear the stream so that input will work for the
next student
}
return in;
}
When I write a function that returns the stream it's called on, it never
clears the stream, whatever happens. (well, unless it's desc explicitely
states the conditions...) the calles shall examine the stream when it likes
and do what is due. [Typically the user reads a file, and there's a single
check at the end, if everything happened as expected. anything between just
builds on the stickybit error handling.]
|
Read the book and the problem it solves.
| Quote: | I guess this example reads console with interactive user -- sure it needs a
clear() before the next input, I'd put it at the caller site.
|
It reads a file and uses an attempt to read a letter into a double to
indicate a break in the data. A data element consists of a name (one
word) followed by two or more numbers. There are an unknown number of
data elements. There are no errors in the input. If you have a better
design for chapter four of a beginners book, please post it.
| Quote: | Also, in the
function I'd clear the vector outside the if -- it's present contents are
sure bad to continue with, and empty state well reflects even the error
condition's result.
|
Compare what that function does to operator>> for string. Since they
are identical with the exception of the clear, what are you saying about
the people who wrote the standard?
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|