Liberty Basic is develeopped by Carl Gundel
Original Newsletter compiled by Alyce Watson and Brosco
Translation to HTML: Raymond Roumeas

The Liberty Basic Newsletter - Issue #38 - MAY 99

"Knowledge is a gift we receive from others." - Michael T. Rankin

In This Issue:

For-Next Loops: Dos and Don'ts by Tom and Alyce Watson


For-Next Loops are an incredibly useful programming tool. They also afford us multiple ways to add bugs to our code! Let's have a look!

LB Syntax:

FOR counter = minimum to maximum (STEP increment)
'do some operation
NEXT counter

Let us use ( i ) as our counter variable, and fill in some numbers:

FOR i = 1 to 10 STEP 1
PRINT STR$(i)
NEXT i

The printout for that procedure looks like this:

1
2
3
4
5
6
7
8
9
10

STEP is optional if it is to have a value of ( 1 ), so the code below would have produced exactly the same results (notice that no STEP is specified) :

FOR i = 1 to 10
PRINT STR$(i)
NEXT i


WATCH OUT!

Here is a mistake that is easily made. Can you spot it?

FOR i = 1 to 10
PRINT STR$(i)
NEXT j

(Should be NEXT i !)

Unfortunately, this one will work just fine in Liberty BASIC! It is unfortunate, because it is sloppy and incorrect and could cause your program to malfunction. The error will not be trapped at runtime and will be difficult to find on debugging, since the TRACE window of the debugger will print the following:

i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10

USING THE COUNTER VARIABLE WITHIN THE PROCEDURE AND NESTED LOOPS

Do make use of the counter variable, when appropriate! It can easily function as a parameter in the code routine that is contained within the loop. Here is a VERY simple example:

FOR i = 1 to 10
FOR k = 1 to i
PRINT STR$(i);
NEXT k
NEXT i

This example shows a NESTED LOOP. For ease of reading the code, always indent to separate the different loops from one another. This particular sample requests that the counter variable ( i ) be printed as many times as its value indicates! Notice that ( i ) is used to count from one to 10, but it is also used as the maximum value for ( k ) in the interior loop! So the number ( 1 ) would be printed once, the number ( 5 ) would be printed five times, etc. And indeed, that is what happens when the code is run. Here is the printout:

12233344445555566666677777778888888899999999910101010101010101010

AHA - you may be wondering WHY the first printout placed the numbers each on a separate line, while the second printout placed them all on one line. The semi-colon is the culprit here.

Notice that one PRINT command ends in a semi-colon and does NOT force a carriage return into the printout each time. The code that does NOT have a semi-colon after the PRINT command DOES force a carriage return each time.

A NESTING CAVEAT

This example is coded properly:

FOR i = 1 to 10
FOR k = 1 to i
PRINT STR$(i);
NEXT k
NEXT i

But this one is not:

 
FOR i = 1 to 10
FOR k = 1 to i
PRINT STR$(i);
NEXT i
NEXT k
 

Both forms will give the same results, but in the second example, the counter variable is not properly nested. The loop that uses k as a counter variable should appear completely within the loop that uses i as a counter variable as it does in the first example.

This error is not trapped by Liberty BASIC, so you should be careful to write it properly and avoid possible problems in the running of your program.

ANOTHER WAY TO USE THE COUNTER VARIABLE WITHIN THE ROUTINE

AND

USING THE *STEP* FUNCTION

In the next example, we'll count in increments of 30, so the code includes the phrase STEP = 30. We will also use the counter variable to place graphics on the window. Cut and paste the code to see the angled line of four circles in a graphics window:

OPEN "Circles" for graphics as #g
PRINT #g, "down";
 
FOR i = 20 TO 110 STEP 30
PRINT #g, "place " ;2*i; " " + STR$(i)
PRINT #g, "circle 10"
NEXT i
 
INPUT A$

Note also that we needn't start counting in the loop with either 0 or 1. This time, we began the count at 20. Another little goodie is the way variables are placed within the graphics commands. Variables MUST appear outside of the quotation marks. They may be numeric variables, in which case they should be enclosed within semi-colons. They may also be string variables, in which case they must be concatenated with the ( + ) plus sign character, just as any strings would be concatenated. If you plan to use variables as part of commands, be very sure that you include the proper blank spaces within the quotation marks of your commands. The following would

NOT WORK!! (There should be a blank space between the word *place* and the quotation mark.)

PRINT #g, "place" ;2*i; " " + STR$(i)

 

COUNTING BACKWARDS !

