Previous Page
Next Page

6.3. Loops

Use a loop to execute a group of statements, called the loop body, more than once. In C, you can introduce a loop by one of three iteration statements : while, do ... while, and for.

In each of these statements, the number of iterations through the loop body is controlled by a condition, the controlling expression . This is an expression of a scalar type; that is, an arithmetic expression or a pointer. The loop condition is true if the value of the controlling expression is not equal to 0; otherwise, it is considered false.

6.3.1. while Statements

A while statement executes a statement repeatedly as long as the controlling expression is true:

while ( expression ) statement

The while statement is a top-driven loop: first the loop condition (i.e., the controlling expression) is evaluated. If it yields true, the loop body is executed, and then the controlling expression is evaluated again. If the condition is false, program execution continues with the statement following the loop body.

Syntactically, the loop body consists of one statement. If several statements are required, they are grouped in a block. Example 6-1 shows a simple while loop that reads in floating-point numbers from the console and accumulates a running total of them.

Example 6-1. A while loop
/* Read in numbers from the keyboard and
 * print out their average.
 * -------------------------------------- */
#include <stdio.h>
int main( )
{
   double x = 0.0, sum = 0.0;
   int count = 0;

   printf( "\t--- Calculate Averages ---\n" );
   printf( "\nEnter some numbers:\n"
           "(Type a letter to end your input)\n" );
   while ( scanf( "%lf", &x ) == 1 )
   {
      sum += x;
      ++count;
   }
   if ( count == 0 )
     printf( "No input data!\n" );
   else
     printf( "The average of your numbers is %.2f\n", sum/count );
   return 0;
}

In Example 6-1, the controlling expression:

scanf( "%lf", &x ) == 1

is true as long as the user enters a decimal number. As soon as the function scanf( ) is unable to convert the string input into a floating-point numberwhen the user types the letter q, for examplescanf( ) returns the value 0 (or -1 for EOF, if the end of the input stream was reached or an error occurred). The condition is then false, and execution continues at the if statement that follows the loop body.

6.3.2. for Statements

Like the while statement, the for statement is a top-driven loop, but with more loop logic contained within the statement itself:

for ( [expression1]; [expression2]; [expression3] )
   statement

The three actions that need to be executed in a typical loop are specified together at the top of the loop body:


expression1 : Initialization

Evaluated only once, before the first evaluation of the controlling expression, to perform any necessary initialization.


expression2 : Controlling expression

Tested before each iteration. Loop execution ends when this expression evaluates to false.


expression3 : Adjustment

An adjustment, such as the incrementation of a counter, performed after each loop iteration, and before expression2 is tested again.

Example 6-2 shows a for loop that initializes each element of an array.

Example 6-2. Initializing an array using a for loop
#define ARR_LENGTH  1000
/* ... */
long arr[ARR_LENGTH];
int i;
for ( i = 0; i < ARR_LENGTH; ++i )
    arr[i] = 2*i;

Any of the three expressions in the head of the for loop can be omitted. This means that its shortest possible form is:

for ( ; ; )

A missing controlling expression is considered to be always true, and so defines an infinite loop .

The following form, with no initializer and no adjustment expression, is equivalent to while ( expression ):

for ( ; expression; )

In fact, every for statement can also be rewritten as a while statement, and vice versa. For example, the complete for loop in Example 6-2 is equivalent to the following while loop:

i = 0;                       // Initialize the counter
while ( i < ARR_LENGTH )     // The loop condition
{
    arr[i] = 2*i;
    ++i;                     // Increment the counter
}

for is generally preferable to while when the loop contains a counter or index variable that needs to be initialized and then adjusted after each iteration.

In ANSI C99, a declaration can also be used in place of expression1. In this case, the scope of the variable declared is limited to the for loop. For example:

for ( int i = 0; i < ARR_LENGTH; ++i )
    arr[i] = 2*i;

The variable i declared in this for loop, unlike that in Example 6-2, no longer exists after the end of the for loop.

The comma operator is often used in the head of a for loop in order to assign initial values to more than one variable in expression1, or to adjust several variables in expression3. For example, the function strReverse( ) shown here uses two index variables to reverse the order of the characters in a string:

void strReverse( char* str)
{
  char ch;
  for ( int i = 0, j = strlen(str)-1;  i < j;  ++i, --j )
    ch = str[i],  str[i] = str[j],  str[j] = ch;
}

The comma operator can be used to evaluate additional expressions where only one expression is permitted. See "Other Operators" in Chapter 5 for a detailed description of the comma operator.

6.3.3. do...while Statements

The do ... while statement is a bottom-driven loop:

do statement while ( expression );

The loop body statement is executed once before the controlling expression is evaluated for the first time. Unlike the while and for statements, do ... while ensures that at least one iteration of the loop body is performed. If the controlling expression yields true, then another iteration follows. If false, the loop is finished.

In Example 6-3, the functions for reading and processing a command are called at least once. When the user exits the menu system, the function getCommand( ) returns the value of the constant END.

Example 6-3. do...while
// Read and carry out an incoming menu command.
// --------------------------------------------
int getCommand( void );
void performCommand( int cmd );
#define END 0
/* ... */
do
{
  int command = getCommand( );  // Poll the menu system.
  performCommand( command );   // Execute the command received.
} while ( command != END );

Example 6-4 shows a version of the standard library function strcpy( ), with just a simple statement rather than a block in the loop body. Because the loop condition is tested after the loop body, the copy operation includes the string terminator '\0'.

Example 6-4. A strcpy( ) function using do ... while
// Copy string s2 to string s1.
// ----------------------------
char *strcpy( char* restrict s1, const char* restrict s2 )
{
  int i = 0;
  do
     s1[i] = s2[i];           // The loop body: copy each character
  while ( s2[i++] != '\0' );  // End the loop if we just copied a '\0'.
  return s1;
}

6.3.4. Nested Loops

A loop body can be any simple or block statement, and may include other loop statements. Example 6-5 is an implementation of the bubble-sort algorithm using nested loops. The inner loop in this algorithm inspects the entire array on each iteration, swapping neighboring elements that are out of order. The outer loop is reiterated until the inner loop finds no elements to swap. After each iteration of the inner loop, at least one element has been moved to its correct position. Hence the remaining length of the array to be sorted, len, can be reduced by one.

Example 6-5. Nested loops in the bubble-sort algorithm
// Sort an array of float in ascending order
// using the bubble-sort algorithm.
// -----------------------------------------
void bubbleSort( float arr[ ], int len ) // The array arr and
{                                       // its length len.
  int isSorted = 0;
  do
  {
     float temp;             // Holder for values being swapped.
     isSorted = 1;
     --len;
     for ( int i = 0;  i < len;  ++i )
       if 
 ( arr[i] > arr[i+1] )
       {
          isSorted = 0;      // Not finished yet.
          temp = arr[i];     // Swap adjacent values.
          arr[i] = arr[i+1];
          arr[i+1] = temp;
       }
   } while ( !isSorted );
}

Note that the automatic variables temp, declared in the do ... while loop, and i, declared in the head of the for loop, are created and destroyed again on each iteration of the outer loop.


Previous Page
Next Page