Bottom     Previous     Contents

Chapter Two
Program Structure

Many people write BASIC programs without ever having thought very much about the resources at their disposal. Sitting down and writing a program 'as it comes' is a workable method for small programs but it is difficult to keep enough detail in your head when working on a large program. To write a large program easily and with the minimum of bugs it is important to understand the way that the instructions that constitute the BASIC language are best used to construct programs. The surprising fact is that the 'units' that make up a program are not, as most elementary BASIC textbooks suggest, single BASIC instructions such as IF or GOTO. The best way to think of, and hence write, a BASIC program is in terms of larger standard units each composed of a number of BASIC statements. For example. the action of the GOTO instruction is easy enough to understand; it transfers control to a given line number, but there are only a small number of circumstances in which it is necessary to transfer control to an out of sequence line number and therefore it is better to think in terms of the 'use' of the GOTO rather than simply what it does. These larger program 'building blocks' are often referred to as structuring elements and the programming method based on consciously using them in program construction is often referred to as structured programming. However, all these terms make it sound as though something forced and unnatural is going on in the use of a 'structuring method' when all that is really happening is the identification and conscious use of the natural structures which the BASIC programming language provides. This is akin to a skilled carpenter learning to work with the grain of the wood rather than against it. You can write programs that go against the 'grain' of BASIC but it is much better not to!

The two parts of a program

Any program has two aspects, its structure and its data. This corresponds to the two aspects of any list of instructions, they always tell you (a) what to do and (b) what to do it to.
In this sense, every program is like a simple English sentence it has a verb, the actions that are to be carried out, and a noun, the data that is to be manipulated by the program.
These two aspects are equally important and indeed there is a trade-off that can be made between the complexity of action and the complexity of the data that the action is applied to. For example, if you use a string to hold a list of numbers then the program to manipulate those numbers is likely to be more complicated than if you had used an array.
The subject of this and the next chapter is program structure. The other side of the coin, data, is dealt with in Chapter Five. What is missing from this neat division is the interaction that occurs between the two in writing a real program. This interaction is so problern-specific that it is almost impossible to discuss it directly. However, it is hoped that as well as illustrating program and data structure separately, the larger examples will also show how the two are balanced in program construction.

The flow of control and spaghetti

One of the first ideas that any programmer has to understand is the flow of control through a program. The default flow of control, whereby BASIC statements are executed in order of increasing line number and from right to left, is the first to be introduced. This rarely causes any trouble but programs that use nothing but the default flow of control are so simple that they completely fail to capture any of the power of a computer and therefore it is not long before the GOTO, IF and FOR statements are introduced as ways of altering the flow of control. The trouble is that normally no guidance is given on how to use these statements to construct programs. Their action is stated and after a few examples it is supposed that the problem in hand will make it clear how the flow of control has to be changed and hence which statements should be used. This is usually referred to as free style programming but for reasons that will be made clear it might better be called 'spaghetti' programming.
Before it is possible to discuss desirable features of the flow of control there has to be an easy way to see it. If you look at any program its flow of control will be difficult to appreciate because of the distracting elements of variables, PRINT statements, etc. If you take a pencil and draw a line that follows all of the possible routes through a program then the result is a 'map' of the flow of control that we can examine without being distracted by the other features of the program. For example, the flow of control map of a simple program that only uses the default flow of control is a straight line down the page (see Fig. 2.1). (It is usual to treat multiple statements on a single line as equivalent to a single 'compound' statement for the purposes of mapping the flow of control.)


Fig. 2.1 The default flow of control


Fig. 2.2. The division of the flow of control.

The effect of an IF statement is to divide the flow of control line into two parts corresponding to the path taken when the condition is true and the path taken when it is false (see Fig. 2.2). The effect of the GOTO statement on the flow of control line is much more difficult to summarise. It certainly diverts the flow of control line but the effect depends on where it is diverted to. Using the GOTO statement it is possible to produce a program that has a flow of control line that is reminiscent of tangled string or a bowl of spaghetti - hence the term spaghetti programming! (see Fig. 2.3).


Fig. 2.3. Spaghetti!

