Decisions, Decisions

What will we cover?
  • The 3rd programming construct - Branching
  • Single branches and multiple branches
  • Using Boolean expressions

The 3rd of our fundamental building blocks is branching or conditional statements. These are simply terms to describe the ability within our programs to execute one of several possible sequences of code(branches) depending on some condition.

Back in the early days of Assembler programs the simplest branch was a JUMP instruction where the program literally jumped to a specified memory address, usually if the result of the previous instruction was zero. Amazingly complex programs were written with virtually no other form of condition possible - vindicating Dijkstras statement about the minimum requirements for programming. When high level languages came along a new version of the JUMP instruction appeared called GOTO. In fact BASIC still provides GOTO and you can try it out by typing the following bit of code:

10 PRINT "Starting at line 10"
20 J = 5
30 IF J < 10 GOTO 50
40 Print "This line is not printed"
50 STOP

Notice how even in such a short program it takes a few seconds to figure out what's going to happen. There is no structure to the code, you have to literally figure it out as you read it. In large programs it becomes impossible. For that reason most modern programming languages either don't have a direct JUMP or GOTO statement or discourage you from using it.

The if statement

The most intuitively obvious conditional statement is the if, then, else construct. It follows the logic of English in that if some boolean condition is true then a block of statements is executed otherwise (or else) a different block is executed.

It looks like this in BASIC:

PRINT "Starting Here"
J = 5
IF J > 10 THEN
    PRINT "This is never printed"
ELSE
    STOP
END IF

Hopefully that is easier to read and understand than the previous GOTO example. Of course we can put any test condition we like after the if, so long as it evaluates to True or False, i.e. a boolean value.

Python looks quite similar:

import sys  # only to let us exit
print "Starting here"
j = 5
if j > 10:
    print "This is never printed"
else:
    sys.exit()

Its very nearly identical, isn't it?

You can go on to chain these if/then/else statements together by nesting them one inside the other like so:

# Assume width created previously...
if width == 100:
   area = 0 
else:
   if width == 200:
      length = length * 2
   else:
      if width == 500:
           width = width/10
      else:
           print "width is an unexpected value!"

Note:we used == to test for equality in each if statement, whereas we used = to assign values to the variables. Using = when you mean to use == is one of the common mistakes in programming Python, fortunately Python warns you that it's a syntax error, but you might need to look closely to spot the problem.

Boolean Expressions

You might remember that in the 'Raw Materials' section we mentioned a Boolean type of data. We said it had only two values: true or false. We very rarely create a Boolean variable but we often create temporary Boolean values using expressions. An expression is a combination of variables and values combined by operators to produce a value. In the foloowing example:

if x < 5:
  print x

x < 5 is the expression. Expressions can be arbitrarily complex provided they evaluate to a single final value. In the case of a branch that value must be either true or false. However, the definition of these 2 values varies from language to language. In many languages false is the same as 0 or a non-existent value(often called NULL, Nil or None). Thus an empty list or string evaluates to false in a Boolean context. This means we can use a while loop to process a list until the list is empty, or example. Python, QBASIC and Tcl all take this approach to Boolean values.

Tcl branches

Tcl's if statement is very similar, looking like this:

if {$x < 5} {
   puts $x
}elseif {$x == 5} {
   puts "its 5!"
}else{
   puts "greater than 5"
   }

That should be straightforward, of course the elseif and else parts are optional. But you probably guessed that.

Case statements

A sequence of nested if/else/if/else... is such a common construction that many languages provide a special type of branch for it. This is often referred to as a Case or Switch statement and the Tcl version looks like:

switch $width {
    100 { set area 0} 
    200 { set length [expr {$length * 2}] }
    500 { set width [expr {$width / 2}] }
    }

Modern BASICs have a version too:

SELECT CASE width 
 CASE 100
   LET area = 0
 CASE 200
   LET length = length * 2
 CASE 500
   LET width = width / 2
 ELSE PRINT "Width not recognised"
END SELECT

Python does not provide an explicit case construct but rather compromises by providing an easier if/elseif/else format:

if width < 100:
   area = 0
elif width < 200:
   length = length * 2
elif width < 500:
   width = width/10
else:
   print "width is too big!"

Note the use of elif and the fact that the indentation (all important in Python) does not change. It's also worth pointing out that both this version and the earlier Python example of this program are equally valid, the second is just a little easier to read if there are many tests.

BASIC also provides a slightly more cumbersome version of this technique with ElseIf...THEN which is used in exactly the same way as the Python elif but is rarely seen since CASE is easier to use.

So What's the Point?

So far our examples have been pretty abstract. To conclude let's take a look at an example that uses branching for something more tangible, and at the same time introduces a common programming technique, namely menus for limiting user input.

Here is the code, followed by a brief discussion:


#################################
# Note use of triple quoted string to make a menu
print """
Choose a shape from the list:
1) Triangle
2) Square
3) Circle
"""

shape = raw_input("Which shape[1,2,3]? ")

# note must now test for character '1' not 
# number 1 coz raw_input returns strings not numbers

if shape == '1':     # a triangle
   ht = input('What is the height of your triangle? ')
   base = input('How long is the base? ')
   print "The triangle's area is: ", 0.5*base*ht

elif shape == '2':   # square
   side = input("How long are the square's sides? ")
   print "The square's area is: ", side*side

elif shape == '3':   # a circle 
   rad = input('What radius is your circle? ')
   print "The circle's area is: ", 3.14159*rad*rad

else:
   print "Sorry, You didn't enter a valid choice"

So we present a menu of choices to the user and depending on which choice the user makes we prompt for the appropriate type of input and calculate the area. The final else simply presents an error message if the user doesn't pick one of the menu choices available.

What the program does is create the illusion to the user that the program knows what they want to do and does it correctly, acting differently depending what they input. In essence the user appears to be in control, whereas in fact, the programmer is in control since the he has anticipated all the valid inputs and how the program will react. The intelligence on display is that of the programmer, not the machine - computers after all are stupid!

The point of branches therefore is to endow our programs with the appearance of intelligence. Depending on the values of the branch variables in the conditions(shape in the case above) the program follows different paths through the code.

Finally you might like to try wrapping this program up in a loop so that it repeats the presentation of the menu until the user selects the Quit option - which you'll need to add to the menu of course! If you manage that successfully you will have the basic framework for many types of program - present a menu and act on the users selection.

Things to Remember
  • Use if/else to branch
  • The else is optional
  • Multiple decisions can be represented using a CASE or if/elif construct
  • Boolean expressions return true or false

Previous  Next  Contents


If you have any questions or feedback on this page send me mail at: alan.gauld@btinternet.com