www.riscos.com Technical Support: |
|
Normally, lines in a BASIC program are executed in sequence, one after the other. However, the language includes two types of structure which alter this sequence:
In all cases, the code is easier to read if it is clear which statements are in the loop and which are conditional on certain factors. This clarity can be achieved by use of the LISTO command before listing the programs, to indent the conditional and loop structures in the listing. All programs included in this chapter are listed as if the command:
LISTO 3
had been typed beforehand; this gives a space after the line number and indents structures.
The IF (single line) statement may be used to enable the computer to make a choice about whether or not to execute a statement or group of statements. It has the form
IF condition [THEN] statements [ELSE statements]
A condition is an expression that gives a number. It is said to be TRUE if the number if not zero, or FALSE if the number is zero. Usually the relational operators described below are used in conditional expressions.
The statements after the THEN keyword (which is optional, as indicated by the square brackets) are only executed if the condition is TRUE. If it is FALSE, the statements are skipped. However, if there is an ELSE, then the statements following that are executed if the condition is FALSE.
For example:
10 PRINT "What is 2 * 4" 20 INPUT ans% 30 IF ans% = 8 THEN PRINT "Well done" ELSE PRINT "Wrong"
Line 30 contains a conditional expression. In the example shown the expression is TRUE (i.e. has a non-zero value) when ans% is equal to 8, and is FALSE (i.e. has a zero value) otherwise. Note that in an IF statement, either the THEN part or the ELSE part (if present) is executed, never both.
Any non-zero number is treated as TRUE in an IF statement, however, the comparison operators described in the following section return a particular value meaning TRUE: -1. They return 0 for FALSE, of course. In addition, there are two functions called FALSE and TRUE which return 0 and -1 respectively.
Two kinds of operators may be used in expressions:
Relational operators can be used to evaluate numbers or strings:
In the following, A and B can be integers or floating point numbers.
Operator | Meaning |
---|---|
A$ = B$ | TRUE when A$ and B$ are the same |
A$ <> B$ | TRUE when A$ and B$ are different |
A$ < B$ | String comparisons; see below: |
A$ > B$ | |
A$ <= B$ | |
A$ >= B$ |
Corresponding characters of each string are examined until either they are different, or the end of a string is reached. If the strings are the same length, and the corresponding characters are the same, the strings are said to be equal; otherwise, the shorter string is 'less than' the longer one.
In the case where the two corresponding characters differ, the relationship between the strings is the same as that between the ASCII codes of the mismatched characters. For example, "HI" < "Hi" yields TRUE, because the ASCII code of upper case I is less than that of lower case i. Similarly, "SIX" > "FIFTEEN" is TRUE because "SIX" starts with S, and the ASCII value of S is larger than that of F.
Operator | Meaning |
---|---|
NOT A | TRUE when A is FALSE |
A AND B | TRUE if both A and B are TRUE |
A OR B | TRUE if either A or B or both are TRUE |
A EOR B | TRUE if either A or B but not both are TRUE |
A block structured IF THEN [ELSE ] ENDIF statement is available. It executes a series of statements, which may be split over several lines, conditionally on the result of the IF expression.
10 n% = RND(10) 20 m% = RND(10) 30 PRINT "What is ";n% " * "m%; 40 INPUT ans% 50 IF ans% = n%*m% THEN 60 PRINT "Well done" 70 ELSE 80 PRINT "Wrong" 90 PRINT n%;" * ";m% " = ";n%*m% 100 ENDIF
The ENDIF on line 90 terminates the statement. It indicates that execution of the following statements is not dependent on the outcome of the conditional expression on line 50, so these statements are executed as normal. Without the ENDIF the computer has no way of knowing whether or not the statements on line 100 belongs to the ELSE part.
There are certain rules which must be obeyed when using IF THEN [ELSE] ENDIF constructions:
IF condition THENwith THEN being the last item on the line.
10 DIM A%(10) 20 count% = 0 30 PRINT "Give me an integer between 0 and 9 "; 40 INPUT number% 50 IF number% >= 0 AND number% <= 9 THEN 60 IF A%(number%) = 0 THEN 70 PRINT "Thank you" 80 A%(number%) = 1 : count% = count% + 1 90 ELSE 100 PRINT "You've already had that number" 110 ENDIF 120 ELSE 130 PRINT number% " is not between 0 and 9 !" 140 ENDIF 150 IF count% < 10 GOTO 30
The FOR and NEXT statements are used to specify the number of times a block of a program is executed. These statements are placed so that they surround the block to be repeated:
10 FOR N% = 1 TO 6 20 PRINT N% 30 NEXT N%
Type RUN and the following is produced:
1 2 3 4 5 6
The variable N% is called the control variable. It is used to control the number of times the block of code is executed. The control variable can be started at any number you choose, and you may alter the step size; the amount by which it changes each time round the loop.
10 FOR N% = -5 TO 5 STEP 2 20 PRINT N% 30 NEXT N%
This program produces:
-5 -3 -1 1 3 5
The step size can be negative so that the control variable is decreased each time. It does not have to be an integer value. You can also use a decimal step size, although this is not generally advisable. The reason is that numbers such as 0.1 are not exactly representable in the internal format used by the computer. This means that when the step is added to the looping variable several times, small errors may accumulate. You can see this by typing the following program:
10 FOR i=0 TO 100 STEP 0.1 20 PRINT i 30 NEXT i
The looping variable i doesn't reach exactly 100.
FOR NEXT loops may be nested. For example,
10 FOR N = 3.0 TO -1.0 STEP -2.0 20 FOR M = 2.5 TO 2.9 STEP 0.2 30 PRINT N,M 40 NEXT M 50 NEXT N
produces:
3 2.5 3 2.7 3 2.9 1 2.5 1 2.7 1 2.9 -1 2.5 -1 2.7 -1 2.9
You do not need to specify the control variable to which NEXT refers. The following program produces the same results as the one above:
10 FOR N = 3.0 TO -1.0 STEP -2.0 20 FOR M = 2.5 TO 2.9 STEP 0.2 30 PRINT N,M 40 NEXT 50 NEXT
The program will now run slightly faster because the computer assumes that NEXT applies to the most recent FOR.
If you put variable names after NEXT you should not mix them up as shown below:
10 FOR N = 3.0 TO -1.0 STEP -2.0 20 FOR M = 2.5 TO 2.9 STEP 0.2 30 PRINT N,M 40 NEXT N 50 NEXT M
The output produced by this example is:
3.0 2.5 1.0 2.5 -1.0 2.5 Not in a FOR loop at line 50
Loops must be nested totally within each other: they must not cross. In the above example, the N and M loops are incorrectly nested. BASIC tries to run the program, but when line 50 is reached, it gives an error message indicating that it cannot match the FOR statements with the NEXT statements.
Note: The reason the error wasn't given sooner, i.e. as soon as the mismatched NEXT was met, was that it is actually legal, though not advisable, to close more than one loop with a single NEXT. When BASIC meets a NEXT var statement, it terminates all open FOR loops until it meets one which started FOR var. Thus the NEXT N in the example above closed the FOR M loop before performing the NEXT N.
A FOR loop is ended when the control variable is:
The loop is performed in the following sequence:
The initial and terminating values and the step size are calculated only once, at the start of the loop.
One of the consequences of the way in which the loop is performed is that the block of code is always executed at least once. Thus,
10 FOR N = 6 TO 0 20 PRINT N 30 NEXT
produces:
6
FOR NEXT loops are very versatile, since the initial and terminating values and the step size can be assigned any arithmetic expression containing variables or functions. For example:
10 REM Draw a sine curve 20 MODE 0 : MOVE 0,512 30 PRINT "Please give me a step size (eg 0.1) " 40 INPUT step 50 FOR angle = -2*PI TO 2*PI STEP step 60 DRAW 100*angle, 100*SIN(angle)+512 70 NEXT 80 END
The REPEAT UNTIL loop repeats a block of code until a given condition is fulfilled. For example:
10 REM Input a number in a given range 20 REPEAT 30 PRINT "Please give me a number between 0 and 9 " 40 INPUT N 50 UNTIL N >= 0 AND N <= 9 60 PRINT "Thank You"
If the result of the conditional expression following the UNTIL is TRUE, then the loop is ended and the statement following the UNTIL is executed. If, however, the result of the expression is FALSE, the block of code after the REPEAT is executed again and the conditional expression is re-evaluated.
REPEAT UNTIL LOOPS MAY BE NESTED IN THE SAME WAY AS FOR NEXT loops. They are also similar to FOR loops in that the body of the loop is always executed once, since no test is performed until the end of the loop is reached.
10 REM Repeat questions until answered right first time 20 REPEAT 30 tries% = 0 40 REPEAT 50 PRINT "What is 20 * 23 + 14 * 11 "; 60 INPUT ans% 70 tries% += 1 80 UNTIL ans% = 20 * 23 + 14 * 11 90 REPEAT 100 PRINT "What is 12 + 23 * 14 + 6 / 3 "; 110 INPUT ans% 120 tries% += 1 130 UNTIL ans% = 12 + 23 * 14 + 6 / 3 140 UNTIL tries% = 2;
The WHILE ENDWHILE loop repeats a block of code while a given condition holds true. For example:
10 X = 0 20 WHILE X < 100 30 PRINT X 40 X += RND(5) 50 ENDWHILE
The WHILE ENDWHILE LOOP HAS A CONDITIONAL EXPRESSION AT THE START OF IT. IF THIS EXPRESSION RETURNS TRUE_ THE BLOCK OF STATEMENTS FOLLOWING THE WHILE_ DOWN TO THE MATCHING ENDWHILE STATEMENT_ IS EXECUTED. THIS IS REPEATED UNTIL THE EXPRESSION RETURNS FALSE_ IN WHICH CASE EXECUTION JUMPS TO THE STATEMENT FOLLOWING THE MATCHING ENDWHILE. WE SAY 'MATCHING' ENDWHILE BECAUSE WHILE LOOPS MAY BE NESTED. THIS MEANS THAT WHEN BASIC IS LOOKING FOR AN ENDWHILE TO TERMINATE A LOOP_ IT MIGHT SKIP NESTED WHILE ENDWHILE loops.
Here is an example of nested WHILE loops:
10 A%=256 20 WHILE A%<>0 30 B%=1 40 WHILE B%<8 50 PRINT A%,B% 60 B%=B%*2 70 ENDWHILE 80 A%=A% DIV 2 90 ENDWHILE
WHILE ENDWHILE IS SIMILAR TO REPEAT UNTIL EXCEPT THAT THE CONDITIONAL EXPRESSION IS EVALUATED AT THE BEGINNING OF THE LOOP (SO THE BODY OF THE LOOP MAY NEVER BE EXECUTED IF THE CONDITION IS INITIALLY FALSE) AND THE LOOP REPEATS IF THE RESULT IS TRUE. THE FOLLOWING PROGRAM DEMONSTRATES THE FACT THAT REPEAT UNTIL LOOPS ARE ALWAYS EXECUTED AT LEAST ONCE_ WHEREAS THE WHILE ENDWHILE loops need not be executed at all.
10 REPEAT 20 PRINT "Repeat" 30 UNTIL TRUE 40 50 WHILE FALSE 60 PRINT "While" 70 ENDWHILE 80 90 PRINT "All done"
This program produces the following output:
Repeat All done
The IF THEN ELSE ENDIF CONSTRUCT IS USEFUL IF YOU WISH TO MAKE A CHOICE BETWEEN TWO ALTERNATIVES. THE CASE statement can be used when there are many alternatives to be acted upon in different ways.
The following program is a keyboard-controlled sketch pad. The statements after the WHENs alter the values of X% and Y%, and then DRAW a line.
10 REM Draw a line depending on the L,R,U,D keys 20 MODE 0 30 MOVE 640,512 40 X% = 640: Y% = 512 50 REPEAT 60 CASE GET$ OF 70 WHEN "L","l": X% -= 40: DRAW X%,Y% :REM go left 80 WHEN "R","r": X% += 40: DRAW X%,Y% :REM go right 90 WHEN "D","d": Y% -= 40: DRAW X%,Y% :REM go down 100 WHEN "U","u": Y% += 40: DRAW X%,Y% :REM go up 110 ENDCASE 120 UNTIL FALSE : REM go on forever ...
This program reads in the character of the next key pressed and checks it against each of the strings following the WHEN statements. If it matches one of these values, the statements following it are executed. Execution continues until another WHEN or the ENDCASE is reached. When this happens, control passes to the statement after the ENDCASE.
If you press a key which is not recognised by any of the four WHEN statements, the program goes round again and waits for another key to be pressed. You can include another line to warn you that you pressed the wrong key. For example:
105 OTHERWISE VDU 7 : REM Make a short noise
The OTHERWISE statement is used if none of the WHENs finds a matching key. The VDU 7 makes a short bell sound to warn you that you have pressed the wrong key.
The following rules apply to CASE statements:
Whenever the result of the expression matches one of the values listed after a WHEN, all the statements following this WHEN down to the next WHEN, OTHERWISE or ENDCASE are executed. BASIC then skips to the statement following the ENDCASE. This means that if the result matches a value in more than one WHEN, only the statements following the first one are executed: the others are ignored. Since OTHERWISE matches any value, having WHEN statements following an OTHERWISE is pointless since they can never be reached.
The following gives another example of using the CASE statement:
10 REM Guess a number 20 X% = RND(100) 30 Still_guessing% = TRUE 40 tries% = 0 50 WHILE Still_guessing% 60 INPUT "What is your guess ",guess% 70 CASE guess% OF 80 WHEN X% 90 PRINT "Well done, you've guessed it after ";tries% " attempts" 100 Still_guessing% = FALSE 110 WHEN X%-1,X%+1 120 PRINT "Very close" 130 tries% += 1 140 OTHERWISE 150 IF guess%<X% THEN PRINT "Too low" ELSE PRINT "Too high" 160 tries% += 1 170 ENDCASE 180 ENDWHILE
Like all the other BASIC structures, CASE statements may be nested.
The GOTO instruction may be used to specify a line number from which the computer is to continue executing the program. For example:
10 PRINT "Hello" 20 GOTO 10
Whenever the computer executes line 20 it is sent back to line 10 once again. Left on its own, this program never ends. To stop it, press Esc.
GOTO instructions send the control of the program either forwards or backwards. The specified line number may be given as an expression. For example:
10 start% = 100 20 GOTO (start%+10) 30 PRINT "This line should not be executed" 100 REM start of the action 110 PRINT "Hello" 120 END
Using a variable, however, as the destination for a GOTO is not recommended because while RENUMBER changes the line numbers, it does not alter GOTO destinations that are given as anything other than a simple number. If you must use an expression, it is best to put in inside brackets, since BASIC may get confused if the expression starts with a number.
If you wish to make your programs easy to read, especially for other people, use as few GOTOs as possible. They make a program very difficult to follow. It is far better to use one of the loop constructs like REPEAT UNTIL which have been described above.
GOSUB stands for 'go to subroutine' and is another variation of GOTO. Instead of continuing indefinitely from the line number which is jumped to, the lines are executed until a RETURN statement is reached. Control then passes back to the instruction which comes after the GOSUB. For example,
10 GOSUB 100 20 PRINT "This is printed after the first GOSUB returns" 30 GOSUB 100 40 PRINT "This is printed after the second GOSUB returns" 50 END 100 PRINT "This is printed in the GOSUB" 110 RETURN
produces:
This is printed in the GOSUB This is printed after the first GOSUB returns This is printed in the GOSUB This is printed after the second GOSUB returns
Like GOTO, GOSUB should be used sparingly, if at all. It is provided in this version of BASIC for compatibility with weaker dialects of the language. Better methods of providing blocks of code, which once executed then return control back to the point from which they were called are described in the Procedures and functions chapter.
The ON GOTO statement is used to choose one of a number of different lines depending on the value of a given expression. For example:
10 PRINT "Input a number between 1 and 4" 20 INPUT N% 30 ON N% GOTO 60, 100, 80, 120 60 PRINT "Your number is 1" 70 GOTO 999 80 PRINT "Your number is 3" 90 GOTO 999 100 PRINT "Your number is 2" 110 GOTO 999 120 PRINT "Your number is 4" 999 END
The computer checks the value of N% which is input, then jumps to the N%th line number in the list. If N% is 3, the computer starts executing at line 80 and so on. If N% is less than 1 or greater than 4, the error message
ON range at line 30
is displayed.
ELSE can be used to catch all other values. It is followed by a statement which is executed if the value of the expression after ON has no corresponding line number. For example, line 30 above could be replaced by:
30 ON N% GOTO 60,100,80,120 ELSE PRINT "Number out of range" 40 GOTO 999
Now, when the program is run, if N% is not between 1 and 4 the message Number out of range is displayed and the program ends normally.
ON GOSUB acts in exactly the same way:
10 PRINT "Input a number between 1 and 4" 20 INPUT N% 30 ON N% GOSUB 60, 100, 80, 120 40 END 60 PRINT "Your number is 1" 70 RETURN 80 PRINT "Your number is 3" 90 RETURN 100 PRINT "Your number is 2" 110 RETURN 120 PRINT "Your number is 4" 130 RETURN
There is also an ON PROC STATEMENT WHICH IS DESCRIBED IN THE Procedures and Functions chapter. Note, however, that when writing new programs, it is better to use the more versatile CASE structures rather than the ON GOTO/GOSUB/PROC constructs. Again, this old-fashioned construct is provided mainly for backwards compatibility with less powerful versions of BASIC.