PROGRAM CONSTRUCTS
CONTENTS

All programming language utilise program constructs. In imperative languages they are used to control the order (flow) in which statements are executed (or not executed). There are a number of recognised basic programming constructs that can be classified as follows:

To which we can also add routine invocation (Fourth Floor). Note also that each of the above constructs are all also program statements in their own right.




SEQUENCES

A sequence construct tells the processor which statement is to be executed next. By default, in imperative languages, this is the statement following the current statement (or the first statement in the program). If we wish to "jump" to some other statement we can use a goto statement. This was popular in the early days of computer programming (1950's to early 1960's). Example BASIC goto statement:

GOTO 400

This tells the processor to "jump" to line 400 and to then continue processing from this point in the program. The use of goto statements was also encouraged by languages such as Fortran and Cobol.


GOTO STATEMENT CONSIDERED HARMFUL (Dijkstra 1968)

Goto statements make it difficult to "trace" a program's execution and to determine the state of variables at a given point during processing. As a result errors are often obscure and difficult to locate. For this reason some more modern (post mid 1960's) imperative languages, for example Modula-2 and Pascal, have abandoned the goto statement all together. However, there are some legitimate reasons why a goto may be desirable, for example to facilitate error handling or to terminate a deeply nested sequence of loops. Both Ada and C support a goto statement but it is best avoided.




SELECTION

A selection statement provides for selection between alternatives. We can identify three types of selection construct:

  1. If statements
  2. Case statements
  3. Pattern matching

However, imperative languages do not generally make much use of pattern matching (logic and some modern functional languages do), thus we will limit the following discussion to the "if" and "case" forms of selection.

IF STATEMENT

An if statement, sometimes referred to as a conditional, can be used in two forms:

  1. If condition then action1
  2. If condition then action1 else action2

Where X is a Boolean expression (or a sequence of Boolean expression), and Y and Z are program statements of some description. We can also identify a number of variations of the above which are particular to individual programming languages. For example the Ada:

if X1 then Y1 elsif X2 then Y2 ... elsif Xn then Yn else Yn+1 end if

Ada Example:

with CS_IO ; use CS_IO ;

procedure IF_ELSE_EXAMPLE is
        NUM_X, NUM_Y, NUM_Z: integer;
begin
        get(NUM_X);
        if NUM_X < 0 then
                NUM_Y := -NUM_X;
                NUM_Z := 10+NUM_X;
        else
                NUM_Y := NUM_X;
                NUM_Z := 10-NUM_X;
                end if;
        put("NUM_X = ");put(NUM_X);new_line;
        put("NUM_Y = ");put(NUM_Y);new_line;
        put("NUM_Z = ");put(NUM_Z);new_line;
end IF_ELSE_EXAMPLE;

Input value for NUM_X and .


C Example:

#include

void main(void)
{
int num_x, num_y, num_z;

scanf("%d",&num_x);

if (num_x < 0) {
        num_y = num_x*num_x;
        num_z = 10+num_x;
        }
else {
        num_y = num_x*num_x*num_x;
        num_z = 10-num_x;
        }

printf("num_x = %d, num_y = %d, num_z = %d\n",num_x,num_y,num_z);
}

Input value for num_x and .


Case Statement

Generally speaking an "if ... then ... else ..." statement supports selection from only two alternatives; we can of course nest such statements, but it is usually more succinct to use a case statement. Case statements allow selection from many alternatives where each alternative is linked to a predicate, referred to as a selector, which when evaluated to true causes an associated program statement (or statements) to be executed. Selections may be made according to:

  1. A distinct value of a given selector.
  2. An expression involving the selector.
  3. A default value.

Selectors must be of a discrete type (typically an integer, a character or an enumerated type). C only supports selection by distinct value or default (default). Ada also supports selection by distinct value and default (others), as well as selection according to:

  1. A number of Alternatives (each separated by a bar |).
  2. Ranges expressed using the .. operator.
  3. Selection by condition *e.g. <, =, >).

