Control Structures

A program's code does not usually execute in a purely linear way. Program execution may require certain program statements, or groups of program statements, to be executed repeatedly (a program loop), either for a predetermined number of iterations, or until some criterion (the exit condition) has been satisfied. Program execution may also branch (jump) to a different location within the program from time to time, depending on (or conditional upon) the current status of one or more variables. Often, the statements that will be executed repeatedly within a loop, or as the result of a conditional statement, are grouped together within a program block. A group of program statements, separated by semicolons, but grouped together between curly braces ({ . . . }), as shown below.

{
  statement1;
  statement2;
  statement3;
}

We have actually seen this construct used in many previous example programs to group together all of the program code that makes up the program's main() function. A code block can contain both simple program statements (i.e. single lines of code, each ending in a semi-colon) and compound program statements (i.e. several simple program statements grouped together and enclosed within curly braces). As you will see, the convention when writing code is to indent the code that appears within a code block to make it clearly distinguishable from any program code outside the block. The more deeply nested the block of code, the greater the level of indentation used.

Conditional structures - if and else

The if keyword is used to execute a statement or a block of code only if a specific condition is met. The general form is shown below.

if (condition) statement

If the expression contained within parentheses evaluates to true, the statement or block of code that follows the condition is executed, otherwise it is not. For the following code fragment, the string "x = 25" is only sent to the screen if the value stored in the variable x is 25.

if (x == 25) printf("x = 25");

If a number of statements are to be executed when a condition evaluates to true, they still appear immediately following the condition, but are enclosed within curly braces, as shown below.

if (x == 25)
{
  printf("The value of x is: ");
  printf("%d", x);
}

We can also specify an alternative course of action that should be followed if the condition evaluates to false using the keyword else, as shown below.

if (condition) statement1 else statement2

In the example code fragment below, the program outputs the string "x is 50" if the condition evaluates to true, otherwise it outputs the string "x is not 50".

if (x == 50)
  printf("x is 50");
else
  printf("x is not 50");

The if . . . else construct can be extended to allow the evaluation of a number of different conditions, with different actions being carried out depending on which of the conditions (if any) evaluates to true. The following code fragment outputs a different string, depending on whether the value of a numeric variable (x) is positive, negative, or neither (i.e. zero).

if (x > 0)
  printf("x is positive");
else if (x < 0)
  printf("x is negative");
else
  printf("x is zero");

The while loop

A loop construct in a program allows program statements to be executed repeatedly, either for a predetermined number of iterations, or until some criterion (the exit condition) has been satisfied. One such construct is the while loop, which has the following form:

while (condition) statement

The statement following the condition (defined within parentheses) is executed repeatedly until the condition evaluates to false. The following short program illustrates the use of the while loop.

// Example program 1
#include <stdio.h>
#include <conio.h>

void main()
{
  int x;

  printf("Please enter a positive whole number: ");
  scanf("%d", &x );
  while (x > 0)
  {
    printf("%d", x);
    if(x > 1) printf(", ");
    --x;  // decrement x by 1
  }
  printf("\n\nPress any key to exit . . . ");
  getch();
}


The output from example program 1

The output from example program 1


The program asks the user to enter a number (x) and prints out a comma-separated list of numbers from x to 1. When the while loop begins, providing the user has entered a number greater than 0, the condition x > 0 evaluates to true, and the statements inside the loop will be executed repeatedly until the value of x is no longer greater than 0. The flow chart for example program 1 is shown below.


The flow chart for example program 1

The flow chart for example program 1


The do . . . while loop

The do . . . while loop has the following form:

do statement while (condition)

The do . . . while loop behaves in exactly the same way as the while loop, with one exception. Whereas the statement in a while loop will only be executed if the condition evaluates to true, the statement in a do . . . while loop is executed at least once, even if the condition evaluates to false on the first iteration of the loop. This is because the condition is evaluated at the end of the loop, instead of at the beginning. The following short program illustrates the use of the do . . . while loop.

// Example program 2
#include <stdio.h>
#include <conio.h>

void main()
{
  int x;

  do
  {
    printf("Please enter a number (or 0 to quit): ");
    scanf("%d", &x );
    printf("\nYou entered: %d\n", x);
  }
  while (x != 0);
  printf("\n\nPress any key to exit . . . ");
  getch();
}


The output from example program 2

The output from example program 2


The loop will continue to accept numbers from the user until the user enters 0, which satisfies the exit condition for the loop. The flow chart for example program 2 is shown below.


The flow chart for example program 2

The flow chart for example program 2


The for loop

The for loop is essentially a counting loop, because it executes a statement (or block of statements) a pre-determined number of times. The general form of the for loop is as follows:

for (expression1; expression2; expression3) statement

