Last modified on 2 August 2013, at 18:50

QBasic/Subroutines and Functions

PurposeEdit

Subroutines and functions are ways to break up your code into a reusable form. They allow the programmer to do a large set of operations just by calling the appropriate procedure or function. For example, lets say you need to PRINT a lot of lines, such as instructions. One way to do this is to just enter all your PRINT commands directly into where you need them. At some point, you may want to move the PRINT commands, or you may use the exact set of PRINTs elsewhere in the program. To move or change all of the PRINT commands would be quite a hassle. A simpler way would be to create a procedure and enter all of the PRINT commands there; then, when you need to execute the commands, you may simply call your procedure and it will execute each line in its body.

Procedure vs. FunctionEdit

A procedure DOES something and does not return anything for the programmer. For example, a procedure might be used to set the screen mode and palette.

A function does something and RETURNS a value. For example, if you need to find the average of two values, you might write a function that takes in two numbers and returns the average.

GOTO and GOSUBEdit

The GOTO and GOSUB statements were the original methods at which functions were created. They were the most common on older basic implementations and are kept around for compatibility reasons; however, their use is not recommended in other programming languages or in large scale projects.

These two commands depend on labels, which come in one of two forms. The first and older form involves writing line numbers at the beginning of each line (usually in increments of 10). The newer method looks similar to other programming languages, which is a single word followed by a colon.

The GOTO statement is simple; it moves the execution point to a given label:

 

The GOSUB statement transfers control to a given label, and is paired with a corresponding RETURN statement.

 

ON ERROREdit

The ON ERROR allows you to define an error handler for your program; when an error occurs, it immediately jumps to the given label. The control returns once the program reaches a RESUME statement, which can either return control to the same point, the next statement, or any other desired label.

Within Qbasic, the error handler cannot be located within any subroutines. As such, any error checking or flags will have to be handled through the use of variables that are shared with the main module.

Note:
While the QBasic documentation states ON ERROR RESUME NEXT is a valid statement, this is incorrect.

NOTE: If your error handling routine does not have a "resume" statement in it (IOW you try to do it all with gotos) error handeling will only work once - the next "on error" will be ignored and the program ends as if you had no "on error" statement at all. This problem does not seem to be mentioned in any of the documentation. It took me three hours to figure out why two nearly identical program portions acted so differently.

Declaring a subroutineEdit

A superior method of declaring a subroutine is using the SUB statement block. Under the QBasic IDE, doing so moves the SUB block to it's own section in the window to prevent accidental deletion of the module, and allows the easier organization of the program code.

Calling a function is as simple as writing the name of the function (passing any required parameters.) If you want, you can use the CALL statement to indicate to other programmers that it is a subroutine.

SUB NAME (params)
{SHARED variables 'if any}
'{code to execute}
'  ...
'  ...
{STATIC variables 'if any, to be saved for use next time}
END SUB

Parameters passed into subroutines are passed by 'reference' i.e. whilst they may take on a new name within the SUB any changes that are made to the values are 'reflected back' into the originals. All other variables used within the SUB are discarded when the END SUB is reached (or an EXIT SUB is executed), except as below :-

To 'preserve' the values of variables used within the SUB for re-use on the next CALL, use the STATIC keyword at the end.

If you need access to a variable (that has not been passed as a parameter), use the SHARED keyword to define each at the start of the subroutine (a SHARED variable retains it's name).

Declaring a functionEdit

A function is a form of subroutine that returns a value. Everything that applies in defining a subroutine also applies to a function. Within the function, the return value is created by using the function name as a variable - the return value is then passed to the calling expression.

FUNCTION NAME (params) 
  ' Shared variable declarations
  NAME = result
  ' ...
END FUNCTION

Functions are declared in the same way as variables - it returns the variable type it's defined to return, in the same way variables are defined to contain their specified type. By default, it is a number, but appending a dollar sign indicates that it is returning a string.

Functions can only be called within an expression; unlike subroutines, they are not a standalone statement.