Velocity Reviews > Two-iteration loop

# Two-iteration loop

Christopher Benson-Manica
Guest
Posts: n/a

 11-10-2003
I have a situation something like this:

int foo;

for( foo=bar() ; foo <= bar()+1 ; foo++ ) {
if( !baz(foo) ) break;
/* do stuff with foo */
}

The idea is that the loop happens at most twice - once for foo=bar(), and once
for foo=bar()+1. If baz(foo) fails, I know I can stop. However, I don't
think this is the "elegant" way to get this behavior - there is a break (which
might be bad style, for some), and bar() may be called three times (which
doesn't seem optimal). I thought of

int foo=bar();

do {
if( !baz(foo) ) break;
/* doo stuff with foo */
} while( foo++ == bar() );

, but it's no better (and is somewhat more obfuscated, to boot). Any
thoughts?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.

Dave Vandervies
Guest
Posts: n/a

 11-10-2003
In article <boodf0\$sta\$(E-Mail Removed)>,
Christopher Benson-Manica <(E-Mail Removed)> wrote:
>I have a situation something like this:
>
>int foo;
>
>for( foo=bar() ; foo <= bar()+1 ; foo++ ) {
> if( !baz(foo) ) break;
> /* do stuff with foo */
>}
>
>The idea is that the loop happens at most twice - once for foo=bar(), and once
>for foo=bar()+1. If baz(foo) fails, I know I can stop. However, I don't
>think this is the "elegant" way to get this behavior - there is a break (which
>might be bad style, for some), and bar() may be called three times (which
>doesn't seem optimal). I thought of
>
>int foo=bar();
>
>do {
> if( !baz(foo) ) break;
> /* doo stuff with foo */
>} while( foo++ == bar() );
>
>, but it's no better (and is somewhat more obfuscated, to boot). Any
>thoughts?

How long is the chunk that "/*do stuff with foo*/" expands to?

If it's not too long, something like this might be a little bit cleaner
(for one thing, it makes it clear that it's a "do something again unless
baz() fails" and not a "loop until some condition is met"), though it's
not without its problems:
--------
foo=bar();
/*do stuff with foo*/
foo++;
if(baz(foo))
{
/*Note that this stuff is the same stuff we did above. If baz
returns nonzero we have to do it again.
*/
/*do stuff with foo*/
}
--------

Depending on how closely what you're doing with foo is tied to the rest
of the code there, it might be worth moving it to another function:
--------
foo=bar();
do_stuff_with(foo);
foo++;
if(baz(foo))
do_stuff_with(foo); /*again*/
--------

dave

--
Dave Vandervies http://www.velocityreviews.com/forums/(E-Mail Removed)
>You can quit emacs?

Yes, and after 12 weeks of rehab, you might even stay off the stuff.
--James Riden and Greg Andrews in the scary devil monastery

Ian Woods
Guest
Posts: n/a

 11-10-2003
Christopher Benson-Manica <(E-Mail Removed)> wrote in
news:boodf0\$sta\$(E-Mail Removed):

> I have a situation something like this:
>
> int foo;
>
> for( foo=bar() ; foo <= bar()+1 ; foo++ ) {
> if( !baz(foo) ) break;
> /* do stuff with foo */
> }
>
> The idea is that the loop happens at most twice - once for foo=bar(),
> and once for foo=bar()+1. If baz(foo) fails, I know I can stop.
> However, I don't think this is the "elegant" way to get this behavior
> - there is a break (which might be bad style, for some), and bar() may
> be called three times (which doesn't seem optimal). I thought of
>
> int foo=bar();
>
> do {
> if( !baz(foo) ) break;
> /* doo stuff with foo */
> } while( foo++ == bar() );
>
> , but it's no better (and is somewhat more obfuscated, to boot). Any
> thoughts?

If the value returned by bar() is loop invarient, assign it to a
variable. If bar() is an expensive (but invarient) computation this will
be a nice gain, and performing a single unnecessary check is at no cost.

You might do this:

int foo, startpos;

startpos=bar();
for (foo=startpos;foo<startpos+2 && !baz(foo);foo++) {
/* do stuff */
}

if you don't like the break. Personally, I don't mind "if (cond) break;"
especially at the beginning of loops.

If bar() isn't loop invarient and expensive, then you can still do it
nicely. something like:

int foo;
for (foo=0;foo<2;foo++) {

int barval=bar()+foo;
if (!baz(barval)) break;

/* do stuff */
}

If bar() isn't expensive and loop invarient, it doesn't really matter if
it's invoked a third.

Ian Woods

Ed Morton
Guest
Posts: n/a

 11-10-2003

On 11/10/2003 10:13 AM, Christopher Benson-Manica wrote:
> I have a situation something like this:
>
> int foo;
>
> for( foo=bar() ; foo <= bar()+1 ; foo++ ) {
> if( !baz(foo) ) break;
> /* do stuff with foo */
> }
>
> The idea is that the loop happens at most twice - once for foo=bar(), and once
> for foo=bar()+1. If baz(foo) fails, I know I can stop. However, I don't
> think this is the "elegant" way to get this behavior - there is a break (which
> might be bad style, for some), and bar() may be called three times (which
> doesn't seem optimal). I thought of
>
> int foo=bar();
>
> do {
> if( !baz(foo) ) break;
> /* doo stuff with foo */
> } while( foo++ == bar() );
>
> , but it's no better (and is somewhat more obfuscated, to boot). Any
> thoughts?
>

If the value returned from bar() never changes, then of course you'd assign that
to a variable outside of the loop:

int foo;
int fooMin = bar();
int fooMax = fooMin + 1;

for( foo=fooMin ; foo <= fooMax ; foo++ ) {
if( !baz(foo) ) break;
/* do stuff with foo */
}

Instead of breaking out of the loop if baz() fails, the obvious change would be
to only do the work if baz() succeeds, e.g.:

int foo;
int fooMin = bar();
int fooMax = fooMin + 1;

for( foo=fooMin ; foo <= fooMax ; foo++ ) {
if( baz(foo) ) {
/* do stuff with foo */
}
}

or even:

int foo;
int fooMin = bar();
int fooMax = fooMin + 1;

for( foo=fooMin ; (foo <= fooMax) && baz(foo) ; foo++ ) {
/* do stuff with foo */
}

If the condition becomes complex, write a macro:

#define ISVALID(foo) ((foo) <= fooMax ? baz((foo)) : 0)

int foo;
int fooMin = bar();
int fooMax = fooMin + 1;

for( foo=fooMin ; ISVALID(foo) ; foo++ ) {
/* do stuff with foo */
}

Now, if bar() doesn't always return the same value, we can easily modify the
above to:

#define ISVALID(foo) ((foo) <= bar() + 1 ? baz((foo)) : 0)

int foo;

for( foo=bar() ; ISVALID(foo) ; foo++ ) {
/* do stuff with foo */
}

Regards,

Ed.

Ben Pfaff
Guest
Posts: n/a

 11-10-2003
Christopher Benson-Manica <(E-Mail Removed)> writes:

> int foo;
>
> for( foo=bar() ; foo <= bar()+1 ; foo++ ) {
> if( !baz(foo) ) break;
> /* do stuff with foo */
> }
>
> The idea is that the loop happens at most twice - once for foo=bar(), and once
> for foo=bar()+1. If baz(foo) fails, I know I can stop. However, I don't
> think this is the "elegant" way to get this behavior - there is a break (which
> might be bad style, for some), and bar() may be called three times (which
> doesn't seem optimal).

If I understand the situation correctly, try this:

for (foo = bar(); baz(foo) && foo <= bar() + 1; foo++) {
/* do stuff with foo */
}
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}

 Thread Tools

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post Isaac Won Python 9 03-04-2013 10:08 AM Byte Python 4 03-24-2006 03:04 AM - Java 12 06-15-2005 08:50 AM Steven Java 5 03-30-2005 09:19 PM =?Utf-8?B?VGltOjouLg==?= ASP .Net 2 02-16-2005 12:21 PM

Advertisments