Also note that where selection is by distinct value, in some cases, these must be presented in the correct numeric order (this is the case in C).


Ada Example:

Format:

`case' SELECTOR `is'
        `when'  `=>' 
        ...
`end case;'

Usage:

with CS_IO ; use CS_IO ;

procedure IF_ELSE_EXAMPLE is
        SELECTOR : integer;
begin
        case SELECTOR is
                when 0 => put("SELECTOR equals 0");
                when 1 | 5 => put("SELECTOR equals 1 or 5");
                when 2..4 => put("SELECTOR equals 2, 3 or 4");
                when others => put("SELECTOR less than 0 or greater than 5");
        end case;
        new_line;
end (CASE_EXAMPLE);

Input value for SELECTOR and .


C Example:

Format:

`switch' SELECTOR `{'
        `case' VALUE `:' 
        `break;'
        ...
        `}'

Usage:

#include

void main(void)
{
int selector;

scanf("%d",&selector);

switch (selector) {
        case 0:
                printf("selector equals 0\n");
                break;
        case 1:
        case 2:
        case 3:
                printf("selector equals 1, 2 or 3\n");
                break;
        default:
                printf("selector less than 0 or greater than 3\n");
        }
}

Input value for selector and .

Note that C requires that selectors are presented according to their numeric order. Note also that neither Ada nor C support selection using expressions involving selectors, e.g. a conditional expression or an arithmetic expression. This is supported by languages such as Pascal.




REPETITION

A repetition construct causes a group of one or more program statements to be invoked repeatedly until some end condition is met. Typically such constructs are used to step through arrays or linked lists. We can identify two main forms of repetition:

  1. Fixed count loops - repeat a predefine number of times.
  2. Variable count loops - repeat an unspecified number of times.

To which we could add recursion (routine calls itself). Recursion is not used so much in imperative languages, although it is the principal program construct used to achieve repetition in logic and functional languages, thus we will confine ourselves in the following discussion to fixed and variable count loops.


Pretest and posttest loops

Both fixed and variable count loops can be further classified according to whether they are pretest or posttest loops. In the case of a pretest loop (also referred to as an entrance-controlled loop) the end condition is tested for prior to each repetition, while in the case of a posttest loop (also referred to as an exit-controlled loop) the end condition is tested for after each repetition.

PRETEST AND POSTTEST LOOPs


FIXED COUNT LOOPS

Fixed count loops (sometimes referred to as for loops) allow a statement to be repeated a "fixed" number of times as specified on entry into the loop. Fixed count loops tend to be pretest loops, i.e. the end condition is tested prior to each repetition. Issues:

  1. Type of the control value.
  2. Nature of start and end conditions.
  3. Updating the control variable.
  4. Reverse processing.
  5. Nesting.

TYPE OF THE CONTROL VARIABLE

NATURE OF START AND END CONDITIONS.

UPDATING THE CONTROL VARIABLE

REVERSE PROCESSING

NESTING

The following example programs initialise a 10 element array and then processes (outputs) that array using a fixed count (for) loop construct.


Ada Example:

Format:

`for' <CONTROL_VALUE> `in' <START_CONDITION> `..' <END_CONDITION> `loop'
        <STATEMENTS>
        `end loop;'

Usage (processing an array):

PRESS
with CS_IO ; use CS_IO ;

procedure FOR_LOOP_EXAMPLE is
        DIGIT: array (integer range 0..9) of integer;
begin
        for INDEX in 0..9 loop
                DIGIT(INDEX) := INDEX;
                end loop;
        for INDEX in reverse 0..9 loop
                put(DIGIT(INDEX));
                new_line;
                end loop;
        new_line;
end FOR_LOOP_EXAMPLE;

Note that: (1) the control variable INDEX is not declared or initialised by the program and (2) that the second loop processes the array in reverse.


C Example:

Format:

`for (' <CONTROL_VALUE> `;' <START_CONDITION> `;' <END_CONDITION> `) {'
        <STATEMENTS>
        `}'

Usage (processing an array):