It should be easy to see that a program that has a simple flow of control line is easier to understand than one that is complicated and tangled. It follows from this that a simple flow of control is less likely to hide bugs because the programmer writing it has a better chance of completely understanding its action! The usual objection to this argument for simple flow of control is that complex programs can only be written using complex flow of control. To a very limited extent this is true. The simplest flow of control, the straight line running down the program, is clearly inadequate for writing any useful programs but the additions that have to be made to it before you can write any program are very few. In principle all you need is some method of forming a loop and a conditional branch, but in practice it is easier to use a few more ways of changing the flow of control - but not very many more and certainly not the complete freedom that the GOTO statement gives you to tie the flow of control in knots!
If you agree that spaghetti programs are a bad thing, then the next question is how to ensure simplicity and clarity without making programming an impossibly difficult activity. This question is answered in the following sections, but if you don't see the point of a simple flow of control then all of this will seem like a waste of time. It is therefore worth thinking a little about the way that you use the statements that alter the flow of control in a program before moving on to read the rest of this chapter. From now on our explicit objective will be to find easy-to-apply methods of keeping the flow of control simple. The main tool in achieving this objective is to only use a small, fixed number of ways of changing it. This approach also has the advantage that, no matter which ways of changing the flow of control are chosen as 'standard', they will be easy to recognise within a program and this in itself makes the program easier to understand.

The natural structure of BBC BASIC

The fact that any program can be written using nothing but loops and branches is remarkable and deserves a good deal of philosophical pondering in its own right. However, the subject of this book is practical programming and for this reason it is necessary to extend this limited range to include one or two other natural structuring elements. In particular, BBC BASIC provides a number of special control structures that fit very nicely into our overall objective of simplifying the flow of control fine but it is important to realise that they are not found in other, less well designed, dialects of BASIC. For this reason structured programming in BBC BASIC is a little different from the structured programming in other dialects of BASIC but the objective is still the same. (The reader is referred to The Complete Programmer (Granada, 1983) for details of natural structured programming in traditional BASIC.)

As BBC BASIC also includes many of the instructions of traditional BASIC there is sometimes an over provision of facilities. The most obvious example is the ability to construct subroutines using GOSUB and procedures using PROC. Procedures and subroutines serve the same purpose but, whereas GOSUB is traditional BASIC, procedures are new and do the job much better. The presence of:

IF ... THEN line number

and

IF ... THEN list 1 ELSE list 2

where 'list 1' and 'list 2' are collections of BASIC statements, is also an example of traditional BASIC versus enhanced BASIC. In early versions of BASIC the only form of the IF statement allowed was IF . . . THEN line number and BBC BASIC has to include this form to make sure that existing programs will run. However, the second form is a much more helpful when it comes to keeping the flow of control line simple and is therefore to be preferred.
It would be nice to avoid any use of older forms of BASIC when writing naturally structured BBC BASIC, but in practice this level of strictness would add too much to the tedium of programming! You can certainly avoid the use of the extremes like GOSUB and IF . . . THEN line number but there are one or two traditional statements that are more difficult to give up. For example, it is possible to write structured BBC BASIC without ever using the GOTO! In this sense the GOTO statement is yet another part of traditional BASIC that has found its way into BBC BASIC. Some people do advocate this total abolition of the GOTO statement as the essence of structured programming and it is easy to see why. The GOTO statement is certainly responsible for most of the tangles in the flow of control line and abolishing it would make it very difficult to write spaghetti programs difficult but not impossible! While avoiding the use of the GOTO would serve our main objective of simplifying the flow of control it turns out to be more useful to examine and allow a few uses of the GOTO statement. This attitude can be summed up as 'the GOTO is a dangerous but powerful statement that it is worth learning to use properly'.
As the two fundamental forms of flow of control are selection between a number of alternatives and loops, it is worth looking at the best ways of implementing each of these in turn, but first it is necessary to consider briefly the role of line numbers in BASIC.

The trouble with line numbers