When the value for STEP is positive, we say that we are INCREMENTING the counter variable. When the value for STEP is negative, we say that we are DECREMENTING it. The next routine will produce exactly the same results as the previous code, but this time we are counting backwards from 110 to 20 by a DECREMENT of -30 each time:

OPEN "Circles" for graphics as #g
PRINT #g, "down";
 
FOR i = 110 TO 20 STEP -30
PRINT #g, "place " ;2*i; " " + STR$(i)
PRINT #g, "circle 10"
NEXT i
 
INPUT A$
 

COUNTING BY DECIMALS

We aren't limited to integer values for our counter variable. Since the counter variable is often used in the code that is executed within the FOR-NEXT LOOP, it might be necessary to use decimal values - and we can! Here is an example:

FOR i = 0 TO 1 STEP .08
PRINT STR$(i)
NEXT i

The printout in the mainwindow:

0
0.08
0.16
0.24
0.32
0.4
0.48
0.56
0.64
0.72
0.8
0.88
0.96
 

DON'T EXIT A FOR-NEXT LOOP !

Try this little sample and see what it does:

FOR i = 1 to 20
PRINT STR$(i)
goto [oops]
NEXT i
 
[loop]
INPUT A$
 
[oops]
NOTICE "OOPs!"
GOTO [loop]

In the mainwindow, you will see the number ( 1 ) printed, but none of the other 20 numbers will print. Why not??? We have coded it as: FOR i = 1 to 20 so shouldn't we get all 20 of our numbers? It is fairly obvious what has happened. After printing the first value of ( i ) in the mainwindow, the program has exited the loop and gone to the branchlabel [oops]. That IS an OOOPS! Probably there is nobody who would write a routine with such an obvious flaw, but this very flaw can hide within our code, making the program malfunction and causing us great headaches!

This premature exit problem often creeps in when we add conditional statements within our FOR-NEXT LOOPS.

Here is an example that is similar to the previous one, but it adds a condition: IF i>10 THEN [oops] to the routine:

FOR i = 1 to 20
PRINT STR$(i) + " ";
IF i>10 THEN [oops]
NEXT i
 
[loop]
INPUT A$
 
[oops]
NOTICE "OOPs!"
GOTO [loop]

 

For a while, this routine functions as we intend it to - printing our numbers in the main window:

1 2 3 4 5 6 7 8 9 10 11 ?

It stops at 11, because when the counter variable gets to 11, the conditional expression then evaluates to TRUE and the program exits the loop and goes to the branchlable [oops]

 There is a way to continue execution of a program at another branchlabel while using a FOR-NEXT LOOP. Actually, there are TWO ways.

 

USE GOSUB INSTEAD OF GOTO FROM WITHIN A FOR-NEXT LOOP

Use a GOSUB command from within a FOR-NEXT LOOP, and the program execution returns to the exact spot where the GOSUB was issued, so the program functions properly. In the following example, all 20 numbers will print, but since numbers above 11 will cause the conditional statement to evaluate to TRUE, the program goes to the subroutine called [oops] for each of the higher numbers.

FOR i = 1 to 20
PRINT STR$(i) + " ";
IF i>10 THEN GOSUB[oops]
NEXT i
 
[loop]
INPUT A$
 
[oops]
NOTICE "OOPs!"
RETURN

The printout in the mainwindow:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ?

 

SET A FLAG WITHIN THE FOR-NEXT LOOP

You may also choose to set a flag within the FOR-NEXT LOOP that will indicate what the program should do AFTER exiting the loop. In the next sample, we have a FLAG variable that we are calling *toomuch* If the counter variable gets too high, the flag is set, else it remains with a value of 0.

When we have finished the FOR-NEXT LOOP, we then check the value of *toomuch* If it has a value greater than 0, then the program proceeds to a branchlabel where that is handled. In this case, we give ourselves a notice and print a warning into the mainwindow.

FOR i = 1 to 20
PRINT STR$(i) + " ";
IF i>10 THEN toomuch=toomuch+1
NEXT i
 
IF toomuch>0 THEN [oops]
[loop]
INPUT A$
 
[oops]
NOTICE "OOPs!"
PRINT
PRINT "Some numbers are TOO high!"
GOTO [loop]

Here is the printout in the mainwindow:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Some numbers are TOO high!
?

WHILE/WEND WITHIN A FOR-NEXT LOOP

Just as you can put conditional statements within a FOR-NEXT LOOP, you can also put in WHILE/WEND loops. Here is an example that will create a 5 second delay in a program, by putting a WHILE/WEND within a FOR-NEXT LOOP:

FOR i = 1 TO 5
T$=TIME$()
WHILE T$ = TIME$()
WEND
NEXT i

 

