Chapter 5 - Decision Structures

True BASIC carries out most statements in the order in which they appear in the source code. This means that most simple programs proceed from “top” to “bottom” when run. With this sort of “linear execution,” each state- ment is used once and only once.

However, many problems require more flexibility than strict linear execution allows. The best solutions may require that certain statements execute more than once or perhaps not at all under some circumstances.

True BASIC uses structures to achieve this flexibility. A structure is a specialized construct that allows the program to control which statements get executed and when. This chapter introduces decision structures — a structure that lets your program decide which statements to execute and which statements to ignore. Later chapters introduce other structures, including loops, defined functions, subroutines, pictures, and error handlers.

True BASIC has two different decision structures: the IF structure and the SELECT CASE structure. Both struc- tures let you “branch” to a specific set of statements and ignore others. Thus, you can write programs that proceed in different ways depending upon the value of logical expressions.

Logical Expressions
True BASIC allows you to compare the values of numeric and string expressions using logical expressions. A log- ical expression (sometimes called a Boolean expression) is an expression that can be evaluated as having either a true or false value. You form a logical expression by using a relational operator to compare two numerical expres- sions or two string expressions. The relational operators are:

Relational Operators
——————————————————————————————————————
Operator Meaning
= equal to
< less than
<= less than or equal to
> greater than
>= greater than or equal to
<> not equal to
——————————————————————————————————————
When you compare two expressions with a relational operator, the resulting logical expression is either true or false — either the relation holds or it doesn’t. For instance, two numeric values are either equal or not; there is no “maybe.”
When comparing numeric values, True BASIC uses standard mathematical conventions. When comparing string values, True BASIC uses the order of characters specified by the character set. (Since most operating systems use the ASCII character set, this manual assumes that set for all examples. For an ordered listing of the ASCII char- acter set, see Appendix A.)
The ASCII character set ranks all letters alphabetically, but all uppercase letters come before lowercase letters, so that “Z” is earlier in the alphabet than “a”. Most other characters, such as punctuation marks and digits, come before letters in the ASCII character set. (Exceptions include { | } ~ and the delete character.) A few examples should clarify these concepts:

Examples of Comparisons
——————————————————————————————————————
Expression Value
4 - 2 = 1 + 1 true
3.5 > 2^2 false
2.35 <= 2.35 true “Apple” < “Pear” true “apple” < “Pear” false
“tree”[3:4] < “grass” true
“123” > “abc” false
——————————————————————————————————————
More complex logical expressions, called compound conditions, may be built using the logical operators NOT, AND, and OR.

Logical Operators
————————————————–––——————————————————————
NOT reverses the value of the logical expression given as its operand. For instance, if the NOT operator is applied to an expression with a true value, the value of the resulting compound condition will
be false. Therefore,
(3+2 = 5) is true and
not (3+2 = 5 ) is false.

AND evaluates the logical expression on its left and the one on its right and returns a value of true only if both logical expressions are true.

OR evaluates the logical expression on its left and the one on its right and returns a value of false only if both logical expressions are false.
—————————————————–––—————————————————————
——————————————————–––—————————————————————
[ ! ] Note: True BASIC evaluates a compound condition from left to right but only as far as is necessary to
determine whether it is true. This process is known as short circuiting and is very useful in avoiding
errors. For example, the complex condition
b <> 0 and a/b > 10
is safe. That is, no error will result if b is 0 because a/b will not be evaluated: if the first expression in an AND condition is false then the entire expression must be false, so True BASIC stops evaluating the compound condition. Similarly, if the first expression in an OR condition is true then the entire expression must be true so True BASIC evaluates no further.
——————————————————–––—————————————————————
To illustrate the behavior of the logical operators consider how True BASIC would evaluate the following complex condition:
x < y or not(x-2 = z) and (a$ = “Yes” or b$ = “No”)

First, the complex condition would be broken down into the operands of the first OR operator as follows:
x < y
not(x-2 = z) and (a$ = “Yes” or b$ = “No”)
The expression x < y, as the left operand, would be evaluated first. If its value is true, then the value of the entire expression is true, and True BASIC stops evaluating. In such a case, the right operand is not even considered.

However, if the value of x < y is false, then the value of the complex condition
not(x-2 = z) and (a$ = “Yes” or b$ = “No”)
must be evaluated. To do so, this complex condition is broken down into the operands of the AND operator as follows:

not(x-2 = z)
(a$ = “Yes” or b$ = “No”)
Again the left operand is evaluated first. The left operand is the complex condition not(x-2 = z). This complex condition has only one operand, (x-2 = z), and the NOT operator serves to reverse the value of this expression. Thus, if the value of the expression (x-2 = z) is true, then the value of the complex condition not(x-2 = z) is false. If the first operand is false, then the AND condition must be false and the second operand is ignored.

