Python has an interesting for
statement which lets you specify an else
clause.
In a construct like this one:
for i in foo:
if
I would accomplish this with a simple helper variable:
#include <stdio.h>
#include <stdbool.h>
int main()
{
bool b;
printf("Numbers which are multiples of 7:\n");
for (int i=8; b=(i<12); i++)
{
if (i%7==0)
{
printf("%d", i);
break;
}
}
if (!b)
{
printf("no numbers found\n");
}
return 0;
}
This way, you need to implement the condition (in the above examplei<12
) only at one place.
This is my rough implementation in C++:
bool other = true;
for (int i = 0; i > foo; i++) {
if (bar[i] == 7) {
other = false;
break;
}
} if(other)
baz();
Something like:
auto it = foo.begin(), end = foo.end();
while ( it != end && ! bar( *it ) ) {
++ it;
}
if ( it != foo.end() ) {
baz();
}
should do the trick, and it avoids the unstructured break
.
You could use a lambda function for this:
[&](){
for (auto i : foo) {
if (bar(i)) {
// early return, to skip the "else:" section.
return;
}
}
// foo is exhausted, with no item satisfying bar(). i.e., "else:"
baz();
}();
This should behave exactly like Python's "for..else", and it has some advantages over the other solutions:
But... I'd use the clunky flag variable, myself.
I am not aware of an elegant way to accomplish this in C/C++ (not involving a flag variable). The suggested other options are much more horrible than that...
To answer @Kerrek SB about real life usages, I found a few in my code (simplified snippets)
Example 1: typical find/fail
for item in elements:
if condition(item):
do_stuff(item)
break
else: #for else
raise Exception("No valid item in elements")
Example 2: limited number of attempts
for retrynum in range(max_retries):
try:
attempt_operation()
except SomeException:
continue
else:
break
else: #for else
raise Exception("Operation failed {} times".format(max_retries))
I came here because I had the same question, in C though. The best thing I came out with is
bool notTerminated = true;
for (int i = 0; i < 50 || (notTerminated = false); i++)
if (bar(i))
break;
if (! notTerminated)
baz();
Explanation: the (notTerminated = false)
is an assignment that will always return the false value, it will never affect the condition and will be evaluated iif the condition if true.