In nearly all versions of BASIC (there are one or two exceptions) each line in a program must have a line number. This is so much part of the BASIC language that BASIC programmers rarely stop to question if so many line numbers are really necessary. BASIC line numbers serve two purposes as convenient 'markers' for editing program lines and as 'labels' that are used by GOTO and GOSUB commands. It is clear that as far as editing is concerned, for the method to work every line must have a line number but for the use of GOTO and GOS UB the only lines that need line numbers are those that are actually referred to in GOTO or GOSUB commands.
There are many reasons why the dual function that line numbers serve is a problem in the easy production of clear and bug-free programs. The most important are:

(1) The line misplacement problem

The fact that every line has to have a line number to determine its position within the program is a mechanism that is very sensitive to typing errors. You only have to mistype a single digit and, not only does a line appear to be missing at one position, an extra line appears elsewhere, possibly in part of a program that was finished and debugged some time before. In this sense, typing a single digit incorrectly causes the destruction of the overall correctness of the program and leaves a very difficult bug lurking in a part of the program that you have tested and is therefore almost above suspicion! (This aspect of line numbers is taken up again in Chapter Seven,)

(2) Fixed destinations

When a line number is used in a GOTO or GOSUB statement, it is an advantage if this line number remains unchanged throughout the life of the program. The reason for this is that the line number of the destination of a GOTO or COS UB serves to 'name' a part of the program that performs a particular task. If this 'name' changes during the development of a program then it is possible that the programmer will incorrectly use the 'old' value instead of the correct new value when re-using that part of the program. For example, if during the initial implementation of a program, subroutine 1000 prints an opening message then you are likely to use GOSUB 1000 later on to print the same message. If, however, in the intervening time it has been necessary to renumber the program so that extra lines can be inserted, fine 1000 may be assigned a new fine number, 1370, say. From this point on, the programmer must remember that what was once referred to as subroutine 1000 is now subroutine 1370, a task made even more difficult by having to remember the fine number changes for all the other subroutines in the program! The moral is that renumbering is generally a bad thing.

(3) The forward jump problem

When writing a program it is easy to use a GOTO statement to transfer control back to a point earlier in the program. The reason for this is that usually the earlier part of the program is already written and it is very easy to find the line number of the point to which you want to return. This should be compared to the situation of using the GOTO to transfer control forward to a line later in the program. In this case the chances are that the line to which you are trying to transfer control has not yet been written. The line number that it will eventually be assigned is difficult to work out as it depends on the number of statements that will be written and the line number increment in use. The best solution to the forward jump problem is not to make a guess at the fine number but to use a symbol such as '*' to indicate that you have to return and fill in the missing line number after the line concerned has been written. If you guess the line number it is possible that you will get it wrong and this will go undetected because, even though the line number you used was incorrect, the GOTO is still valid BASIC. If you use '*' to mark incomplete GOTO statements it is impossible to forget them as they will cause the program to crash if not removed!
It is possible to imagine a version of BBC BASIC that doesn't use line numbers for editing. Program fines could be entered, deleted, fisted and modified by use of the cursor keys instead. This would be a great improvement because the confusion and difficulties that result from the dual use of fine numbers would be completely eliminated. Failing this, the best course of action is to try to avoid the use of line numbers within GOTO and GOSUB as much as possible. Once again we have a reason for minimising the use of the GOTO and GOSUB statements!

Selecting between two alternatives

The simplest form of selecting between a number of alternatives is when there are only two possibilities. This corresponds to the well known:

IF condition THEN list 1 ELSE list 2

where 'list 1' and 'list 2' are collections of BASIC statements. The action of this statement is familiar enough if the 'condition' is true then 'list I' will be executed; if the 'condition' is false then 'list 2' will be executed. You can see this causes the flow of control line to split into two possible paths which recombine only after the entire statement is complete, see Fig. 2.2. This is a particularly simple way of dividing the flow of control; you can immediately see what happens when 'condition' is true and when it is 'false'. You can also see instantly where the flow of control fine recombines. If you think that these are small considerations, compare IF. .. THEN. ..ELSE with the traditional BASIC way of selecting between two alternatives:

IF condition THEN GOTO x
. . .
list 2
. . .
GOTO y
x . . .
list 1
. . .
y rest of BASIC program