However, if the first operand of the AND operator is true, then the second operand must be evaluated to determine the value of the AND condition. This operand consists of another complex condition which may be broken down as operands of the OR operator:
a$ = “Yes”
b$ = “No”
If the expression a$ = “Yes” is true, then the entire OR condition is true and the right operand is ignored. However, if the left operand is false, then the right operand must be evaluated to determine the value of the OR condition.

The value of the OR condition within the parentheses is then used to resolve the value of the AND condition. In turn, the value of the AND condition is used to resolve the value of the initial OR condition. This then provides the value of the original complex condition.

The IF Structure
Logical expressions are commonly used in the IF structure, which lets your program make decisions. Simple IF struc- tures choose between only two options, while more complex IF structures can select from several choices.

Single-branch IF Structures
The simplest form of the IF structure simply determines whether a particular block of statements will be exe- cuted. For example:

IF age >= 100 then
PRINT “Congratulations!” END IF
In this code segment, the “Congratulations!” message will be printed only when the value of age is greater than or equal to 100. The IF structure begins with an IF statement containing a logical expression and the keyword THEN. An END IF statement marks the end of the structure.

Because of its simplicity, this IF structure could also be written as the following single-line IF statement:
IF age >= 100 then PRINT “Congratulations!”
Single-line IF statements may have only one statement following THEN, and they have no END IF statement.

The IF structure is usually more flexible, however, since you can specify any number of statements to be executed if the logical expression is true. For example:
IF age >= 100 then
PRINT “Congratulations!” LET bonus = 10
END IF
Everything between the IF and END IF statements will be executed if the condition is true.

Two-branch IF Structures
A slightly more complicated form of the IF structure allows you to specify two different blocks of statements; one to be executed if the logical expression is true, and another to be executed if it is false.

For example, suppose you are playing a guessing game. The computer has picked a number and stored it in the variable n. Your guess is stored in the variable guess. You could then use the following IF structure to determine whether the guess is correct:

IF guess = n then
PRINT “Right” ELSE
PRINT “Wrong”
PRINT “It was “; n
END IF
This structure, like the earlier example, starts with an IF statement and ends with an END IF statement. Notice that the position of the ELSE statement defines two distinct blocks of statements; one for a correct answer, and another for an incorrect answer. If you guessed correctly, the logical expression is true so the program uses the first block to print the “Right” message and ignores the second block. If you were wrong, the logical expression is false and the program ignores the first block and uses the second to print “Wrong” and give you the correct answer. Thus, the program follows one of two different courses of action, depending on the values of the variables guess and n. The indentation used here, which helps to display the structure, is based on the style conventions discussed in Chapter 1 “A Word on Style.”

You may use the single-line form of the IF statement with a two-way decision as long as the THEN and ELSE key- words each have just one statement:
IF guess = n then PRINT “Right” else PRINT “Wrong”
Notice that again there is no END IF statement with a single-line IF statement. Single-line IF statements may have only one statement after the THEN keyword and one statement after the optional ELSE keyword. True BASIC interprets any IF statement with a statement following the THEN keyword on the same line as a single- line IF statement.

Multiple-branch IF Structures
You may use the ELSEIF statement to create more intricate branches. To illustrate a three-way branch, here is a short program for quadratic equations:
PRINT “Enter the three coefficients: “
INPUT a, b, c ! The coefficients LET discr = b^2 - 4*a*c ! The discriminant IF discr = 0 then ! One root
PRINT “The root is:” PRINT -b/(2*a)
ELSEIF discr > 0 then ! Two roots
LET s = Sqr(discr) ! Take square root
PRINT “The roots are:” PRINT (-b+s)/(2*a) PRINT (-b-s)/(2*a)
ELSE ! Complex roots
PRINT “No real roots” END IF
END
In this example, the IF structure defines three distinct blocks of statements. It is important to remember that, regardless of the number of blocks it contains, a single IF structure will execute one, and only one, of these blocks. Once a condition is satisfied, its associated block of statements is executed and the program continues with the line following the END IF statement; all other blocks in the IF structure are ignored.

You may use as many ELSEIF statements as necessary within an IF structure, but you may include only one ELSE statement (which should appear as the last option). Each ELSEIF statement must specify its own logical expression followed by the keyword THEN. As you have seen, each IF structure must begin with an IF statement (ending with the keyword THEN) and end with an END IF statement.

There is no form of the single-line IF statement that lets you include more than two possible actions. You must use a multi-line IF structure for three or more possible branches.

