the book has those variables outside the while loop |
This is a common thing in many books that follow an older C-style design.
Back when we were all wee laddies (or not yet born!) C required all variables to be declared before any statements. So:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
void my_func()
{
int x;
char * s;
float f;
for (x = 0; x < 10; x++)
{
s = ...;
}
f = ...;
}
|
(Even back then you could use curly braces {
,}
to create a local lexical context and keep stuff together, but few people ever did...)
It appears your book is following that way of thinking. It’s not...
wrong, per se, but it isn’t the way modern C++ (and C!) should be written.
The thing to remember is that
the compiler can do it better than you can. Hard to accept, but true. Let the compiler do its job.
If the line below replaces the internal buffer with the string, shouldn't it internally just reset the bit flags as well? [...] |
You’d think so, but that’s not how the class was designed to function. I’m pretty sure there’s an actual reason for that. I don’t know what it is. It has never caused me any difficulties.
It looks like they are suggesting terminating the program when the cin stream is bad. Is this what is done? |
Maybe. Depends on your program.
Or if the cin was trivial in only getting the user name and you never relied on it again, can you bypass using the cin again (and use a default name) and continue your program? |
Sure. However you design your program to work.
Or does a bad cin indicate something more sinister? |
Remember, standard input is just another input stream. A special one, yes, but a character file none-the-less.
Remember,
all streams can have:
• an end
• access/privilege errors
• data your program does not like
For standard input, the user can terminate it by pressing
Ctrl+Z,
Enter (Windows) or
Ctrl+D (*nixen), or by simply redirecting a normal file from disk to it, or a piped file from another utility to it, etc.
If the file simply does not contain data you like that is something the program should handle.
Part of the problem is that code like this is exampled almost everywhere, and it is almost always WRONG. (With capital everything.)
(The same holds true for
scanf()
, but I’ll leave that rant for another day.)
There are two issues:
• Text files, and standard input specifically, are
line based data.
• C++ streams allow you to goober the state of the stream more or less permanently.
Use
getline()
to obtain a line of input from
cin
(or your
ifstream
), then use an
istringstream
to parse it.
Likewise, use an
ostringstream
to format data, then send the resulting string through
cout
(or your
ofstream
object).
This is because
cin
,
cout
, and
cerr
are
global, shared resources. If you jack its state, some other part of your program may very well malfunction when attempting to use it.
Hence, use a local, temporary stringstream to do things like set persistent formatting preferences and simply pass the string data through the standard streams unmodified.
This, of course, requires a little more care when programming, and tends to make writing short examples harder in how-to books, websites, etc, so you see a lot of
1 2 3 4 5
|
cout << hex << STUFF;
...
/* end of program */
|
Instead of the more correct:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
std::ostream & operator << ( std::ostream & outs, Stuff stuff )
{
std::ostringstream oss;
oss << hex << stuff.value;
return outs << oss.str();
}
...
int main()
{
Stuff my_stuff;
...
std::cout << my_stuff << "\n";
}
|
Meh. Enough ranting. :O)
seeplus wrote: |
---|
You can even do this:
1 2 3
|
// Attempt to read a line and print the values we got
if (double low, high; ss >> low >> high)
std::cout << std::setw(8) << low << std::setw(8) << high << "\n";
|
|
I still don’t know how I feel about that. In one way it is definitely welcome — the ability to declare a variable in-line and use it is nice...
But it comes at the cost of obscure syntax. I mean, I know what it means and can read it just fine, but it still takes a second to process, where the following is just so much more straight-forward:
1 2 3
|
double low, high; // ah, variables! one named "low" and another "high"
if (ss >> low >> high) // hey, an "if" statement. Easy peasy!
...
|
If scope of those two variables is an issue, a pair of curly braces
{
,
}
fixes that easily enough and remains just as readable.
The only time I can imagine such a construct being actually useful is in old & crufty macro tricks where we currently have to use a
do
..
while
loop or a GCC compiler extension.
But then, I think I tend to write fairly clean code...
IDK.