First Next Previous Last Glossary About

Decision and Iteration


Introduction

The decision structure is an essential part of algorithms in computer programming. If a computer language can't evaluate decisions then we can't write programs that can branch.

In computing terms a decision is a structure that has a truth value. It can only be either TRUE or FALSE.

In C++ decisions, also known as conditions or propositions or logical expressions or relational expressions or boolean expressions, appear enclosed inside parentheses:

if (relational expression)
    statement1;
else statement2;   // optional 

The (relational expression) is evaluated, if TRUE then statement1 is executed else statement2 is executed.

Return to top of page

if, if .. else and the relational operators

C++ has the bool data type which it treats as numeric values (usually true is 1, or at least non-zero, and false is zero), so (relational expression) since it is numeric can also be (expression != 0) which has the same effect as (relational expression).

We use the relational operators when evaluating relational expressions:

Example Comments
if (n> 0)
 if (a> b)
  z = a;
 else z = b;

Without any indication to the contrary, an else belongs to the previous if. In this case the else belongs with the condition (a> b).

if (n> 0) 
 { if (a> b)
    z = a;
 }
else z = b;

To change this association, uses braces as shown here. In this case the else belongs with the condition (n> 0).

A semi-colon follows the statement associated with if. A statement is always terminated by a semi- colon.

Decision and the logical operators

We can combine many relational expressions by using the logical operators. For instance:

Here are some examples using the syntax of C++:

Example Comments

Logical AND

if ((a > b) && (a < 22))
 c = a + b;
else
 c = a - b;

There are two conditions (a > b) logically combined with (a < 22) and they are combined using the logical operator AND which in C++ is written &&.

If (a > b) is true AND (a < 22) is true then the statement c = a + b; is executed. Note that the whole logical expression is enclosed in parentheses ((a > b) && (a < 22)). If either (a > b) or (a < 22) is false then the whole expression ((a > b) && (a < 22)) is false and the statement c = a - b is executed.

Logical OR

if ((a > b) || (a < 22))
 c = a + b;
else
 c = a - b;

In this example there are two conditions (a > b) logically combined with (a < 22) and they are combined using the logical operator OR which in C++ is written || (the pipe symbol or broken bar).

If (a > b) is true OR (a < 22) is true then the statement c = a + b; is executed. Note again that the whole logical expression is enclosed in parentheses ((a > b) || (a < 22)). The statement c = a - b will only be executed if (a > b) is false and (a < 22) is false.

Logical NOT

if !(a > b)
 c = a + b;
else
 c = a - b;

In this example there is a single condition (a > b) logically combined with the logical operator NOT which in C++ is written ! (exclamation mark). The ! operator changes the truth sense of the relational expression.

If (a > b) is true then !(a > b) is false. In this case the statement c = a + b is executed. If (a > b) is false then !(a > b) is true and the statement c = a - b is executed.

The table below shows truth tables for each of the logical operators &&, || and !.

And, Or, Not truth tables

AND

OR

NOT

(a > b) (a < 22) (a > b) && (a < 22)
FALSE FALSE FALSE
FALSE TRUE FALSE
TRUE FALSE FALSE
TRUE TRUE TRUE
(a > b) (a < 22) (a > b) || (a < 22)
FALSE FALSE FALSE
FALSE TRUE TRUE
TRUE FALSE TRUE
TRUE TRUE TRUE
(a > b) !(a > b)
FALSE TRUE
TRUE FALSE

Return to top of page

Multi-way decisions or nested if ... else

A common requirement in a computer program is the need to make decisions based on the outcome of previous decisions. For example if x is true then do y else if j is true then do z else if ...

if (expression)
 statement1;
else if (expression)
      statement2;
     else if (expression)
           statement3;
          else if (expression)
                statement4;
               else statement5;

If any expression is true then its associated statement is executed and the chain is terminated. The last else is the default condition in the event that none of the (expression)'s are true.


Switch statement

