Control Structures

From BR Wiki
Revision as of 16:15, 9 February 2012 by Mikhail.zheleznov (talk | contribs)
Jump to navigation Jump to search

Introduction

Normally, statements in an application are executed one after the other in the order in which they’re written. This process is called sequential execution.

Various BR statements enable you to specify that the next statement to execute is not necessarily the next one in sequence—this is called transfer of control.

All applications can be written in terms of only three control structures:

  1. the sequence structure,
  2. the selection structure, and
  3. the repetition structure.

GOTO Statement

The GoTo statement transfers program control to a specified line number or label.

The GOTO statement not be executed from the command line. Error 1011 (Illegal immediate statement) will occur if such usage is attempted. Instead try go line number.

Syntax

GOTO <line ref>

Comments and Examples

In the following example, line 320 transfers control to line number 45:

00045 start: !
00050 let a = 1
00060 let a += 1
00320 GOTO 45

The above example could be rewritten to use a label instead of a line number to transfer control. In the next example, where the GOTO points to a line label, control is transferred to the first executable statement after the label:

00045 start: !
00050 let a = 1
00060 let a += 1
00320 GOTO start

Parameters

GOTO has one required parameter: the Line=ref can be either a line number or label. This is the line number or label that program control is to be transferred to.

Technical considerations

  1. See the ON GOTO statement for a method of branching to one of several lines depending on the value of a numeric expression.


IF Statement

The If statement evaluates a relational expression. If the expression is true, it follows the THEN path and executes one or more specified statements or transfers control to another line, as indicated in the instructions. If it is false, it follows the ELSE path, which may specify another statement, transfer control to another line, or initiate another IF statement.

For example, suppose that the passing grade on an exam is 60. The BR statement below determines whether the condition grade >= 60 is true or false. If the condition is true, "Passed" is displayed, and the next BR statement in order is performed. If the condition is false, the output statement is ignored, and the next BR statement in order is performed.

00010 print "Enter a grade"
00020 input grade
00030 if grade >= 60 then print "Passed"
00040 stop

Syntax

IF [NOT] <conditional expression> [{AND|OR}...] THEN [<statement>][ ELSE <statement>]

Multi-line IF Statements

The same program could be rewritten to put the print "Passed" statement on a separate line with indentation to emphasize that this statement may or may not happen:

00010 print "Enter a grade"
00020 input grade
00030 if grade >= 60 then 
00040    print "Passed"
00050 end if
00060 stop

In the above example, end if marks the end of the statements which will be performed if the grade >= 60 condition is true. The indentation of line 40 of this selection statement is optional, but recommended, because it emphasizes the inherent structure of the if statement.

Below is the general syntax used in a multi-line if statement:

IF condition THEN
   [body]
END IF

The optional body between IF condition THEN and END IF is a group of zero or more statements. At least one statement in the body is encouraged for clarity.

Although it is not required to indent the body of a multi-line IF statement, it is highly recommended to indent it for readability.

Programmers often run into situations in which more than one statement needs to be executed if a particular condition is true. To illustrate the method of achieving this in BR, we will expand the above example to print multiple statements if the grade entered by the user is more than or equal to 60:

00010 print "Enter a grade"
00020 input grade
00030 if grade >= 60 then 
00040    print "Passed"
00050    print "You will not need to re-take the test" 
00060    print "Good job"
00070 end if
00080 stop

IF... ELSE Statement

When your programming needs call for two different actions depending on whether or not a condition is true, the IF... ELSE statement should be used.

00010 print "Enter a grade"
00020 input grade
00030 if grade >= 60 then 
00040    print "Passed"
00050 else
00060    print "Failed"
00070 end if
00080 stop

IF... ELSE IF Statement

When your programming needs call for many different actions depending on multiple conditions, the IF... ELSE IF statement should be used.

00010 print "Enter a grade"
00020 input grade
00030 if grade >= 90 AND grade <= 100 then 
00040    print "Got an A"
00050 else if grade >= 80 AND grade <= 89 then 
00060    print "Got a B"
00070 else if grade >= 70 AND grade <= 79 then 
00080    print "Got a C"
00090 else if grade >= 60 AND grade <= 69 then
00100    print "Got a D"
00110 else if grade < 60 AND grade > 0 then
00120    print "Failed"
00130 end if
00140 stop

IF... ELSE IF... ELSE Statement

The program above covers all scenarios except two:

1. When the grade entered by the user is negative 2. When the grade entered by the user is greater than 100

