[comp.lang.c] Loop semantics: FOR C := A TO B DO ...

markh@csd4.milw.wisc.edu (Mark William Hopkins) (02/04/89)

This problem was recently posed:

    Find a suitable translation in C for

    a, b, c: CHAR
    ...
    FOR c := a TO b DO <Body>

that correctly accounts for c's remaining inside its subrange 0..127 or
0..255 or whatever.  The answer is this:

	      for (c = a; c < b; c++) <Body>
	      if (c = b) <Body>

Of course, if you want to avoid duplication, you can go something like this:

	      for (c = a; c <= b; if (c < b) c++) <Body>

gwyn@smoke.BRL.MIL (Doug Gwyn ) (02/04/89)

In article <763@csd4.milw.wisc.edu> markh@csd4.milw.wisc.edu (Mark William Hopkins) writes:
>Of course, if you want to avoid duplication, you can go something like this:
>	      for (c = a; c <= b; if (c < b) c++) <Body>

There is a solution but that ain't it.

msb@sq.uucp (Mark Brader) (02/09/89)

>     Find a suitable translation in C for
>     a, b, c: CHAR
>     ...
>     FOR c := a TO b DO <Body>
> 
> that correctly accounts for c's remaining inside its subrange 0..127 or
> 0..255 or whatever.

I haven't seen the following answer yet.  (I'm sure that net propagation
delay means that I'll see three such answers tomorrow, but anyway....)

As a non-speaker of Modula2, I am assuming that the original statement
calls for the greater of 0 and b-a+1 iterations, i.e., including both the
a and b cases if a >= b but nothing if a < b.  Otherwise it'd be simple.

The problem is of course that c might loop through all values that its
type can hold, so there's no single test such as c < b that you can use
in a for- or while-header, no matter how you fiddle the increment side.
However, this doesn't mean that you have to repeat the whole body.
Just provide a separate test before the first iteration:

	if (a <= b) {
		c = a;
		do {
			<Body>
		} while (c++ < b);
	}

This does what was asked for -- and yes, I tested it.  So you might
keep it in mind the next time you need a loop whose index that might
exactly reach the minimum legal maximum value for its data type.

But I don't think it really meets the requirement of a *suitable* C
translation... it's more of a transliteration.  A suitable C translation
would use the suitable datatype for a loop index whose absolute value
doesn't exceed 32767: int.  Since the loop index isn't going to reach 32767,
the loop can now be coded in (wait "for" it) a straight"for"ward fashion:

	for (c = a; c <= b; ++c) {
		<Body>
	}

Of course, the loop body might have to be altered if it does something
that depends on the type of the loop index being char.  Such things
are relatively rare, usually involving & operations.

Mark Brader, Toronto		sed -e "s;??\\([-=(/)'<!>]\\);?\\\\?\\1;g"
utzoo!sq!msb, msb@sq.com	will fix them...	-- Karl Heuer

ark@alice.UUCP (Andrew Koenig) (02/09/89)

In article <1989Feb8.183945.21485@sq.uucp>, msb@sq.uucp (Mark Brader) writes:

> 	if (a <= b) {
> 		c = a;
> 		do {
> 			<Body>
> 		} while (c++ < b);
> 	}

> This does what was asked for -- and yes, I tested it.  So you might

Even though you tested it, it's wrong.  The last time through the loop,
c == b.  Thus after exiting from the loop, c == b+1.  This violates
the conditions of the problem.  (imagine a machine that checks for
integer overflow)
-- 
				--Andrew Koenig
				  ark@europa.att.com