where 'x' and 'y' are line numbers. Using this method in a real program makes it difficult to see what happens when 'condition' is true and when it is false. It is also very difficult to see where the flow of control line recombines and continues through the rest of the program.
The advantages of the IF. . . THEN . . . ELSE form of the BASIC statement make it worth using in preference to ail other forms. When either 'list 1' or 'list 2' contain only a few statements they can be written within the IF statement separated by colons. If the lists are at all long they should be turned into procedures and then called from within the IF statement. For example, rather than:

IF condition THEN t1:t2:t3 . . . tn
ELSE e1:e2:e3 . . . en

where t1 to tn and e1 to en are lists of BASIC instructions use:

IF condition THEN PROCIist_1 ELSE PROClist_2

where PROClist_1 and PROClist_2 are defined elsewhere in the program and consist of statements t! to tn and e1 to en respectively. The subject of using procedures is discussed more fully in Chapter Three but even at this early stage they show themselves as one of the most useful features of BBC BASIC. Notice that it is never necessary to use:

IF . . . THEN GOTO x ELSE GOTO y

or

IF . . . THEN GOSUB x ELSE GOSUB y

where x and y are line numbers.
It looks as though the subject of selection is completely settled in that the IF . . . THEN . . . ELSE statement is just right for the job, but there is the question of what should happen when there are more than two possible courses of action. Or, at an even simpler level, how should the very common situation of conditional execution of one fist of statements be handled ?

THEN without ELSE

If you examine almost any BASIC program you will find that the form of the IF statement that occurs most often is:

IF condition THEN list of statements

This can be regarded as a special form of the IF . . . THEN . . . ELSE statement where the list of actions that follow the ELSE part is empty. Although this may seem like a rather academic way of looking at a perfectly simple and practical BASIC statement, it does highlight a number of issues. The 'list of statements' following the THEN will of course only be carried out if 'condition' is true but in practice the converse is just as common a requirement; that is, the list of statements will be 'skipped' if a condition is true. This corresponds to an IF statement with an empty statement list following the ELSE. While you can indeed write something like:

IF A=0 THEN ELSE PRINT "Not Zero"

there is something very difficult and confusing about reading THEN ELSE. Of course, the most commonly encountered solution is to use the NOT of the 'condition' as in:

IF NOT (A=0) THEN PRINT "Not Zero"

or even the more readable:

IF A<>0 THEN PRINT "Not Zero"

Notice that although in this simple example the final form of the IF statement looks the easiest and the one that should always be used, this is not the case if the 'condition' is at all complicated. For example, if you want to skip a list of statements when:

A=0 AND (B<>0 OR Z=100)

is TRUE, it is much easier to write:

IF NOT (A=0 AND (B<>0 OR Z=100)) THEN list

rather than try to work out what the NOT of the condition is.
It is important to notice in this discussion of the IF . . . THEN statement that there is an implicit assumption that the list of statements that follows the THEN never need contain a GOTO. In particular there is never any need to use:

IF condition THEN GOTO x

to determine whether to execute or skip a section of program. If you need to execute a section of program according to some condition then use:

IF condition THEN list

and if you need to skip a section of program according to a condition then use:

IF NOT(condition) THEN list

Once again if the 'list' of statements becomes too long to be conveniently written on one line then it should be turned into a procedure

Multiple selection - ON

It is not often that a program has to execute one of a large number of alternatives according to a condition but when it does happen it is usually a major feature such as a 'menu selection' with a great many alternatives. Traditional BASIC uses the:

ON x GOTO list of line numbers

or

ON x GOSUB list of line numbers

to select which of a number of sections of program will be executed. The value of x, a numeric variable, selects which of the 'list of line numbers' will be the destination of the GOTO or GOSUB command. For example:

ON I GOSUB 1000,2000,3000,4000

will transfer control to 1000 if I is 1, to 2000 if I is 2 and so on. In this case if I is less than I or greater than 4 the program will crash. BBC BASIC has both ON. . .GOTO and ON. . .GOSUB and it even allows the statements to be followed by an ELSE statement to avoid crashing on out of range values Thus the previous example could be written:

ON I GOSUB 1000,2000,3000,4000
ELSE GOSUB 3000