In order to catch this problem, you may add an ELSE clause to the end of the program above, resulting in:

00010 print "Enter a grade"
00020 input grade
00030 if grade >= 90 AND grade <= 100 then 
00040    print "Got an A"
00050 else if grade >= 80 AND grade <= 89 then 
00060    print "Got a B"
00070 else if grade >= 70 AND grade <= 79 then 
00080    print "Got a C"
00090 else if grade >= 60 AND grade <= 69 then
00100    print "Got a D"
00110 else if grade < 60 AND grade > 0 then
00120    print "Failed"
00130 else
00140    print "Invalid grade. Must be positive and less than 100"
00150 end if
00160 stop

Complex Conditions

Often in programs, the execution of a statement depends on several different conditions. For example, you may want REQUIRE the user to enter a name, a date of birth, and a social security number before saving a record.

00010 dim name$*40, dob$*8, ssn$*9
00020 get_data:!
00030 input name$, dob$, ssn$
00040 if trim$(name$)="" or trim$(dob$)="" or trim$(ssn$)="" then
00050    print "Enter ALL THREE fields before saving"
00060    goto get_data$
00070 end if

To see more information on operations see Operations.

Nested if statements

Sometimes you may need to embed if statements into other if statements. These embedded if statements are formerly known as nested if statements. Below is an example:

00020    PRINT "Enter employee type"
00030    PRINT "1 - Manager"
00040    PRINT "2 - Hourly"
00050    PRINT "3 - Commission"
00060    INPUT PAYCODE
00070    IF PAYCODE = 1 THEN ! Manager
00080       PRINT "Manager Selected."
00090       PRINT "Enter Weekly Salary "
00100       INPUT SALARY
00110       if salary => 0 then
00120          PRINT "Manager's pay is " & STR$(SALARY)
00130       else
00140          print "Can't have a negative salary"
00150       end if
00160    ELSE IF PAYCODE = 2 THEN ! Hourly Worker
00170       PRINT "Hourly worker Selected."
00180       PRINT "Enter the hourly salary "
00190       INPUT WAGE
00200       PRINT "Enter the total hours worked "
00210       INPUT HOURS
00220       if hours < 0 then
00230          print "Can't have negative hours"
00240       else if HOURS <= 40 THEN
00250          LET SALARY = HOURS * WAGE
00260       ELSE
00270          LET SALARY = 40.0 * WAGE + ( HOURS - 40 ) * WAGE * 1.5
00280       END IF
00290       PRINT "Hourly worker's pay is " & STR$(SALARY)
00300    ELSE IF PAYCODE = 3 THEN ! Commission Worker
00310       PRINT "Commission Worker Selected."
00320       PRINT "Enter gross weekly sales "
00330       INPUT SALES
00340       if sales > 0 then
00350          LET SALARY = SALES * .057 + 250
00360          PRINT "Commission worker's pay is " & STR$(SALARY)
00370       else
00380          print "Can't have negative sales"
00390       end if
00400    END IF

If there are several levels of indentation, each level should be indented the same additional amount of space.


DO LOOP Repetition Statement

See also DO and Exit Do.

DO [WHILE|UNTIL condition1]
   [loop body]
   [exit do]
LOOP [WHILE|UNTIL condition2]

A DO LOOP allows you to specify that an application should repeat a statement or set of statements while some condition1 remains true and/or until another condition2 becomes true.

In the above syntax, condition1, condition2, the loop body, and the exit do statement are optional, but the use of at least one of them is encouraged for clarity.

The loop body may consist of zero or more statements. However, the use of at least one statement in the loop body is encouraged for clarity.

Eventually, the condition(s) should become false. At this point, the repetition terminates, and the first statement after the DO LOOP executes.

The DO LOOP stops execution in 3 cases:

  1. The condition following the WHILE keyword becomes FALSE
  2. The condition following the UNTIL keyword becomes TRUE
  3. An EXIT DO statement is encountered

Although it is not required to indent the body of a DO LOOP, it is highly recommended to indent it for readability.

Syntax

DO {WHILE|UNTIL}  <conditional expression>
{<statement>} 
[EXIT DO] 
LOOP

Examples

For example, the loop below will print 3, then double the 3 to 6 and print it, then double the 6 to 12 and print it, and so on until the variable becomes greater than 100. At this point the repetition stops.

00010 let a=3
00020 do until a > 100
00030    print a
00040    let a = 2 * a
00050 loop