In this construct, expression1 sets a counter variable to some initial value (this occurs only once). The exit condition is given by expression2, which determines the value the counter must reach in order for program execution to exit the loop. The exit condition is evaluated on each iteration of the loop. During each iteration, the statements within the loop are executed, as is expression3, which increments (or decrements) the counter by a specified value (usually 1). The short program below illustrates the use of the for loop.

// Example program 3
#include <stdio.h>
#include <conio.h>

void main()
{
  int x;

  for (x = 10; x > 0; x--)
  {
    printf("%d\n", x);
  }
  printf("\n\nWe have lift off!\n\n");
  printf("\n\nPress any key to exit . . . ");
  getch();
}


The flow chart for example program 3

The output from example program 3


Notice that in the above example, the counter variable (x) is both declared and initialised within the loop itself, although it is also possible to use an existing counter variable for this purpose. Notice also that we have initialised the counter to a non-zero value (10), and have used the decrement operator to reduce the value of the counter by one on each iteration of the loop. The program exits the loop when the counter reaches 0. The flow chart for example program 3 is shown below.


The flow chart for example program 3

The flow chart for example program 3


The break statement

We can use the break statement to exit from a loop before the exit condition has been satisfied. The program below demonstrates the use of the break statement, and is a modification of the for loop program we have just seen.

// Example program 4
#include <stdio.h>
#include <conio.h>

void main()
{
  int x;

  for (x = 10; x > 0; x--)
  {
    printf("%d\n", x);
    if (x==3)
    {
      printf("\n\nCountdown aborted at t-%d seconds", x);
      break;
    }
  }
  printf("\n\nPress any key to exit . . . ");
  getch();
}


The output from example program 4

The output from example program 4


The continue statement

The continue statement causes execution of the current iteration of a loop to terminate, so that program execution continues at the start of the next iteration of the loop. The following program demonstrates the use of the continue statement, again using a modification of the for loop program seen previously.

// Example program 5
#include <stdio.h>
#include <conio.h>

void main()
{
  int x;

  for (x = 10; x > 0; x--)
  {
    if (x==5) continue;
    printf("%d\n", x); // this line is omitted if x is 5
    }
  printf("\n\nPress any key to exit . . . ");
  getch();
}


The output from example program 5

The output from example program 5


Notice that the countdown has been completed, but the number 5 is not included. Program execution has jumped out of this iteration of the loop before the number can be output to the screen.

The goto statement

The goto statement allows you to make an unconditional jump to any point in the program. The destination is identified by a label, which consists of a valid identifier followed by a colon. Although we provide an example program below, use of the goto statement in a high-level programming language is generally considered to be poor programming practice.

// Example program 6
#include <stdio.h>
#include <conio.h>

void main()
{
  int x = 10;

loop:
  printf("%d\n", x );
  x--;
  if (x > 0) goto loop;
  printf("\n\nWe have lift off!\n\n");
  printf("\n\nPress any key to exit . . . ");
  getch();
}


The output from example program 6

The output from example program 6


The exit() function

The exit() function is declared in the stdlib.h header file. It is used to terminate the current program, and to return a specific exit code to the process that called the program (e.g. the operating system). Its prototype is given below.

void exit (int exitcode);

By default, an exit code of 0 indicates that the program terminated normally. Any other value indicates that an error of some kind has occurred during program execution.

The switch statement

The switch statement allows us to compare the value of an expression with any number of constant values (cases). The action taken by the program will be that associated with the case matching the expression. In the event that none of the cases matches the expression, a default action may be specified. This construct is similar to using a series of if . . . else instructions. The general form of the switch statement is shown below.

switch (expression)
{
  case const_1:
    statement_1;
    break;
  case const_2:
    statement_2;
    break;
    .
    .
    .
  case const_n:
    statement_n;
    break;
  default:
    default statement;
}

The expression supplied as an argument to the switch statement is evaluated against each case in turn. If a match is found, the statement (or statements) associated with the matching case are executed. The break statement must follow the statement (or statements) to be executed for each case, or the program will continue to traverse the switch structure. When a break statement is encountered, program execution continues from the end of the switch structure. Note that the default case is optional. The following short program demonstrates the use of the switch statement.

// Example program 7
#include <stdio.h>
#include <conio.h>

void main()
{
  int x;

  printf("Please enter a number between 1 and 5: ");
  scanf("%d", &x);

  switch ( x )
  {
    case 1:
      printf("\n\nYou entered one!\n\n");
      break;
    case 2:
      printf("\n\nYou entered two!\n\n");
      break;
    case 3:
      printf("\n\nYou entered three!\n\n");
      break;
    case 4:
      printf("\n\nYou entered four!\n\n");
      break;
    case 5:
      printf("\n\nYou entered five!\n\n");
      break;
    default:
      printf("\n\nNumber is outside specified range.\n\n");
    }
  printf("\n\nPress any key to exit . . . ");
  getch();
}


The output from example program 7

The output from example program 7


The flow chart for example program 7 is shown below.


The flow chart for example program 7

The flow chart for example program 7