and subroutine 5000 would be called if I was less than 1 or greater than 4.
Certainly if you are going to use the ON statement you should use the ON.. .GOSUB form and always follow it with an ELSE statement to catch out of range values. However, following the earlier discussion of the sort of problems that using line numbers bring it is obviously better to avoid the ON statement if at all possible. In theory, it is always possible to use a collection of IF statements to replace a single ON statement. For example, the previous ON . . . GOSUB can be written:

IF I=1 THEN PROCaction_one
IF I=2 THEN PROCaction_two
IF I=3 THEN PROCaction_three
IF I=4 THEN PROCaction_four
IF I<1 OR I>4 THEN PROCaction_error

Notice that each of the conditions is mutually exclusive and only one of the procedures following the THEN will be executed. The correctness of the scheme depends on one vital implied rule:

the value of I must not be changed by any of
the procedures following the THEN

If this rule is broken then it is possible that more than one of the procedures will be executed. Sometimes there is a temptation to break this type of rule to obtain a quick result For example, if PROCaction_one changes I to 4 then when I is initially 1 both PROCaction_one and PROCaction_four will be called. This is the worst sort of opportunist programming! Anyone reading the program would be very unlikely to spot this trick and the results could be a completely tangled and bugged program! If your intention is also to call PROCaction_four when I is 1 then make it clear by:

IF I=1 THEN PROCaction_one:PROCaction_four

In most cases the conditions in the collection of IF statements are not as simple as I=1, 1=2 and so on and therefore it is much more difficult to ensure that only one of the procedures (or fists of statements) will be executed. In situations where the conditions to be satisfied are complicated it is usually sufficient to ensure that each condition correctly determines whether or not a procedure (or list of statements) should be executed and that nothing that would effect the condition is altered until all of the IFs are completed.
You might object that this method of selecting one of a number of actions is inefficient and slow. Surely there is no need to work through the rest of the IF statements after one of them has found a true condition? The answer is that there is no satisfactory way of gaining the slight speed advantage of skipping the remaining tests after a true condition has been found without reducing the readability and simplicity of the program. One method that is often advocated is the 'nesting' (see later) of IF statements as in:

IF A=1 THEN PRINT "One" ELSE
IF A=2 THEN PRINT "Two"
ELSE IF A=3 THEN PRINT "Three"
ELSE PRINT "Error"

By no stretch of the imagination can this be considered as clear (and therefore less likely to hide bugs) as:

IF A=1 THEN PRINT "One"
IF A=2 THEN PRINT "Two"
IF A 3 THEN PRINT "Three"
IF A<1 OR A>3 THEN PRINT "Error"

There are plenty of examples of the use of the IF statement to make choices in later chapters. Finally, it is worth recalling that what matters is clarity and simplicity. Do not value short cuts that save a few fines of program they will cost you much more time when it comes to debugging.

Loops

The other fundamental way of altering the flow of control is the loop. It is difficult to think of a worthwhile program that doesn't contain some element of repetition. Although BBC BASIC contains two distinct and special instruction pairs FOR. . .NEXT and REPEAT. . .UNTIL there is still a role for loops built using IF and GOTO and this is one of the few cases where it is worth risking the dangerous GOTO in a program.
The basic mechanism of all loops can be seen in the infinite loop:

x list of BASIC statements
. . .
. . .
GOTO x

The GOTO x transfers control back to line number 'x' and so repeats the lines of BASIC in between forever. In this description it is assumed that there are no GOTO statements within the loop that transfer control out of it.
Infinite loops are sometimes useful in applications where a computer has to control some piece of equipment theoretically forever, but apart from this loops usually have some way of coming to an end that is they are finite loops. A finite loop is produced from an infinite loop by the addition of a conditional statement that transfers control out of the loop hence their alternative name conditional loops. The standard form of the conditional loop is:

x list of BASIC statements
. . .
IF condition THEN GOTO y
. . .
list of BASIC statements
GOTO x
y rest of program

The IF statement transfers control out of the loop to fine number 'y' when 'condition' is true. This constitutes an 'exit point' for the loop and its 'condition' is an 'exit condition', see Fig. 2.4.
The only way that finite loops differ from one another is in the number and position of their exit points. There are advantages of simplicity and clarity in using only one exit point within a loop. If there is only one exit point it is easy to determine what the exit condition is and where control is transferred when the loop ends. However, there are exceptions to this one exit point rule and these will be discussed later.


