Objects First |
Programming languages provide looping statements to enable this repetitive behaviour. C has three variants:
while ( expression ) statement
statement
may be either a single statement or a
block.
|
Print XXXXXXXXXX on the output |
#define N 10
int i;
i = 0;
while( i < N ) {
printf("X");
i++;
}
|
| Sum the elements of an array |
#define N 10
int i;
double x[N], sum;
i = 0;
sum = 0.0;
while( i < N ) {
sum = sum + x[i];
i++;
}
|
|
Print XXXXXXXXXX on the output |
i = 1;
while( i <= N ) {
printf("X");
i++;
}
|
i = 0;
while( i < N ) { ... }
style is preferred for all loops.
The expression that guards the loop is evaluated before the block of statements is entered. The loop continues while the expression evaluates to true.
|
The dreaded infinite loop
The expression is always true! |
#define TRUE 1
...
while( TRUE ) {
printf("X");
i++;
}
|
Because the expression is evaluated before entering the loop, it is possible to produce a while loop whose body is never executed:
|
If the input is unsatisfactory, try again! |
double f( double x ) {
/* Make sure that x is in the correct range */
while( (x < low) || (x > high) ) {
x = read_input("Enter a value for x: ");
}
....
return ..... ;
}
|
|
Print N X's on the output |
i = N;
while( i > 0 ) {
printf("X");
i--;
}
|
|
Function to
sum n elements of an array |
double vector_sum( double x[], int n ) {
double sum = 0.0;
while( n-- ) {
sum = sum + x[n];
}
return sum;
}
|
Exercise
If we had written
while ( --n ) { ... }
do { ... } while ( expression );
This is essentially the same as a while loop, except that the expression is evaluated after the statements in the loop body have been executed. Thus a do loop is always executed at least once. Compare these two trivial examples:
| Loop never executed |
while( FALSE ) {
.....
}
|
| Loop executed once |
do {
.....
}
while( FALSE );
|
| How many X's will be output? |
#define N 10
i = N;
do {
printf("X");
i--;
} while ( i > 0 );
|
|
Solve f(x) = 0 by Newton's technique df(x) returns f'(x) |
#define EPSILON 1.0e-10
double solve( double guess ) {
double x1, x2;
do {
x1 = guess;
x2 = x1 - f(x1)/df(x1);
guess = x2;
}
while ( abs(x1 - x2) > EPSILON );
return x2;
}
|
for( expr1; expr2; expr3 ) { ... }
Formally, a for statement is equivalent to:
expr1;
while( expr2 ) {
....
expr3;
}
To make this clear, take a simple example.
Again, we want to sum the n elements of an array:
using a for loop, we write:
for(i=0;i < n;i++) {
sum = sum + x[i];
}
which is equivalent to:
i=0;
while( i < n ) {
sum = sum + x[i];
i++;
}
|
expr1;
while( expr2 ) {
....
expr3;
}
|
i = 0;
i++; /* Equivalent to i = i+1; */
Of course, since the three elements of a for are expressions, arbitrarily complex expressions are possible! For example,
while( ?? what goes here ?? ) {
/* Calculate some initial results */
.....
/* Based on these initial results, we know whether to continue the
loop or not */
if ( termination_condition ) {
?? /* exit the loop here */
}
/* but if we didn't terminate, continue the computation */
....
}
C's break statement handles this situation:
while( TRUE ) {
/* Calculate some initial results */
.....
/* Based on these initial results, we know whether to continue the
loop or not */
if ( termination_condition ) {
/* Exit the loop with break */
break; }
/* but if we didn't terminate, continue the computation */
....
}
Note that the if ( expression ) break;
statement is supplying the loop termination condition,
so that the while( TRUE ) part is perfectly
reasonable and does not necessarily produce an infinite loop.
break may be used in any
while, do or for
loop to generate an exit from the loop at any point within the loop.
If loops are nested,
break exits only the immediately enclosing
loop:
/* Doubly nested loop to process an nxm matrix */
for(i=0;i<n;i++) {
for(j=0;j<m;j++) {
a[i][j] = ....
if ( a[i][j] < EPSILON ) break;
....
}
.... /* break statement resumes HERE */
}
In this case, if you wanted to exit both loops,
you would need two i
break statements -
one in each loop.
continue: skip the rest of the loop
A continue statement causes the rest of the loop
to be skipped, but loop execution continues.
Thus, whereas break can be used to supply a
termination condition,
continue doesn't break out of a loop and
a valid termination condition must still be supplied!
while( termination_condition ) {
s1; s2; ... /* Some statements */
if ( skip_rest_of_loop ) continue;
s10; s11; ... /* More statents */
/* continue resumes here */
}
continue is exactly equivalent to:
while( termination_condition ) {
s1; s2; ... /* Some statements */
if ( ! skip_rest_of_loop ) {
s10; s11; ... /* More statents */
}
}
thus it is relatively rarely used. All it does is
avoid a block of statements nested inside
a loop - a minor simplification of the program!
The break statement, on the other hand,
finds many applications and will be found in
most C programs somewhere or other.
In fact it is necessary in
switch
statements, where its omission will cause
unexpected results to be generated!
Key terms |
| Continue on to Readable code | Back to the Table of Contents |