PRESS
#include

void main(void)
{
int index=0, digits[10];

for (index;index<10;index++) {
        digits[index] = index;
        }

for (index=9;index>=0;index--) {
        printf("%d ",digits[index]);
        }

printf("\n");
}

Note that the way the C for loop construct is used here is fixed count, the construct could equally well be used to implement a variable count loop.

Terminating a Loop

Sometimes there is a need to terminate a loop somewhere in the middle. Many languages therefore support a break (C) or exit (Ada) statement. Ada actually supplies two types of exit statement, exit and exit when.


Variable Count Loops

Variable count loops allow statements to be repeated an indeterminate number of times. The repetition continues until a control condition (usually a boolean expression) is no longer fulfilled. As such, variable count loops do not feature a control variable which is incremented and tested against some end condition on each loop. Variable count loops may be pretest or posttest loops. Pretest variable count loop are sometimes referred to as a while loops (Ada, C, Pascal), and posttest variable count loops as a do-while (C) or repeat (Pascal) loops (Ada does not feature a posttest variable count loop construct).

Ada While Loop Example:

PRESS
with CS_IO ; use CS_IO ;

procedure WHILE_LOOP_EXAMPLE is
        COUNTER: integer:= 1;
begin
        while COUNTER <= 10 loop
                put(COUNTER);
                put(COUNTER*COUNTER);
                put(COUNTER*COUNTER*COUNTER);
                new_line;
                COUNTER := COUNTER + 1;
                end loop;
end WHILE_LOOP_EXAMPLE;

C While Loop Example:

PRESS
#include

void main(void)
{
void main(void)
{
int counter = 1;

while (counter <= 10) {
        printf("%d  %d  %d\n",counter,counter*counter,counter*counter*counter);
        counter++;
        }
}

Ada While Loop Example With exit Statement:

with CS_IO ; use CS_IO ;

procedure GUESSING_GAME is
        NUMBER: integer;
        GUESS, OFFSET: integer:= 64;
        COUNTER: integer:= 1;
begin
        put_line("Enter a number between");
        put_line("1 and 127 inclusive");
        get(NUMBER);

        while COUNTER < 7 loop
                put(COUNTER);
                put("Guess ");put(GUESS);new_line;
                exit when GUESS=NUMBER;
                OFFSET:= OFFSET/2;
                if NUMBER < GUESS then GUESS:= GUESS-OFFSET;
                else GUESS:=GUESS+OFFSET;
                end if;
                COUNTER:= COUNTER+1;
                end loop;

        if (COUNTER = 7) then put_line("You win!");
        else put("Number is ");put(GUESS);
                new_line; put_line("I win!");
        end if;
end GUESSING_GAME;

Enter a number between 1 and 127 inclusive for NUMBER and .


C Do-While Loop Example With exit Statement:

#include <stdio.h>

void main(void)
{
int number, guess = 64, offset = 64, counter = 1;

printf("Enter a number between ");
printf("1 and 127 inclusive ");
scanf("%d",&number);
printf("\n");

do {
        printf("%d) Guess %d\n",counter,guess);
        if (guess == number) break;
        offset = offset/2;
        if (number < guess) guess=guess-offset;
        else guess=guess+offset;
        counter++;
        } while (counter < 7);

if (counter == 7) printf("You win!\n");
else printf("Number is %d\nI win!\n",guess);
}

Enter a number between 1 and 127 inclusive for number and .




ROUTINE INVOCATION

Routine (or procedure) invocation is particular to imperative languages. When a sequence of statements forms a conceptual unit about which it is possible and useful to think and reason in isolation it is convenient to encapsulate the sequence in a named routine (procedure) and to replace it with a procedure call in the original code. Unlike a goto statement, routine invocation guarantees that the flow of control will eventually return to the point from which the routine was called (the procedure call).

ROUTINE INVOCATION



CONTINUE

LIFT CALL: UP - return to imperative home page, DOWN - continue.




Created and maintained by Frans Coenen. Last updated 03 July 2001