The switch statement achieves a similar effect to the nested if else. It tests whether an expression matches a number of constant values.

 switch (expression)
 {
   case 1 : statement1a;    /* execute the statements */
            statement1b;    /* then fall out of the   */
            statement1c;    /* switch statement       */
            break; 
   case 2 : statement2;
            break;
   case 3 : statement3;
            break;
   case 4 :                 /* a fall-through case  */
   case 5 :                
   case 6 : statement456;
            break;

   default : statementdefault; /* do this if all else fails */
             break;
 } // end of switch 

The (expression) is evaluated and its value compared with all the cases. Each case must be labelled by an integer constant, character constant or constant expression. The break statement terminates the switch. The default case executes if all other cases fail (it is optional), the last break (in the default case) isn't required but is good defensive programming practice, you may want to add more cases later.


Switch statement examples

Example Comments
#include <iostream>
int main()
{ 
 int i;
 cin >> i;
 switch (i)
 {
   case 1 : ++i;
            cout << i << endl;
            break;
   case 2 : --i;                
            cout << i << endl;  
            break;              
   case 3 : i += 9;             
            cout << i << endl;  
            break; 
   case 4 :        
   case 5 :                
   case 6 : cout << (i < 4) << endl;
            break;
   default : cout << i << endl;
             break;
 } // end of switch 
return 0;
} 

The program accepts a value for i from the stdin device and tests this in the switch statement to determine if it is one of several values.

Cases 1, 2 and 3 each do something differen. The code for each case is executed and then the break statement follows, breaking out from the switch.

Cases 4, 5 and 6 are all combined into a single case.

In the event that i was not in the range 1 to 6 there is a default case.

#include <iostream>
#include <ctype.h>

int main()
{ 
 char i;
 cout << "Enter a single character: ";
 cin >> i;
 i = toupper(i);
 switch (i)
 {
   case 'A' : ++i;
            cout << i << endl;
            break;
   case 'B' : --i;                
            cout << i << endl;  
            break;              
   case 'C' : i += 9;             
            cout << i << endl;  
            break; 
   case 'D' :        
   case 'E' :                
   case 'F' : cout << (i < 4) << i * 2 << endl;
              break;
   default : cout << i << endl;
             break;
 } // end of switch 
return 0;
} 

In this example we use a switch statement with characters.

Note the use of the toupper() function. You need to include the file ctype.h to use this function. As the name suggests toupper() converts a character to its uppercase form.

This example shows too that you can do arithmetic with chars. Since the char is a simple data type then operations like + and - are quite OK.

It is usually a good idea to enclose expressions headed for the cout stream in parentheses. This helps to avoid complaints from the compiler.

Return to top of page

Iteration - The While Loop

The while loop has the form: while (expression) statement; which means that while (expression) is true execute statement. The while loop is distinguished by its having the condition before any processing which is within the scope of the loop.

The expression must be enclosed in parentheses and must evaluate to a boolean value, ie true or false, for example:

while (i > 9) ...

while (a != 'Q') ...

while (x) ... //x is treated as bool

The statement can be a simple statement or a compound statement, for example:

while (i > 9)             //using a simple statement
 j += 4;

while (a != 'Q')          //using a compound statement
 { j += 4;
   s = "123456"
   cout << j;   
 }

#include <iostream>
int main()
{ 
 int  i = 1;

 while (true) 
  { cout << "Enter an integer value: ";
    cin >> i;
    if (i > 10) break;
  }
 return 0;
}

Here is an interesting example of using a "permanent" while which uses the break statement to "break out" of the loop. The condition for the while always true.



#include <iostream>
int main()
{bool value = true;
 int  i = 1;

 while (value) 
  { ++i;
    value = i < 5;
    cout << "value is " << value
         << " i is     " << i << endl;
  }
 return 0;
}

produces the output:

value is 1 i is     2
value is 1 i is     3
value is 1 i is     4
value is 0 i is     5

The last while example shows how you would normally use a while loop. The loop contains a statement which will terminate the loop when a certain condition arises. You can see too that the bool value is treated as an integer. A bool has a non-zero value (1) when true and is zero when false.


Return to top of page

Iteration - The Do .. While Loop

   do                 
    statement         
   while (expression);

The do ... while loop is a repeat ... until loop. The do ... while loop is distinguished by its having the condition after any processing which is within the scope of the loop.


//ex15.cc
#include <iostream>

