Control structures Foundation
Control structures define the logical program flow and are determined by statements. Xbase++ provides statements for branches, loops, and error handling. Branching allows different program sections to be called depending on conditions. Loops repeat a specific program section. The control structure for error handling controls the program flow if a runtime error occurs that does not require the program to be terminated.
Xbase++ offers two syntaxes for branching in programs. The first is the DO CASE...ENDCASE control structure and the other consists of the IF...ENDIF statements. Both branch statements evaluate logical expressions and branch to a program section when a logical condition returns the value .T. (true). The statements DO CASE...ENDCASEand IF...ENDIF offer different syntaxes but have the same effect. The general scheme for both control structures is as follows:
The simplest form of the IF statement tests only one condition and executes the program code appearing between the IF and ENDIFstatements when the condition is true.
If only one condition will be tested, but one of two branches will always be executed, the keyword ELSE is used. This means that whenever the condition is false, the alternative program code found between the ELSE and ENDIF statements is executed. With ELSE, no further condition is tested:
Additional conditions within the IF..ENDIF control structure are defined using the ELSEIF statement. If the statement ELSE is used along with ELSEIF statements, ELSE must always appear after all ELSEIF statements. In this case, ELSE defines the program code which is to be executed if none of the specified conditions apply.
There is no limit to the number of conditions that can be tested using IF...ELSEIF...ENDIF. IF branches can also be nested to any depth. An example of nesting is shown in the following program code:
The two branch control structures, IF...ENDIF and DO CASE...ENDCASE are merely different syntaxes and neither offers advantages in regard to runtime behavior. So the above branched code can also be written as follows:
A branch using IF...ENDIF is generally used only when only a few conditions are to be tested. When many possible conditions are tested in program code, it is generally done usingDO CASE.
The control structure "program loop" allows repeated execution of specific program sections. Xbase++ recognizes two sets of statements for loops: the DO WHILE...ENDDO and the FOR...NEXT statements. The DO WHILE loop tests a condition and repeats the section of program code as long as the condition returns the logical value .T. (true). The FOR loop is an iterative control structure that repeats a program section a specified number of times. Both control structures are described as follows:
The DO WHILE loop is the simpler form of program looping because it tests only one condition each time the program repeats the loop. If the condition returns the value .F. (false) when the DO WHILE statement is first reached, the loop is not executed at all. Otherwise the program code appearing between DO WHILE and ENDDO, is executed repeatedly until the condition returns the value .F..
The FOR loop changes a counter variable by a specific value after each cycle through the loop. The loop is terminated as soon as the value of the counter variable exceeds a maximum (or goes under a minimum) value.
Within both of these control structures the statements LOOP and EXIT may be included. LOOP causes the immediate return to the opening statement of the loop (FOR.. or DO WHILE...) skipping any remaining code within the loop. This allows parts of the loop to be excluded in certain repetitions. The statement EXIT immediately terminates the loop without any further testing of the condition or counter variable.
An example for a simple DO WHILE loop is shown in the following code. Keyboard input is read as long as the user does not press either the "Y" or the "N" key. If the user presses the "Y" key the program terminates, otherwise it continues:
An example of a typical use for DO WHILE loops is sequentially traversing data records in files after opening them using a DatabaseEngine.
FOR loops are used when the number of times a program section will be repeated is known. Each FOR loop contains an initialization part where the start value is assigned to the counter variable and where the final value (comparison value) for the counter is defined. In the following example, the end value is the constant 10 but it can also be a variable or an expression:
By default, the counter variable is incremented by the value 1after each pass through the loop. The optional keyword STEPspecifies the value by which the counter variable is changed after each pass through the loop. If a negative value is specified, the loop counter is decremented. In this case, the start value must be greater than the end value. Decrementing is shown in the next example which totals all even numbers between 10 and 1:
A very important area where FOR loops are used in programming is handling arrays. Within an iterative loop each array element can be sequentially accessed. The following code shows an example:
Xbase++ provides a control structure designed especially for exceptions and handling runtime errors. It uses the statements BEGIN SEQUENCEand ENDSEQUENCE and represents a powerful tool for improving the reliability and stability of a program. This section deals only with the fundamentals of the BEGIN SEQUENCE control structure. A detailed look at strategies for handling runtime errors is found in the chapter "Error Handling Concepts".
BEGIN SEQUENCE and ENDSEQUENCE delimit a section of program code which can be terminated at any time using the statement BREAKor the function Break(). Besides terminating the control structure, ENDSEQUENCE is also be a point where program flow continues after a BREAK is issued. In its simplest form, the control structure can be used as follows:
In this example, the program continues after a BREAK at the RETURN statement because it follows immediately after END SEQUENCE. The program code between BREAK and ENDSEQUENCEis skipped. This form of the control structure should generally be used only in exception situations. It is possible to exit deeply nested loops using a single BREAK if all loops are enclosed by BEGIN SEQUENCE and ENDSEQUENCE, but a branch is generally a better solution.
The most important use of this structure lies in error handling, which is performed using an additional RECOVER statement. RECOVERmarks a second entry point. If it is available, it marks the point where the program resumes after a BREAK is reached. If a BREAK does not occur, the program code betwen RECOVER and ENDSEQUENCE is not executed, and program flow moves to the first line following the RECOVER statement. Since the program code between RECOVER and ENDSEQUENCE is executed only after a BREAK, it generally contains program code that responds to runtime errors:
In this example, there is no explicit BREAK statement because the default error handling system of Xbase++ automatically executes a BREAK as soon as a runtime error occurs. An error occurs in the example whenever division by zero is attempted or when the variables nDividend and nDivisor do not both have numeric values. These errors cause a BREAK and the program continues after RECOVER. The line appearing there defines a valid value for the return value of the function Divide() that will allow the program to continue. When no error occurs during the division, the program code between RECOVER and ENDSEQUENCE is not executed.
As versatile as the control structure BEGIN SEQUENCE...ENDSEQUENCE is, it has an important restriction: this control structure cannot be exited using RETURN, EXIT, or LOOP. It can only be exited using BREAK or Break(). The following code shows invalid use of statements leading to compiler errors such that this program code cannot be compiled:
The above example can be compiled if the BEGIN SEQUENCE...ENDSEQUENCE encloses the DO WHILE loop and the RETURN statement does not appear within the loop. In this case, the jump to the top of the DO WHILE loop caused by LOOP and the loop termination caused by EXIT are still within the control structure BEGIN SEQUENCE...ENDSEQUENCE:
When a RECOVER statement appears within BEGIN SEQUENCE..END SEQUENCE, the statements LOOP, EXIT or RETURN can be used between RECOVER and ENDSEQUENCE to exit the BEGIN SEQUENCE..ENDSEQUENCE control structure. This is allowed because the entry point defined by RECOVER (which can only be reached after a BREAK) has already been reached. The following program code is valid and can be compiled:
The most important task of the BEGIN SEQUENCE...ENDSEQUENCEcontrol structure is to define the entry point where the program resumes if an exception or an error occurs. An entry point is defined using either the statement RECOVER or ENDSEQUENCE. Both entry points are reached after a BREAK or Break(). When the program does not execute a BREAK, the program code between RECOVER and ENDSEQUENCE is skipped and is not executed.
Within BEGIN SEQUENCE and ENDSEQUENCE, two alternative program sections can be programmed. The first alternative is executed when the program runs normally and the second is delimited byRECOVER and only executes following a BREAK. Possible program errors may be anticipated during program development and handled as exception situations. During normal program execution, the program code for correcting runtime errors is not executed. It is only executed when an error occurs.
The control structure BEGIN SEQUENCE...ENDSEQUENCE is augmented by the function ErrorBlock(). This function can be used to replace the default error handling system of Xbase++ with a user defined error system. Further information is found in the chapter "Error Handling Concepts".
If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.