HP OpenVMS Systems Documentation
HP BASIC for OpenVMS
When a loop block is entirely contained in another loop block, it is called a nested loop.
The following example declares a two-dimensional array and uses nested FOR...NEXT loops to fill the array elements with sales information. The inner loop executes 16 times for each iteration of the outer loop. This example assigns a value to each of the 256 elements of the array.
DECLARE INTEGER Column_number, Row_number REAL Sales_info, Two_dim_array (15%, 15%) FOR Row_number = 0% TO 15% FOR Column_number = 0% to 15% INPUT "Please enter the sales information";Sales_info Two_dim_array (Row_number, Column_number) = Sales_info NEXT Column_number NEXT Row_number
Note that in nested loops the inner loop is entirely contained in the
outer loop; nested loops cannot overlap.
9.3 Unconditional Branching (GOTO Statement)
The GOTO statement specifies which program line the HP BASIC compiler is to execute next, regardless of that line's position in the program. If the statement at the target line number or label is nonexecutable (such as an REM statement), HP BASIC transfers control to the next executable statement following the target line number.
You can use a GOTO statement to exit from a loop; however, it is better
programming practice to use the EXIT statement.
9.4 Conditional Branching
Conditional branching is the transfer of program control only when specified conditions are met. There are three HP BASIC statements that let you conditionally transfer control to a target statement in your program:
The ON...GOTO...OTHERWISE statement tests the value specified after the ON keyword. If the value is 1, HP BASIC transfers control to the first target in the list; if the value is 2, control passes to the second target, and so on. If the value is less than 1 or greater than the number of targets in the list, HP BASIC transfers control to the target specified in the OTHERWISE clause. For example:
Menu: PRINT "Would you like to change:" PRINT "1. First name" PRINT "2. Last name" INPUT CHOICE% ON CHOICE% GOTO First_name, Last_name OTHERWISE Other_choice First_name: INPUT "First name"; firstname$ GOTO Done Last_name: INPUT "Last name"; lastname$ GOTO Done Other_choice: PRINT "Invalid choice" PRINT "Let's try again" GOTO Menu Done: END
Note that if you do not supply an OTHERWISE clause and the control
variable is less than 1 or greater than the number of targets,
BASIC signals "ON statement out of range (ERR = 58)".
9.4.2 IF...THEN...ELSE Statement
The IF...THEN...ELSE statement evaluates a conditional expression and uses the result to determine which block of statements to execute next. If the conditional expression is true, HP BASIC executes the statements in the THEN clause. If the conditional expression is false, HP BASIC executes the statements in the ELSE clause, if one is present. If the conditional expression is false and there is no ELSE clause, HP BASIC executes the statement immediately following the END IF statement.
In the following example, HP BASIC evaluates the conditional expression number < 0. If the input value of number is less than zero, the conditional expression is true. HP BASIC then executes the statements in the THEN clause, skips the statement in the ELSE clause, and transfers control to the statement following the END IF. If the value of number is greater than or equal to zero, the conditional expression is false. HP BASIC then skips the statements in the THEN clause and executes the statement in the ELSE clause.
INPUT "Input number"; number IF (number < 0) THEN number = - number PRINT "That square root is imaginary" PRINT "The square root of its absolute value is"; PRINT SQR(number) ELSE PRINT "The square root is"; SQR(number) END IF END
Input number? -9 That square root is imaginary The square root of its absolute value is 3
Do not neglect to end an IF...THEN...ELSE statement. After an IF block is executed, control is transferred to the statement immediately following the END IF. If there is no END IF, HP BASIC transfers control to the next line number. Code between the keyword ELSE and the next line number becomes part of the ELSE clause. If there are no line numbers, the HP BASIC compiler ignores the remaining program code from the keyword ELSE to the end of the program. Therefore, it is important to end IF statements.
IF...THEN...ELSE statements can be nested. In an inner nesting level, if an END IF is not present, the BASIC compiler treats the presence of an ELSE clause for an IF statement in an outer nesting level as an implicit END IF for all unterminated IF statements at that point. For example, in the following construction, the third ELSE terminates both inner IFs:
IF expression THEN IF expression THEN statement-list ELSE IF expression THEN statement-list ELSE statement-list ELSE
In the following example, the first IF...THEN...ELSE statement is ended by END IF, and works as expected. Because the second IF...THEN...ELSE statement is not terminated by END IF, the HP BASIC compiler assumes that the last PRINT statement in the program is part of the second ELSE clause.
10 DECLARE INTEGER light_bulb DECLARE INTEGER circuit_switch DECLARE INTEGER CONSTANT Opened = 0 DECLARE INTEGER CONSTANT Closed = 1 PRINT "Please enter zero or one, corresponding to the circuit" PRINT "switch being open or closed" INPUT On_off_val (1) IF On_off_val = Opened THEN PRINT "The light bulb is off." ELSE PRINT "The light bulb is on." END IF IF On_off_val = Closed THEN PRINT "The light bulb is on." ELSE PRINT "The light bulb is off." (2) PRINT "That's all for now." 20 END
Please enter zero or one, corresponding to the circuit switch being open or closed ? 0 The light bulb is off. The light bulb is off. That's all for now.
Please enter zero or one, corresponding to the circuit Switch being open or closed ? 1 The light bulb is on. The light bulb is on.
Note that a statement in a THEN or ELSE clause can be followed by a modifier. In this case, the modifying IF applies only to the statement that immediately precedes it.
IF A = B THEN PRINT A IF A = 3 ELSE PRINT B IF B > 0 END IF
The SELECT...CASE statement lets you specify an expression (the SELECT expression), any number of possible values (cases) for the SELECT expression, and a list of statements (a CASE block) for each case. The SELECT expression can be a numeric or string value. CASE values can be single or multiple values, one or more ranges of values, or relationships. When a match is found between the SELECT expression and a CASE value, the statements in the following CASE block are executed. Control is then transferred to the statement following the END SELECT statement.
In the following example, the CASE values appear to overlap; that is, the CASE value that tests for values greater than or equal to 0.5 also includes the values greater than or equal to 1.0. However, HP BASIC executes the statements associated with the first matching CASE statement and then transfers control to the statement following END SELECT. In this program, each range of values is tested before it overlaps in the next range. Because the compiler executes the first matching CASE statement, the overlapping values do not matter.
DECLARE REAL Stock_change INPUT "Please enter stock price change";Stock_change SELECT Stock_change CASE <= 0.5 PRINT "Don't sell yet." CASE <= 1.0 PRINT "Sell today." CASE ELSE PRINT "Sell NOW!" END SELECT END
Please enter stock price change? 2.1 Sell NOW!
If no match is found for any of the specified cases and there is no CASE ELSE block, HP BASIC transfers control to the statement following END SELECT without executing any of the statements in the SELECT block.
SELECT...CASE lets you use run-time expressions for both SELECT expressions and CASE values. The following example uses HP BASIC built-in string functions to examine command input:
! This program is a skeleton command processor. ! It recognizes three VAX BASIC Environment commands: ! ! SAVE ! SCRATCH ! OLD DECLARE INTEGER CONSTANT True = -1 DECLARE INTEGER CONSTANT False = 0 DECLARE STRING CONSTANT Null_input = "" !This is the null string. DECLARE STRING Command ! Main program logic starts here. Command_loop: WHILE True ! This loop executes until the user types only a ! carriage return in response to the prompt. PRINT PRINT "Please enter a command (uppercase only)." PRINT "Type a carriage return when finished." INPUT Command PRINT SELECT Command CASE Null_input ! If user types RETURN, ! exit from the loop GOTO Done ! and end the program. ! The next three cases use the SEG$ and LEN string functions. ! LEN returns the length of the typed string, and SEG$ searches ! the string literals ("SAVE", "SCRATCH", and "OLD") for a ! match up to that length. Note that if the user types an "S", ! it is interpreted as a SAVE command only because SAVE is the ! first case tested. CASE SEG$ ( "SAVE", 1%, LEN (Command) ) PRINT "That was a SAVE command." CASE SEG$ ( "SCRATCH", 1%, LEN (Command) ) PRINT "That was a SCRATCH command." CASE SEG$( "OLD", 1%, LEN (Command) ) PRINT "That was an OLD command." CASE ELSE PRINT "Invalid command, please try again." END SELECT NEXT Done: END
This section describes the EXIT and ITERATE statements and shows their use with nested control structures.
The ITERATE and EXIT statements let you explicitly control loop execution. These statements can be used to transfer control to the top or bottom of a control structure.
You can use EXIT to transfer control out of any of these structures:
In the case of control structures, EXIT passes control to the first statement following the end of the control structure.
You can use ITERATE to explicitly reexecute a FOR...NEXT, WHILE...NEXT, or UNTIL...NEXT loop. EXIT and ITERATE statements can appear only within the code blocks you want to leave or reexecute.
Executing the ITERATE statement is equivalent to transferring control to the loop's NEXT statement. The termination test is still performed when the NEXT statement transfers control to the top of the loop. In addition, transferring control to the NEXT statement means that a FOR loop's control variable is incremented by the STEP value.
Supplying a label for every loop lets you state explicitly which loop to leave or reexecute. If you do not supply a label for the ITERATE statement, HP BASIC reexecutes the innermost active loop. For example, if an ITERATE statement (that does not specify a label) is executed in the innermost of three nested loops, only the innermost loop is reexecuted.
In contrast, labeling each loop and supplying a label argument to the ITERATE statement lets you reexecute any of the loops. A label name also helps document your code. Because you must use a label with EXIT and it is sometimes necessary to use a label with ITERATE, you should always label the structures you want to control with these statements.
The following example shows the use of both the EXIT and ITERATE statements. This program explicitly exits the loop if you type a carriage return in response to the prompt. If you type a string, the program prints the length of the string and explicitly reexecutes the loop.
DECLARE STRING User_string Read_loop: WHILE 1% = 1% LINPUT "Please type a string"; User_string IF User_string == "" THEN EXIT Read_loop ELSE PRINT "Length is ";LEN(User_string) ITERATE Read_loop END IF NEXT END
In HP BASIC, a subroutine is a block of code accessed by a GOSUB or ON GOSUB statement. It must be in the same program unit as the statement that calls it. The RETURN statement in the subroutine returns control to the statement immediately following the GOSUB.
The first line of a subroutine can be any valid HP BASIC statement, including a REM statement. You do not have to transfer control to the first line of the subroutine. Instead, you can include several entry points into the same subroutine. You can also reference subroutines by using a GOSUB or ON GOSUB statement to another subroutine.
Variables and data in a subroutine are global to the program unit in
which the subroutine resides.
9.6.1 GOSUB and RETURN Statements
The GOSUB statement unconditionally transfers control to a line in a subroutine. The last statement in a subroutine is a RETURN statement, which returns control to the first statement after the calling GOSUB. A subroutine can contain more than one RETURN statement so you can return control conditionally, depending on a specified condition.
The following example first assigns a value of 5 to the variable A, then transfers control to the subroutine labeled Times_two. This subroutine replaces the value of A with A multiplied by 2. The subroutine's RETURN statement transfers control to the first PRINT statement, which displays the changed value. The program calls the subroutine two more times, with different values for A. Each time, the RETURN transfers control to the statement immediately following the corresponding GOSUB.
A = 5 GOSUB Times_two PRINT A A = 15 GOSUB Times_two PRINT A A = 25 GOSUB Times_two PRINT A GOTO Done Times_two: !This is the subroutine entry point A = A * 2 RETURN Done: END
10 30 50
Note that HP BASIC signals "RETURN without GOSUB" if it
encounters a RETURN statement without first having encountered a GOSUB
or ON GOSUB statement.
9.6.2 ON...GOSUB...OTHERWISE Statement
The ON...GOSUB...OTHERWISE statement transfers control to one of several target subroutines depending on the value of a numeric expression. A RETURN statement returns control to the first statement after the calling ON GOSUB. A subroutine can contain more than one RETURN statement so that you can return control conditionally, depending on a specified condition.
HP BASIC tests the value of the integer expression. If the value is 1, control transfers to the first line number or label in the list; if the value is 2, control passes to the second line number or label, and so on. If the control variable's value is less than 1 or greater than the number of targets in the list, HP BASIC transfers control to the line number or label specified in the OTHERWISE clause. If you do not supply an OTHERWISE clause and the control variable's value is less than 1 or greater than the number of targets, BASIC signals "ON statement out of range (ERR=58)". For example:
INPUT "Please enter first integer value"; First_value% INPUT "Please enter second integer value"; Second_value% Choice: PRINT "Do you want to perform:" PRINT "1. Multiplication" PRINT "2. Division" PRINT "3. Exponentiation" INPUT Selection% ON Selection% GOSUB Mult, Div, Expon OTHERWISE Wrong GOTO Done Mult: Result% = First_value% * Second_value% PRINT Result% RETURN Div: Result% = First_value / Second_value% PRINT Result% RETURN Expon: Result% = First_value% ** Second_value% PRINT Result% RETURN Wrong: PRINT "Invalid selection" RETURN Done: END
The following HP BASIC statements suspend program execution:
These statements cause HP BASIC either to suspend program execution for a specified time or to wait a certain period of time for user input.
After execution of the last statement, a HP BASIC program automatically halts and closes all files. However, you can explicitly halt program execution by using one of the following statements:
The STOP statement does not close files. It can appear anywhere in a
program. The END statement closes files and must be the last statement
in a main program.
9.7.1 SLEEP Statement
The SLEEP statement suspends program execution for a specified number of seconds. The following program waits two minutes (120 seconds) after receiving the input string, and then prints it:
INPUT "Type a string of characters"; C$ SLEEP 120% PRINT C$ END
The SLEEP statement is useful if you have a program that depends on
another program for data. Instead of constantly checking for a
condition, the SLEEP statement lets you check the condition at
9.7.2 WAIT Statement
You use the WAIT statement only with terminal input statements such as INPUT, INPUT LINE, and LINPUT. For example, the following program prompts for input, then waits 30 seconds for your response. If the program does not receive input in the specified time, HP BASIC signals "Keyboard wait exhausted (ERR=15)" and exits the program.
WAIT 30% INPUT "You have 30 seconds to type your password"; PSW$ END
The WAIT statement affects all subsequent INPUT, INPUT LINE, LINPUT, MAT INPUT, and MAT LINPUT statements. To disable a previously specified WAIT statement, use WAIT 0%.
In the following example, the first WAIT statement causes the first INPUT statement to wait 30 seconds for a response. The WAIT 0% statement disables this 30-second requirement for all subsequent INPUT statements.
WAIT 30% INPUT "You have 30 seconds to type your password"; PSW$ WAIT 0% INPUT "What directory do you want to go to"; DIR$
The STOP statement is a debugging tool that lets you check the flow of program logic. STOP suspends program execution but does not close files.
When HP BASIC executes a STOP statement, it signals "STOP at line <line-num>."
If you compile, link, and execute a program containing a STOP statement, HP BASIC displays a number sign (#) prompt when the STOP statement is encountered. At this point, you can enter:
The END statement marks the end of a main program. When HP BASIC executes an END statement, it closes all files and halts program execution.
The END statement is optional in HP BASIC programs. However, it is good programming practice to include it. The END statement must be the last statement in the main program.