int main()
{
 int number, right_digit;
 cout << "enter a number ";
 cin >> number;
 do
  { right_digit = number % 10;
    cout << right_digit;
    number = number / 10;
  } while (number != 0);

 return 0;
}

Here is an example of do ... while which reverses the digits of a number:


Return to top of page

Iteration - The For Loop (1)

The general form of a for loop is:

 for ( initial condition;
       terminal condition; 
       iteration step)
   statement;

or

     for (expr1; expr2; expr3)
      statement;

The for loop is a special case of a while loop:

     expr1;
     while (expr2)
      { statement;
        expr3;
      }

Usually expr1 and expr3 are assignment statements and expr2 a relational expression but the expressions can be left out:

     for(;;) {  some statements   }

The relational expression is assumed always true which means a break or return would have to be used to break out of the loop.

Here is are some simple examples of the for loop:

For loop examples

Example Comments
#include <iostream>
int main()
{ int i;
  for (i = 0; i < 10; ++i) 
   cout << " " << i; 
  return 0;
}

  1. the initial condition is set by i = 0 (expr1).
  2. the loop is terminated when i < 10 becomes false (expr2).
  3. the loop is iterated by ++i (expr3).
  4. the loop has a simple statement cout << " " << i; in its scope.
  5. the output is : 0 1 2 3 4 5 6 7 8 9

#include <iostream>
int main()
{ for (int i = 10; i < 30; i += 4) 
   cout << " " << i;  
  return 0;
}

  1. the initial condition is set by i = 10 (expr1).
  2. the loop is terminated when i < 30 becomes false (expr2).
  3. the loop is iterated by i += 4, ie it "moves" in steps of 4 (expr3).
  4. the loop has a simple statement cout << " " << i; in its scope.
  5. the output is : 10 14 18 22 26

#include <iostream>
#include <math.h>
int main()
{
 int i;
 double j;

 for (i = 8; i < 16; i++)
  cout << "2 "
       << " raised to the power "
       << i    << " is "
       << pow(2,i) 
       << endl; 

 cout << hex;

 for (i = 8; i < 16; i++)
  { j = pow(2,i);
    cout << "2 " << " raised to the power "
         << i    << " is "
         << (long) j
         << endl; 
  }
 return 0;
}

========= a modification ==========
 ... 
 
 long j;

 ...

 cout << hex;

 for (i = 8; i < 16; i++)
  { j = (long) pow(2,i);
    cout << "2 " << " raised to the power "
         << i    << " is "
         << j << "H"
         << endl; 
  }
 ...
 

  1. For both loops the initial condition is set by i = 8 (expr1).
  2. For both loops the loop is terminated when i < 16 becomes false (expr2).
  3. For both loops the loop is iterated by ++i (expr3).
  4. The first loop has a simple statement in its scope, the second s compound statement.
  5. the output is :
    2  raised to the power 8 is 256
    2  raised to the power 9 is 512
    2  raised to the power 10 is 1024
    2  raised to the power 11 is 2048
    2  raised to the power 12 is 4096
    2  raised to the power 13 is 8192
    2  raised to the power 14 is 16384
    2  raised to the power 15 is 32768
    2  raised to the power 8 is 100H
    2  raised to the power 9 is 200H
    2  raised to the power a is 400H
    2  raised to the power b is 800H
    2  raised to the power c is 1000H
    2  raised to the power d is 2000H
    2  raised to the power e is 4000H
    2  raised to the power f is 8000H
    
  6. Note the use of this: (long) j in the second loop. This is known as a typecast. It forces the double variable j to be treated as a long integer for the purpose of formatting its output. j has to be a double since the pow function returns a double precision float. See what happens if you leave the (long) out. You could achieve the same by declaring j to be a long and typecasting the result from the pow function to long j = (long) pow(2,i). Then you could leave the (long) off (long) j.

Return to top of page

Iteration - The For Loop (2) and the C++ operator comma ','

The comma operator most often finds use in a for statement. A pair of operands separated by a comma is evaluated left to right and the type and value of the result are the type and value of the right operand, i.e. multiple expressions can be placed in the for statement expressions.

More for loop examples

