On 11/11/2003 8:10 AM, Christopher Benson-Manica wrote:
I have a situation something like this:
int b, i, j;
for( i=0 ; i < 7 ; i++ ) {
b=0;
for( j=0 ; j < 8 ; j++ ) {
if( some_func() || other_func(i,j) ) {
b=1;
break;
}
}
if( !b ) {
continue;
}
/* do various other things */
}
I'm quite certain this is a bad way to do this, but I'm at a loss for
something better. Any comments are (again) appreciated.
Using break, continue, and goto let you jump from one point in your code to
another without explicitly stating the abstraction of why you're doing it. I
don't want to start another debate on whether or not that's reasonable. Who
knows, maybe it is for some people. I personally always try to make the
conditions that cause me to make execution flow changes explicit and I find that
if I never let myself use break (except in case statements), continue, or goto,
then that forces me to either explicitly state those conditions so the next
person to modify the code doesn't have to manually synthesize those
abstractions, or at the very least ensure that if you look at the condition
specified between the two ";"s in any loop, then that is THE condition that
affects the loop entry/exit and there isn't some other nameless exit condition
hidden in the loop body somewhere.
For example, in your loops you behave differently if "some_func() ||
other_func(i,j)" but there's no indication of what the condition MEANS or why
it's important someone coming along to modify that code in future would have to
spend the time to figure out that meaning (synthesize the abstraction).
With that in mind, if we assume that when either "some_func()" or
"other_func(i,j)" return a non-zero value, that means you're out of resources,
then you can get rid of the break and continue and, I think, make the code
easier to read to the next guy:
int i, j;
for( i=0 ; i < 7 ; i++ ) {
int gotRsrcs = 1;
for( j=0 ; j < 8 && gotRsrcs; j++ ) {
gotRsrcs = ( (some_func() || other_func(i,j)) ? 0 : 1 )
}
if( gotRsrcs ) {
/* do various other things */
}
}
Regards,
Ed.