Fig. 2.4. A conditional loop

Given that there is only one exit point, the only scope for variation is in its placement. Once again, there are advantages of clarity and simplicity in placing restrictions on the way that loops are formed. Two favoured positions for loop exit points are at the very start of the loop and at the very end. Loops that have their single exit point at the start are usually called while loops and those that have their single exit point at the end are called until loops. The reason for these names is not important; they have their roots in other computer languages. What is important, however, is that BBC BASIC provides a pair of instructions, REPEAT and UNTIL, that explicitly implement until loops. Thus, rather than:

x list of BASIC statements
. . .
. . .
IF condition THEN GOTO y
GOTO x

use

REPEAT
list of BASIC statements
. . .
. . .
UNTIL condition

Notice that the REPEAT .. .UNTIL form of the loop completely avoids the use of GOTOs and line numbers. Unfortunately, BBC BASIC doesn't include a pair of instructions to implement a while loop and so there is no choice but to construct it from scratch using IF and GOTO.
As a while loop has an exit point at its beginning it is possible for this exit to be taken without the statements within the loop ever being executed. However, the statements within an until loop have to be executed before the exit point is reached. In other words, you can execute a while loop any number of times including zero but you have to execute an until loop at least once.
Apart from these two simple characteristics concerning the minimum number of times that a loop can be executed, the main advantage of placing exit points at the start or the end of a loop is that all of the statements within the loop will be carried out the same number of times. For example, in the conditional loop:

10 I=0
20 I=I+1
30 IF I=10 THEN GOTO 60
40 PRINT I
50 GOTO 20
60 END

Statement 20 is executed ten times but statement 40 is executed only nine times. In general, the portion of the loop before the exit point is always executed once more than the portion of the loop that follows the exit point. The accepted wisdom is that this difference in the number of times statements are executed within a loop makes it difficult to understand, and hence debug, programs that contain anything other than while or until loops. However to restrict all conditional loops to just these two types is unnecessarily harsh. A natural form of loop that often occurs in BASIC is:

x pre-exit statements
IF condition THEN GOTO y
post-exit statements
GOTO x
y rest of the program

where the pre-exit statements perform any actions that are necessary to discover the current 'value' of the 'condition' and the post-exit statements carry out the actions that have to be repeated if the 'condition' is false. This form of 'loop is more complicated and difficult to debug than either the while or the until loop and it should only be used when absolutely necessary. This more general conditional loop can often be found in BASIC programs where a little thought would have proved the while or the until loop perfectly suitable. In short use the while and until forms of the conditional loop unless there is a real need to use a more general form.

Multiple exit points

Although the emphasis in the last section was on the use of conditional loops with one exit point, there are times when a program can be made easier to understand by the use of more than one exit point. It is important to realise that the only reason for using such a complicated form of conditional loop is that control needs to be transferred to a number of different points depending on what 'condition' caused the loop to end. It should never be necessary to use more than one exit point if they transfer control to the same position within a program. For example. the loop:

x list of BASIC statements
. . .
IF condition 1 THEN GOTO y
. . .
IF condition 2 THEN GOTO y
GOTO x
y rest of program

can be reduced to the much simpler form:

x list of BASIC statements
. . .
IF condition 1 OR condition 2 THEN GOTO y
. . .
GOTO x
y rest of program

Of course there is the problem of exactly where the single exit point should be placed in the loop to give the same effective result as the pair of separate exit points but this is usually not at all difficult.
The real use of multiple exit points occurs when there are different reasons for leaving the loop and different actions that have to be carried out subsequently. For example, suppose you are searching a string array for a particular word using a loop that compares each element of the array against the 'target' string. There are two distinct reasons for leaving the loop. Either the target is found and further processing is necessary or it isn't and an error message (say) has to be printed. In this case, using a loop with two exit points is permissible and may even result in a simpler program. For example compare:

1000 I= I
1010 IF S$=T$(I) THEN GOTO 2000
1020 IF I=N THEN GOTO 3000
1030 I=I+1
1040 GOTO l0l0

