 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
dmh2000 Guest
|
Posted: Tue Jul 12, 2005 12:46 am Post subject: question on example code from Stroustrup::Design of C++0x |
|
|
CUJ May 2005 has an article by Professor Stroustrup in which he gives a
couple of examples of bad code, but in one case he doesn't clearly
explain what is wrong.
void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
His alternative solution is much simpler 'cin >> s'. But it appears to
me the 'bad code' is actually wrong, not just sloppy. 'while
(cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0? What am I missing? A google search shows other folks using
cin.get in this manner.
thanks
david howard
[email]daveh (AT) dmh2000 (DOT) com[/email]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Tue Jul 12, 2005 8:28 am Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
"dmh2000" <daveh (AT) dmh2000 (DOT) com> writes:
| Quote: | CUJ May 2005 has an article by Professor Stroustrup in which he gives a
couple of examples of bad code, but in one case he doesn't clearly
explain what is wrong.
void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
|
Probably he means to indicate that this code is
a. overly complex
b. highly error-prone (how do you know if the array p points into
will be big enough?
| Quote: | His alternative solution is much simpler 'cin >> s'. But it appears to
me the 'bad code' is actually wrong, not just sloppy. 'while
(cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0? What am I missing?
|
Streams themselves are testable as boolean expressions via a
conversion operator. They convert to false when an error has
occurred.
HTH,
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
ThosRTanner Guest
|
Posted: Tue Jul 12, 2005 8:33 am Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
dmh2000 wrote:
| Quote: | CUJ May 2005 has an article by Professor Stroustrup in which he gives a
couple of examples of bad code, but in one case he doesn't clearly
explain what is wrong.
void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
|
There is no size specified for p. Therefore it is not possible check
for overrunning of p.
For instance:
char password[20];
cout << "Please enter your password (8 to 10 chars): ";
get_input(&password[0]);
When this is run, a user types 'supercalifragelisticexpialidocious'.
Bang goes your program.
| Quote: | His alternative solution is much simpler 'cin >> s'. But it appears to
me the 'bad code' is actually wrong, not just sloppy. 'while
(cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0? What am I missing? A google search shows other folks using
cin.get in this manner.
There is a basic_istream::operator bool() which returns true unless |
there has been an error.
<rant>
IMHO this is a rather vile kludge, which appears to be vaguely related
to the implicit cast of pointer or any integer to bool, inherited from
C.
</rant>
There is a good() method which returns true, and you could write:
"while (cin.get(ch).good()) {}" (or "while (cin.get(ch), cin.good()) {
}" if you find the first form makes you choke), with no loss of
clarity.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Heinz Ozwirk Guest
|
Posted: Tue Jul 12, 2005 8:33 am Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
"dmh2000" <daveh (AT) dmh2000 (DOT) com> schrieb im Newsbeitrag
news:1121107287.497859.174050 (AT) o13g2000cwo (DOT) googlegroups.com...
| Quote: | 'while (cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0? What am I missing?
|
operator void*()
Each stream is convertable to void* and the conversion returns 0, if a
previous operation has failed.
HTH
Heinz
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ali Çehreli Guest
|
Posted: Tue Jul 12, 2005 8:34 am Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
"dmh2000" <daveh (AT) dmh2000 (DOT) com> wrote
| Quote: | CUJ May 2005 has an article by Professor Stroustrup in which he gives a
couple of examples of bad code, but in one case he doesn't clearly
explain what is wrong.
void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
His alternative solution is much simpler 'cin >> s'. But it appears to
me the 'bad code' is actually wrong, not just sloppy. 'while
(cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0? What am I missing? A google search shows other folks using
cin.get in this manner.
|
Your question applies to the alternative solution too, because 'cin >> s'
returns basic_istream& as well.
Streams can be used in place of a boolean expressions because they define
'operator void*'. That operator traditionally returns 0 when the stream is
unusable, and (I think) the address of the object when the stream is usable.
These two values decay to false and true respectably, in boolean contexts.
Ali
P.S. The reason streams don't define simply 'operator bool' is to prevent
accidentally using them in arithmetic expressions. It would be possible to
write 'cin + 42' had there been an 'operator bool' defined.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gianluca Silvestri Guest
|
Posted: Tue Jul 12, 2005 8:34 am Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
"dmh2000" <daveh (AT) dmh2000 (DOT) com> ha scritto nel messaggio
news:1121107287.497859.174050 (AT) o13g2000cwo (DOT) googlegroups.com...
| Quote: | CUJ May 2005 has an article by Professor Stroustrup in which he gives a
couple of examples of bad code, but in one case he doesn't clearly
explain what is wrong.
void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
His alternative solution is much simpler 'cin >> s'. But it appears to
me the 'bad code' is actually wrong, not just sloppy. 'while
(cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0? What am I missing? A google search shows other folks using
cin.get in this manner.
basic_ios<> has among his member functions the definition of operator |
void*() const which can be used by the compiler in boolean contexts. In fact
its semantics is to return a null pointer whenever fail() returns true and a
pointer other than null to indicate success.
HTH
Gianluca
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Tue Jul 12, 2005 8:35 am Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
"dmh2000" <daveh (AT) dmh2000 (DOT) com> writes:
| Quote: | CUJ May 2005 has an article by Professor Stroustrup in which he gives a
couple of examples of bad code, but in one case he doesn't clearly
explain what is wrong.
void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
His alternative solution is much simpler 'cin >> s'. But it appears to
me the 'bad code' is actually wrong, not just sloppy. 'while
(cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0?
|
Stream classes are derived from a specialization of the basic_ios
template which has member functions
operator void*() const
bool operator!() const
The former will return a non-null pointer if and only if the stream's
fail() member function returns false
The latter returns the same value as fail().
The real thing I don't like about BS's code is that he didn't offer
if (cin >> s)
as an alternative rather than just
cin >> s
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gene Bushuyev Guest
|
Posted: Tue Jul 12, 2005 8:35 am Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
"dmh2000" <daveh (AT) dmh2000 (DOT) com> wrote
| Quote: | CUJ May 2005 has an article by Professor Stroustrup in which he gives a
couple of examples of bad code, but in one case he doesn't clearly
explain what is wrong.
void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
His alternative solution is much simpler 'cin >> s'. But it appears to
me the 'bad code' is actually wrong, not just sloppy. 'while
(cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0? What am I missing? A google search shows other folks using
cin.get in this manner.
|
The answer is found in std::basic_ios class template that provides a
conversion operator:
operator void *( ) const;
which is 0 only when fail bit is set.
There is also another operator:
bool operator!( ) const;
which serves the same purpose.
Gene
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Tutone Guest
|
Posted: Tue Jul 12, 2005 8:36 am Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
dmh2000 wrote:
| Quote: | CUJ May 2005 has an article by Professor Stroustrup in which he gives a
couple of examples of bad code, but in one case he doesn't clearly
explain what is wrong.
void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
His alternative solution is much simpler 'cin >> s'. But it appears to
me the 'bad code' is actually wrong, not just sloppy. 'while
(cin.get(ch) ....)' shouldn't work. My library reference says
basic_istream::get(char) returns basic_istream&. How is that ever going
to be 0? What am I missing? A google search shows other folks using
cin.get in this manner.
|
std::cin has operator void*() const (or the moral equivalent) defined,
and that conversion function returns 0 when the stream is at end of
file or has an error condition. (It returns an implementation-defined
non-zero pointer otherwise.) This conversion is included so that
std::cin (and other streams) can be used in while and if statements
exactly as BS shows in the code you quoted.
But I think that the reason that BS considers this bad code is that
there is nothing to stop a buffer overrun - how ever much space you
provide in the buffer that p points to, the input from cin may be
larger. Using a std::string, as BS suggests as a better alternative,
avoids the possibility of such a buffer overrun.
Best regards,
Tom
[ 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 Jul 12, 2005 1:30 pm Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
dmh2000 wrote:
| Quote: | CUJ May 2005 has an article by Professor Stroustrup in which
he gives a couple of examples of bad code, but in one case he
doesn't clearly explain what is wrong.
|
I've not read the article, but a priori, writing a function to
do something that is already provided for in the library is
wrong.
| Quote: | void get_input(char* p)
{
char ch;
while (cin.get(ch) && !iswhite(ch)) *p++ = ch;
*p = 0;
}
His alternative solution is much simpler 'cin >> s'. But it
appears to me the 'bad code' is actually wrong, not just
sloppy.
|
It is wrong. It contains undefined behavior.
| Quote: | 'while (cin.get(ch) ....)' shouldn't work. My library
reference says basic_istream::get(char) returns
basic_istream&.
|
Then your library reference is wrong. It returns a pointer,
which will be null if the function fails.
| Quote: | How is that ever going to be 0? What am I missing? A google
search shows other folks using cin.get in this manner.
|
The problem here isn't with the cin.get(ch). One of the
problems, already mentionned, is that the function doesn't check
the length. Presumably, in Stroustrups correct example, cin >>
s, s has type std::string -- otherwise, it suffers from the same
problem.
The other problem, of course, is that calling iswhite (which
should in fact be isspace) with a char as a parameter is
undefined behavior.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Tue Jul 12, 2005 4:22 pm Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
In article <1121166700.531122.290310 (AT) g43g2000cwa (DOT) googlegroups.com>,
<kanze (AT) gabi-soft (DOT) fr> wrote:
| Quote: | 'while (cin.get(ch) ....)' shouldn't work. My library
reference says basic_istream::get(char) returns
basic_istream&.
Then your library reference is wrong. It returns a pointer,
which will be null if the function fails.
|
Not according to my copy of the standard its prototype is
basic_istream<C,T> & basic_istream<C,T>::get(C &c);
[iso/iec 14882,section 27.6.1.3 para 5].
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Tutone Guest
|
Posted: Tue Jul 12, 2005 10:42 pm Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
[snip]
| Quote: | 'while (cin.get(ch) ....)' shouldn't work. My library
reference says basic_istream::get(char) returns
basic_istream&.
Then your library reference is wrong. It returns a pointer,
which will be null if the function fails.
|
My library references must be wrong too, then. All of my
references say that basic_istream::get(char_type&) returns a
basic_istream&, as the OP said. That basic_istream& is then
convertible to a pointer to const void (which, as you said, will be
zero if the istream& isn't providing any more characters).
Best regards,
Tom
[ 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: Wed Jul 13, 2005 12:54 pm Post subject: Re: question on example code from Stroustrup::Design of C++0 |
|
|
Thomas Tutone wrote:
| Quote: | kanze (AT) gabi-soft (DOT) fr wrote:
[snip]
'while (cin.get(ch) ....)' shouldn't work. My library
reference says basic_istream::get(char) returns
basic_istream&.
Then your library reference is wrong. It returns a pointer,
which will be null if the function fails.
My library references must be wrong too, then. All of my
references say that basic_istream::get(char_type&) returns a
basic_istream&, as the OP said. That basic_istream& is then
convertible to a pointer to const void (which, as you said,
will be zero if the istream& isn't providing any more
characters).
|
Yes. I short-cut a few steps in there -- I'm so used to the way
I use streams, that I didn't think about the actual definition.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ 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
|
|