Nested IF Structures
The flexibility of the IF structure may be further enhanced by nesting — the process of defining one structure
within another. The inner structure is said to be “nested” within the outer structure. The nested structure must be completed before the containing structure can be completed.
Here is an example of nesting. First, note that the above three-way branch for quadratic equations did not check whether a is 0. You could solve that problem by expanding the original IF structure to a four-way branch beginning with a test for a = 0 and nesting another IF structure in that new first branch as shown below:
PRINT “Enter the three coefficients: “
INPUT a, b, c ! The coefficients
LET discr = b^2 - 4*a*c ! The discriminant

IF a = 0 then ! New test with nested structure
IF b = 0 and c = 0 then ! Begin nested structure
PRINT “Any number is a solution.” ELSEIF b = 0 then
PRINT “There is no solution.” ELSE
PRINT “The root is:” PRINT -c/b
END IF ! End nested structure

ELSEIF discr = 0 then ! (continue as above) PRINT “The root is:” ! One root
PRINT -b/(2*a)

ELSEIF discr > 0 then ! Two roots
LET s = Sqr(discr) ! Take square root
PRINT “The roots are:” PRINT (-b+s)/(2*a) PRINT (-b-s)/(2*a)

ELSE ! Complex roots
PRINT “No real roots” END IF

END

The SELECT CASE Structure
If all the choices in the decision structure are based on the value of a single numeric or string expression, it is often more convenient to use a SELECT CASE structure.

The formation of a SELECT CASE structure is similar to that of an IF structure. The SELECT CASE statement, which indicates the beginning of the structure, contains the expression to be evaluated. An END SELECT state- ment indicates the end of the structure. Within the structure, you may use as many CASE statements as neces- sary to define blocks of statements that will be executed for specific values of the specified expression. True BASIC evaluates the expression and then executes the block of statements indicated by the first appropriate CASE state- ment; any remaining blocks are ignored. For example:
SELECT CASE n
CASE 2 ! If the number is 2
PRINT “Even prime”
CASE 3, 5, 7 ! If the number is 3, 5, or 7
PRINT “Odd prime”
CASE 1, 4, 9 ! If the number is 1, 4, or 9
PRINT “Perfect square”
CASE else ! If anything else

PRINT “Composite, not a square:” END SELECT
When executing this segment of code, True BASIC determines the value of n and looks for the first CASE state- ment that specifies a matching value. When it encounters an appropriate CASE statement, it executes the block of statements immediately following that statement (up to the next CASE statement) and continues with the line following the END SELECT statement. If there is no CASE statement that specifically matches the value of n, then the block of statements following the CASE ELSE statement is executed. If there is no CASE ELSE state- ment, then an error occurs and the program stops.
The CASE ELSE statement is optional, but if used it must be the last case in the structure. Since a CASE state- ment is not required to have a block of statements associated with it, a program can “ignore” a particular case sim- ply by having no statements between that CASE and the next. Thus, you may wish to include an empty CASE ELSE block to avoid errors.
The CASE statements may specify only constant values; variables and expressions may be used only in the SELECT CASE statement. While the above example demonstrates the use of discrete constants in the CASE statements, you can build much more powerful SELECT CASE structures using ranges and relations on the CASE statements.
A range specifies a range of values for which the CASE statement holds true. To specify a range, use the keyword
TO with constants specifying the low and high ends of the range, as in:
CASE 10 TO 20
Ranges are inclusive. For instance, the above example would hold true for values of 10, 20, or any value greater than 10 and less than 20.

A relation specifies a relationship between the value of the expression specified in the SELECT CASE statement and a constant value for which the CASE statement holds true. To specify a relation, use the keyword IS followed by one of the relational operators and a constant value, as in:
CASE IS < 0
This CASE statement holds true for any SELECT CASE expression whose value is less than 0.

Consider the following example that demonstrates the use of ranges and relations with a string expression. This program counts characters of various types. It uses the facts that space is the first regular character and that con- trol characters (carriage returns, line feeds, etc.) come before regular characters in the ASCII character order.

LINE INPUT PROMPT “Enter a line of text: “: line$ FOR c = 1 to Len(line$)
SELECT CASE line$[c:c] ! Current character
CASE “0” to “9” ! If it is a digit
LET number = number + 1
CASE “A” to “Z” ! If it is uppercase
LET uc = uc + 1
CASE “a” to “z” ! If it is lowercase
LET lc = lc + 1
CASE is < “ “ ! If a control character
LET control = control + 1
CASE else
LET other = other + 1
END SELECT NEXT c
PRINT “The line contained:”; number; “numbers and”; uc + lc; PRINT “characters.”
PRINT “There were”; other + control; “other characters in the line.” END
Loop Structures