which searches the string array T$ for an occurrence of the string in S$ using two exit points line 1010 exits to line 2000 if the string is found and line 1020 exits to fine 3000 if it isn't with its single exit point version:

1000 I=1
1010 IF S$=T$(I) OR FN THEN GOTO 2000
1020 I=I+1
1030 GOTO 1010

which is shorter but leaves the task of sorting out what causes the loop to end to the part of the program starting at line 2000.
It is rare for it to be necessary to use more than two separate exit points and conditions within a single loop and even then in most cases the exit points can be replaced next to each other.

Enumeration loops - FOR . . . NEXT

There is one very special and very important class of conditional loop with one exit point, the enumeration loop. An enumeration loop is one that causes a section of program to be repeated a number of times that is fixed before the loop begins. All versions of BASIC, including BBC BASIC, have a pair of instructions FOR . . . NEXT that are intended to be used to construct enumeration loops. For example:

FOR I=1 TO 10
. . .
list of BASIC statements
. . .
NEXT I

will repeat the 'list of BASIC statements' ten times. In some ways the existence of a 'loop counter' or 'index variable' (I in the example given above) that 'counts' the number of times that the loop has been executed is unnecessary to the idea of an enumeration loop but in practice it turns out to be an almost indispensable feature in the FOR loop, In particular, the index variable is often used in array calculation, etc., within the loop but its value should never be changed by direct assignment. If this rule is broken and the index variable's value is altered as the loop progresses the result is not fatal from the program's point of view, as the loop will run, but the task of working out how many times it will repeat is very difficult. The rule is that the number of times an enumeration loop is executed should always be clear' from an examination of the FOR statement without having to delve into the list of statements within the loop. This &so implies that an IF statement or direct assignment to the index variable should never be used to leave a FOR loop early. For example, searching a string array for a particular value is often done using:

1000 FOR I=1 TO N
1010 IF S$=T$(I) THEN GOTO 2000
1020 NEXT I

where line 1010 terminates the FOR loop when (and if) the value in S$ is found in T$(I). This is not only bad programming style, it will eventually cause the program to crash. This is because each time a FOR loop is begun an entry is created in an area of memory known as the FOR stack. This entry is only removed when the normal exit is made from the FOR loop. Leaving the loop early, as in the above example, does not remove the entry and if this is repeated the FOR stack becomes so clogged with data on incomplete FOR loops that there is no room for any more hence the crash. The correct way to leave a FOR loop without crashing the program is to set the index variable to the final value:

1000 FOR 1=1 TO N
1010 IF S$=T$(I) THEN J=I:I=N
1020 NEXT I

Notice that to keep track of where the entry was found the value of I has to be saved in J before it is set to N so terminating the loop. However, as far as programming style is concerned there is no good way of exiting a FOR loop early! The whole point of an enumeration loop is that it is executed a given number of times and does not exit on any other condition. If you find that you are always exiting FOR loops before they are complete the chances are that you are confusing the purpose of enumeration and conditional loops.
It has already been stated that a FOR loop has only one implicit exit point. The remaining question is where is it placed? There are only two practical possibilities at the end of the loop (giving an 'until' form of the enumeration loop) and at the beginning (giving a 'while' form of the enumeration loop). The difference in practice is only the number of times that the FOR loop will be executed. If the exit point is at the end the loop must be carried out at least once before the test for exit is made. On the other hand if the exit point is at the start, the exit can occur before the loop is even executed once. The trouble is that different versions of BASIC use different forms of the FOR loop some use the 'until' FOR and others use the 'while' FOR. BBC BASIC uses the 'until' version of the FOR loop and so the loop is executed at least once to reach the test. For example:

10 FOR I=2 TO 1
20 PRINT I
30 NEXT I

will print 2 on the BBC Micro's screen but on some versions of BASIC the loop will not be executed even once. As long as you know which type of FOR loop you are working with there is no problem. The difficulties arise when switching between different versions of BASIC.
Finally the FOR loop has one extra, and often dangerous, refinement the STEP statement As the value of the index variable is often involved in calculations the BASIC command STEP can be used to alter the amount by which the index variable is increased each time through the loop. For example:

