---------------------------------------------------------
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 couter 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:brosco@orac.net.au
                       or
           mailto:awatson@mail.wctc.net
---------------------------------------------------------