Example Comments
#include <iostream>
int main()
{ int i,x = 5;

  for (i = 0; i < 10; 
        cout << i << endl,
        x += 1,
        ++i);
  return 0;
}

  1. the initial condition is set by i = 0 (expr1).
  2. the loop is terminated when i < 10 becomes false (expr2).
  3. the loop is iterated by ++i.
  4. the loop has no statements in its scope but has three statements in the place of (expr3). Each statement is separated by a comma.

#include <iostream>
#include <time.h>
#include <stdio.h>

#define DAYS       365
#define HOURS       24
#define SECONDS   3600

int main()
{
 time_t the_time, the_old_time;
 clock_t ticks;
 int i = 20000;
 
 the_time = time(&the_time);
 the_old_time = the_time;
 
 cout << "It has been "
      << (double) the_time/(DAYS * HOURS * SECONDS) 
      << " years since UNIX time began" 
      << " (give or take a few days)."
      << endl;

 cout << "Press the enter key" << endl;

 getchar();

 for ( the_time = time(&the_time); 
       the_old_time < (the_time + 10);
       the_old_time = time(&the_old_time)
     )
  { i--;
    cout << "My how tempus fugits! Counting down "
	      << i << endl; 
  }

 ticks = clock();

 cout << "\nWe used " << ticks 
      << " clock ticks waiting there." 
      << endl;

 cout << "I say again " 
      << (clock() / CLOCKS_PER_SEC) 
      << " seconds."
      << endl;

 return 0;
}

  1. the initial condition is set by the_time = time(&the_time) (expr1).
  2. the loop is terminated when the_old_time < (the_time + 10) becomes false (expr2).
  3. the loop is iterated by the_old_time = time(&the_old_time) (expr3).
  4. the loop has a compound statement cout << " " << i; in its scope.
  5. the program uses some time-related functions - time() which returns the elapsed time in seconds since January 1 1970 (or thereabouts) and clock() which returns the number of seconds the program has been running. The datatypes time_t and clock_t are declared in the header file time.h.
  6. the program also uses an old C function called getchar(). This takes a char from the stdin device. To use this function we must include stdio.h.

Return to top of page


Tutorial

  1. Write a short program which demonstrates the NAND function.
  2. Write a short program which demonstrates the NOR function.
  3. Write a short program which shows that !(a && b) is the same as !a || !b.
  4. Write a program which plays a guessing game.
  5. An incomplete number guessing program is shown below. You have to complete it. Follow the instructions in the program.
    #include <iostream≶
    #include <math.h>   //we probably dont need this include file
    #include <time.h>   //we need this to use the time function
    #include <stdlib.h> //we need this for the srand() and rand() functions
    
    #define MAXTRIES 10       //Maximum number of tries 
    
    int main()
    { int compguess,            //the computer's number
          myguess,              //the user's guess
          count = 0;            //a count of tries
    
      srand(time(0));  //seed the random number generator
                       //with the current time
      compguess = rand() + 1; //get a random number
    //
    // RAND_MAX is the largest random value
    // It is defined in stdlib.h
    //
      cout << "RAND_MAX is " << RAND_MAX << endl;
      myguess = 0;
      do {
        cout << "Enter your guess: ";
        cin >> myguess;
    //
    // You now have the user's guess
    // Use if ... else to determine if the user's guess is correct, too low
    // or too high.
    //
    // Print these messages where appropriate:
    //
    // This is try number X your guess was correct
    // This is try number X your guess was too low
    // This is try number X your guess was too high
    //
    // X is the current try count
    // Keep a count of the user's attempts
    
    // You will need to complete this condition
    // While guess isn't the same as the computer number and we have
    // more tries yet
      } while (                                    );
    
      cout << "Computer's number was " << compguess;
      return 0;
    }
    

  6. Modify your number guessing game to accept the number of tries permitted from the user, ie you won't need MAXTRIES. Also instead of using a do ... while, now use a for loop.
  7. A last little challenge for you! Write a modified guessing game which doesn't count tries but uses a timeout - say 30 seconds. There is an example program using some time functions here.

Return to top of page


First Next Previous Last Glossary About


Copyright © 1999 - 2001 David Beech