Each time through the loop, the program waits WHILE TIME$() remains at the value it had when T$ was set to TIME$().

When TIME$() is no longer equal to T$, the program moves on to the next increment of the counter, i.

Since it waits for one second to pass in each loop, and there are five loops, this creates a 5 second delay.

 

FILLING ARRAYS

In some cases, a FOR-NEXT LOOP is the fastest and easiest way to fill an array. One application is in game programming. As an example, let us say that enemy ships are in an array called enemy(25,3) and that the element enemy(i,2) contains the number of missiles each enemy ship owns. This element will be decremented by 1 each time an enemy ship fires, but it must start out with a value of 10. At the start of the game, you must assign the value 10 to each enemy's second array element. Here is one way:

enemy(1,2)=10
enemy(2,2)=10
enemy(3,2)=10
enemy(4,2)=10
enemy(5,2)=10
enemy(6,2)=10
enemy(7,2)=10
enemy(8,2)=10
enemy(9,2)=10
enemy(10,2)=10
enemy(11,2)=10
enemy(12,2)=10
enemy(13,2)=10
enemy(14,2)=10
enemy(15,2)=10
enemy(16,2)=10
enemy(17,2)=10
enemy(18,2)=10
enemy(19,2)=10
enemy(20,2)=10
enemy(21,2)=10
enemy(22,2)=10
enemy(23,2)=10
enemy(24,2)=10
enemy(25,2)=10

Whew! as you can see, that would take 25 assignments - a LOT of code! And that same procedure would need to be performed for all elements in all arrays. That could get boring pretty fast, and could also be a good place for bugs to creep in. Here it is in a FOR-NEXT LOOP - much tighter code, with less chance of bugs and typos:

FOR i = 1 TO 25
enemy(i,2)=10
NEXT i

DON'T CHANGE THE VALUE OF THE COUNTER VARIABLE!

The counter variable is often used as a parameter in the code routine(s) contained within the FOR-NEXT LOOP. For this reason, care must be taken to preserve the value of the counter variable. In other words, make sure you don't change the value! Here is a small sample that includes an obvious value change for the counter variable. It is unlikely that any of us would make such an obvious, simple mistake, but it might sneak into a more complex routine, so take care!

FOR i = 1 TO 30
PRINT STR$(i)
i = 2*i
NEXT i

And here is the printout in the mainwindow:

1
3
7
15

Ooops!

 

IT WAS ALL RIGHT THERE IN THE HELPFILE!

Just in case you are wondering how the editors of this little publication got so smart, we will tell you our secret..... WE READ THE HELPFILE!

For those of you who don't like looking it up, here is the concise and clear entry from LB's own helpfile on FOR-NEXT LOOPS:

 

FOR...NEXT

Description:

The FOR . . . NEXT looping construct provides a way to execute code a specific amount of times. A starting and ending value are specified like so:

for var = 1 to 10
{BASIC code}
next var

In this case, the {BASIC code} is executed 10 times, with var being 1 the first time, 2 the second, and on through 10 the tenth time. Optionally (and usually) var is used in some calculation(s) in the {BASIC code}. For example if the {BASIC code} is print var ^ 2, then a list of squares for var will be displayed upon execution.

The specified range could just as easily be 2 TO 20, instead of 1 TO 10, but since the loop always counts +1 at a time, the first number must be less than the second. The way around this limitation is to place STEP n at the end of for FOR statement like so:

for index = 20 to 2 step -1
{BASIC code}
next index

This would loop 19 times returning values for index that start with 20 and end with 2. STEP can be used with both positive and and negative numbers and it is not limited to integer values. For example:

for x = 0 to 1 step .01
print "The sine of "; x; " is "; sin(x)
next x

NOTE: It is not recommended to pass control of a program out of a FOR . . . NEXT loop using GOTO (GOSUB is acceptable). Liberty BASIC may behave unpredictably. For example:

for index = 1 to 10
print "Enter Customer # "; index
input customer$
if customer$ = "" then [quitEntry]'<- don't cut out of a for ... next
loop like this
 
cust$(index) = customer$
next index
[quitEntry]

 

. . . is not allowed! Rather use while ... wend:

 
index = 1
while customer$ <> "" and index <= 10
print "Enter Customer # "; index
input customer$
cust$(index) = customer$
index = index + 1
wend

 

THANKS, CARL GUNDEL!


Newsletter compiled and edited by: Brosco and Alyce.

Comments, requests or corrections: Hit 'REPLY' now!

mailto:brosc-@orac.net.au

or

mailto:awatso-@mail.wctc.net