10 FOR I=10 TO 1 STEP -1
20 PRINT I
30 NEXT I

is an enumeration loop which is carried out ten times, but the value of the index variable decreases by 1 each time through the loop. Integer values of STEP size are fairly easy to deal with and the meaning of the resulting loop is usually quite clear. The trouble really begins when fractional values are used for the STEP size. For example you might like to try to work out the last number printed by the following FOR loop when it is run on the BBC Micro:

10 FOR I=0 TO 1 STEP .1
20 PRINT I
30 NEXT I

The answer is not 1! Ambiguities such as this are common when the STEP size is a fraction and are a consequence of the way fractions are represented in binary. Even so, occasionally it has to be admitted that a fractional STEP size is the clearest and simplest way of achieving something.

A family tree of loops

There is no doubt that the number of loop types is large enough to be confusing at first acquaintance. At this point in the discussion it is worth summarising the information that has been presented concerning loops in the form of a diagram see Fig. 2.5.


Fig. 2.5. Loops

Constructing programs sequencing and nesting

The basic idea that lies behind structured programming is that programs are constructed using nothing but the structuring elements that have been introduced in this chapter. So far nothing has been said about how these structuring elements can be put together in combination. An important factor Up be noted when combining structuring elements is that their pattern of flow of control should not be altered. In particular it is important that a GOTO instruction doesn't transfer control into the body of a structuring element. This rules out, for example, jumping into loops, etc. It is surprising to discover just how few and simple the possibilities are. In fact there are only two sequencing and nesting. Sequencing corresponds to the most obvious way of putting structuring elements together for they are simply arranged one after the other i.e. in sequence. For example, a loop may be followed by an IF statement and then another loop and so on. Sequencing is rather like writing each of the structuring elements on a card and making up a program by laying the cards out in the desired order.
The second way of combining structuring elements - nesting - is more complicated, but very natural and familiar to all programmers. Nesting is where one structuring element occurs as part of one of the 'lists of BASIC statements' that have been present in each of the definitions given so far. The most familiar example of nesting is when a loop occurs within another loop as in:

10 FOR I=1 TO 10
20 FOR J=1 TO 10
30 PRINT I,J
40 NEXT J
50 NEXT I

where the FOR loop at lines 20 to 40 is completely contained, or nested, within the FOR loop at lines l0 to 50, see Fig. 2.6. Notice that the phrase 'completely contained' is implied in the very idea of a structuring element.
If you were somehow only partially to include one structuring element within another the result would be a brand new pattern of flow of control and this would go against the very idea of using only a small and fixed number of ways of altering the flow of control. Although loops are the most often encountered examples of nesting, it is possible to have nested IF statements. Indeed, the example given in the earlier section on multiple selection used nested IFs. Nested IFs are generally difficult to understand and should be avoided or converted to a single IF. For example the nesting:


Fig. 2.6. Nesting.

IF condition 1 THEN IF condition 2
THEN list of BASIC statements

is better written as:

IF condition 1 AND condition 2
THEN list of BASIC statements

However, there is one case where nested IFs are important and this is where 'condition 2' would cause an error if it was evaluated when 'condition 1' was false.

Freedom, efficiency and structure

The account of structured programming given here is nowhere near as restrictive as that found in most books that advocate structured programming as a method of producing easy to understand, bug-free programs. Hard line structured programming generally forbids the use of GOTO and only allows the use of the until, while and FOR loops. However, the whole point of structured programming is to produce a simple and recognisable flow of control and, while this is an important objective, overall program simplicity should never be sacrificed to the application of nothing but the standard programming elements. For example, there are some occasions when the ON . . . GOSUB statement is so right for the job that it is better to use it than avoid it. The rules about which structuring elements to use are only rules to the unskilled programmer - the advanced programmer exercises judgement. Another problem that often arises is the question of efficiency. Early programmers were taught that the main objective of programming was to write programs that work fast and use little memory. These days, with hardware being so much better and high level languages improving all the time, efficiency is much less important. Now it is the cost and reliability of software that matters and structured programming reduces cost and increases reliability.


Next     Top