You can reach an identical result by using WHILE and reversing the condition from a > 100 to a <= 100:

00010 let a=3
00020 do while a <= 100
00030    print a
00040    let a = 2 * a
00050 loop

You may want to combine the use of both WHILE and UNTIL in the same DO LOOP:

00010 do while fkey <> 99                  ! loop will stop if user presses ESC
00020    let kstat$(1)
00030    print "FKEY is now "&str$(FKEY)
00040 loop until fkey = 12                 ! loop will stop if user presses F12

Results identical to those from the above example may be obtained from the following DO LOOP:

00010 do while fkey <> 99 and fkey <> 12                 ! loop will stop if user presses ESC or F12
00020    let kstat$(1)
00030    print "FKEY is now "&str$(FKEY)
00040 loop

DO LOOP WHILE vs DO WHILE LOOP

There is a major difference in the effect of using DO LOOP WHILE vs DO WHILE LOOP:

DO LOOP WHILE always executes at least once regardless of condition

DO WHILE LOOP may not execute at all if the condition in the WHILE clause is false when the loop attempts to execute for the first time

For example, consider the difference between the following 2 programs:

00010 let a = 1
00020 do
00030    print a  ! prints once because while a < 0 is checked after the first loop execution
00040 loop while a < 0
00050 stop

VS

00010 let a = 1
00020 do while a < 0
00030    print a  ! doesn't print because while a < 0 is checked before the first loop execution
00040 loop 
00050 stop

EXIT DO

00010 do
00020    print 'This loop will stop when you press F1'
00030    let kstat$(1)
00040    if FKEY = 1 then EXIT DO
00050 loop

As you can see, the combination of WHILE, UNTIL, and EXIT DO allows for various combinations of DO LOOP conditions.

Common Errors

Not providing in the body of a DO LOOP an action that eventually causes the condition in the WHILE clause to become false or the condition in the UNTIL clause to become true normally results in a logic error called an infinite loop, in which the loop never terminates.

The following example will execute forever:

00010 let a = 100
00020 do
00030    print a
00040 loop while a > 0
00050 ! the program never gets here, because the value of a is 100, which is ALWAYS greater than 0
00060 stop

The program above appears to be stuck in RUN mode, until the user forcefully terminates the program using CTRL+A and the STOP command (or another command which stops program execution)

Below is what a corrected version of the above program might look like:

00010 let a = 100
00020 do
00030    print a
00040    let a -= 1
00050 loop while a > 0
00060 ! the program gets here after 100 executions of the while loop, 
00070 ! after which a is no longer greater than 0
00080 stop

Loop Performance

In loops, avoid calculations for which the result never changes—such calculations should typically be placed before the loop.



FOR NEXT Repetition Statement

FOR counter = initial_value to final_value [STEP step_value]
   [loop body]
NEXT counter

A FOR LOOP allows you to specify that an application should repeat a statement or set of statements until a counter reaches its final_value.

The loop body may consist of zero or more statements. However, the use of at least one statement in the loop body is encouraged for clarity.

The optional numeric step_value following the STEP keyword specifies by how much to increase or decrease the counter variable with each execution of the FOR LOOP. If the STEP keyword is absent and step_value isn't specified, then the default value of +1 is used. If step_value is negative, then the counter variable is decreased with each execution of the loop.

Although it is not required to indent the body of a FOR LOOP, it is highly recommended to indent it for readability.

Syntax

Examples

This example prints integers from 1 to 100:

00010 for counter = 1 to 100
00020    print counter
00030 next counter

The same effect may be achieved by this program:

00010 for counter = 1 to 100 step 1 ! this is redundant, since the default value of 1 is used anyway.
00020    print counter
00030 next counter

This program prints numbers from 100 to 1 in descending order:

00010 for counter = 100 to 1 step -1
00020    print counter
00030 next counter

This program prints EVEN numbers from 2 to 100 in ascending order:

00010 for counter = 2 to 100 step 2
00020    print counter
00030 next counter 

Best Practices

Although the value of the LOOP COUNTER VARIABLE can be changed in the body of a for loop, avoid doing so, because this practice can lead to subtle errors.

For example, it is impossible to tell how many times the following loop will execute, because the user may change the value of the loop counter each time the loop executes

00010 for i = 1 to 10
00020    print "Enter a value"
00030    input i
00040 next i

Loop Performance

In loops, avoid calculations for which the result never changes—such calculations should typically be placed before the loop.