V
vineoff
Thank you all guys!
* Kai-Uwe Bux -> Neil Cerutti:
One crucial thing here is the name change, to reflect what the
function produces. I don't think I could guess from the name
'ranged_prompt' (the OP's choice) that it actually does input.
I'd guess it produced a prompt.
Of course for good measure -- less Undefined Behavior, those
iostreams aren't my favorite beasts!
-- one should read in a
whole line using getline, and parse it using strtol or strtod
as appropriate (not a stringstream)...
In this situation, you seem to be iterating once over three coordinates.Tatu said:It is not efficient.
Alf said:A Do-It-Yourself RAII-based version might go like this:
StreamCleanup cleaner( std::cin );
* Alf P. Steinbach:
Very nice solution
Warning (line N): Unused variable 'cleaner' ...
How do you work around that warning (without introducing some silly
cleaner.noop(); )?
Tatu said:It is not efficient.
vineoff said:If I'm having nested loops like:
for (...) for (..) for (...) { /* exit here */ }
and I need to exit from there ^ .
Is it better to use exceptions or goto or some other method?
There are some situations in which a "goto" is the most readable
and clear way to go. A good example would be the initialization
of a device driver (ok, those are normally done in C and not
C++). If something goes wrong there you must make sure that you
revert the state of the device on how you found it.
enum subdevice{A, B, C};
bool init_device()
{
sub_device_status pre_A;
sub_device_status pre_B;
sub_device_status pre_C;
// each init_subdevice_ call initializies the
// internal data structures and then reset the
// subdevice
get_device_status(A, &pre_A);
if( !init_subdevice_A() )
goto failed_A;
get_device_status(B, &pre_B);
if( !init_subdevice_B() )
goto failed_B;
get_device_status(C, &pre_C);
if( !init_subdevice_C() )
goto failed_C;
// All subdevices got initialized properly
return true;
failed_C:
set_device_status(C, pre_C);
failed_B:
set_device_status(B, pre_B);
failed_A:
set_device_status(A, pre_A);
return false;
}
Frankly I don't know a cleaner way to write this, but I'm open to
other suggestions.
1. For bailing out of deeply nested loops, GOTO is not necessarily
harmful. But I don't have my copy of the Standard available, and am not
sure if a goto calls destructors when exiting blocks.
Neil Cerutti said:Prompting and verifying input is a case where goto turns out to
seem nice and clean.
template <typename T>
T ranged_prompt(T min, T max)
{
T n;
prompt:
std::cout << "Enter a number from " << min << " to " << max ": ";
std::cout.flush()
std::cin >> n;
if (!std::cin || n < min || n > max) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<int>::max(), '\n');
goto prompt;
}
return n;
}
Sure, but for the purpose of *BAILING OUT OF A DEEPLY NESTED LOOP*Ali said:Destruction is only one side of the coin. How about construction:
for (;
{
goto future;
}
Foo foo;
future:
cout << "doomed\n";
Unfortunately foo will not be constructed in the future.
To the OP: goto is harmful. There is plenty of writing about that, which
can be easily found on the Net.
use break
Destruction is only one side of the coin. How about construction:
for (;
{
goto future;
}
Foo foo;
future:
cout << "doomed\n";
Unfortunately foo will not be constructed in the future.
To the OP: goto is harmful. There is plenty of writing about that, which
can be easily found on the Net.
Destruction is only one side of the coin. How about construction:
for (;
{
goto future;
}
Foo foo;
future:
cout << "doomed\n";
Unfortunately foo will not be constructed in the future.
To the OP: goto is harmful. There is plenty of writing about that, which can
be easily found on the Net.
Goto is not dangerous or evil, it's just easy to use in ways that mess up
your code.
[...]
To me it seems people tend to forget why they should not use goto, and
just refrain from using it because their teachers told them not to.
You should always consider the solution which creates clear and
understandable code which is easy to maintain.
Using goto is not nice nor clean. goto is inherently risky and
the code below is obfuscated.
red floyd said:Sure, but for the purpose of *BAILING OUT OF A DEEPLY NESTED LOOP*
for (...)
{
for (...)
{
for (...)
{
...
if (disaster)
goto bailout;
}
}
}
bailout:
Note that what you propose can occur *WITHOUT* goto, as well:
switch (expr)
{
case 1:
Foo foo;
case 2:
// uh oh, if expr == 2, foo is not constructed!
foo.bar();
break;
default:
break;
}
That's because switch/case is some type of lookup and a number
of gotos in disguise. Also, maybe less than goto, but
switch/case is frowned upon in C++ as well...
The above program isn't well-formed. The compiler will not letAli said:Destruction is only one side of the coin. How about construction:
for (;
{
goto future;
}
Foo foo;
future:
cout << "doomed\n";
Unfortunately foo will not be constructed in the future.
red said:Sure, but for the purpose of *BAILING OUT OF A DEEPLY NESTED LOOP*
for (...)
{
for (...)
{
for (...)
{
...
if (disaster)
goto bailout;
}
}
}
bailout:
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.