04 QBasic Tutorial Procedures

SECTION 5 – DESIGNING APPLICATIONS (Linear V Modular)

Learning Objectives

At the end of this tutorial  you will know about:

  • How to use functions and procedures

It is not practical in real world terms to set up an application in one long list of code. Many early programming languages were purely linear, meaning that they started from one point on a list of code, and ended at another point. However, linear programming is not practical in a team environment. If one person could write one aspect of code, and another write another part of the program, things would be much more organized. QBasic contains the capability to meet these needs, called modular programming. You can break a program into different “modules” which are separate from the main program and yet can be accessed by any part of it. I highly recommend the use of separate modules in programming applications, although it is not a simple task to learn.

 Procedures & Functions

These separate modules are also known as procedures in the QBasic environment. There are two types of procedures: subs and functions. Subs merely execute a task and return to the main program, which functions execute a task and return a value to the main program. An example of a sub might be a procedure which displays a title screen on the screen, while a function may be a procedure that returns a degree in degrees given a number in radians. Function procedures are also used in Calculus, so you Calculus people should already be familiar with functions.

Arguments

Procedures can accept arguments in what is called an argument list. Each argument in the argument list has a defined type, and an object of that type must be passed to the procedure when it is called. For example, the CHR$ QBasic function accepts a numeric argument. The function itself converts this numeric argument into a string representation of the ASCII value of the number passed, and returns this one character string.

Procedures

Procedures in QBasic are given their own screen. When you enter the QBasic IDE, you are in the main procedure which can access all the others. Other procedures are created by typing the type of procedure (SUB or FUNCTION), the procedure name, followed by the complete argument list. You can view your procedures through the VIEW menu. Here is an example of a sub procedure which performs some operations for a program that will be using graphics, random numbers, and a logical plane.

 

SUB initProgram()

RANDOMIZE TIMER

SCREEN 12

WINDOW (0,0)-(100,100)

COLOR 15

END SUB

 

The only thing you need to type is SUB initProgram (), and the screen will be switched to that procedure. The END SUB is placed there for you, so the only thing you need to type then is the code within the sub. Try typing this out on your own to see how this works. This procedure is called by simply typing initProgram in the main procedure. An alternative method is CALL initProcedure (). Right here the parentheses are optional, but if you were to pass arguments to the procedure, parentheses would be required with the CALL statement. Now lets try passing an argument to a procedure. We will pass two arguments to a procedure called centre which are a string containing the text to be centreed, and the horizontal location on the screen at which you wish to centre it.

 

SUB centre( strText, sngHLointC )

LOCATE sngHLointC, 41 – (LEN(strText) / 2)

PRINT strText

END SUB

 

The first line after the sub declaration positions the starting point of the text at the horizontal location we passed at the second argument and vertical coordinate. The vertical coordinate is calculated by subtracting one half the screen’s width in characters (41) and half the LENgth of the text we passed as the first argument. We would call centre from the main procedure like this:

centre “Programmed by QP7”, 12

Or like this

CALL centre (“Programmed by QP7”, 12)

The Concrete Calculator

This program calculates the volume of a block using a procedure

 Program Code – Type it in
DECLARE SUB subBlock ()

DECLARE SUB subcylinder ()

‘Program: Concrete Calculator

‘Author Michael Fabbro

‘Date 7 December 2003

‘This program will work out costings for quotes

Dim dblTotalVolume As Double

Dim intStartLine As Integer

‘Main section

intStartLine = 2

Call subBlock

End

 

Sub subBlock()

‘Procedure to calculate volume of a block

Dim sngHeight, sngWidth, sngLength As Single

Dim dblVolume As Double

Color 10, 1

Cls

LOCATE 2, 25: Print “Concrete Calculator”

LOCATE intStartLine + 5, 5: Print “Height”

LOCATE intStartLine + 7, 5: Print “Width”

LOCATE intStartLine + 9, 5: Print “Length”

LOCATE intStartLine + 15, 15: Print “Volume”

LOCATE intStartLine + 5, 12: INPUT ” “, sngHeight

LOCATE intStartLine + 7, 12: INPUT ” “, sngWidth

LOCATE intStartLine + 9, 12: INPUT ” “, sngLength

‘Calculate Volume

dblVolume = sngHeight * sngWidth * sngLength

LOCATE intStartLine + 15, 24: Print USING “#####.##”; dblVolume;

End Sub

Test the program with this data
Input:

Expected output:

 

 

Results

The full program in modular form can be found here. A menu using procedures is used and INKEY$ which reads a character from the keyboard.

IN KEY$

■ INKEY$ returns a null string if there is no character to return
■ For standard keys, INKEY$ returns a 1-byte string containing the character read.
■ For extended keys, INKEY$ returns a 2-byte string made up of the   character (ASCII 0) and the keyboard scan code.

Example:
PRINT “Press Esc to exit…”
DO

LOOP UNTIL INKEY$ = CHR$(27)   ’27 is the ASCII code for Esc.

Keycodes

Key        Code   ║     Key         Code   ║     Key        Code
 c        1       ║     A           30     ║    Caps Lock   58
 ! or 1   2       ║     S           31     ║     F1           59
 @ or 2   3       ║     D           32     ║     F2           60
 # or 3   4       ║     F           33     ║     F3           61
 $ or 4   5       ║     G           34     ║     F4           62
 % or 5   6       ║     H           35     ║     F5           63
 ^ or 6   7       ║     J           36     ║     F6           64
 & or 7   8       ║     K           37     ║     F7           65
 * or 8   9       ║     L           38     ║     F8           66
 ( or 9   10      ║     : or ;      39     ║     F9           67
 ) or 0   11      ║     " or '      40     ║     F10               
          12      ║     ~ or `      41     ║     F11         133
 + or =   13      ║     Left Shift  42     ║     F12         134 
 Bksp     14      ║     | or \      43     ║     NumLock      69
 Tab      15      ║     Z           44     ║     Scroll Lock  70
 Q        16      ║     X           45     ║     Home or 7   71

 

This is the full program

DECLARE SUB subBlock ()
DECLARE SUB subCylinder ()
‘Program: Concrete Calculator
‘Author Michael Fabbro
‘Date 7 December 2003
‘This program will work out costings for quotes

‘Glossary of Variables
‘intStartLine – start position of the inputscrenn
‘dblTotalVolume – running total of volume

‘Global Scope Variables
Dim dblTotalVolume As Double
Dim intStartLine As Integer
‘Local Variables
Dim strCommand As String

‘Main section
‘initialise variables
dblTotalVolume = 0

‘Set up input screen
intStartLine = 2
Color 10, 1
DO
CLS
LOCATE 2, 25: Print “Concrete Calc Main Menu”
LOCATE intStartLine + 6, 15: Print “[B]lock”
LOCATE intStartLine + 8, 15: Print “[C]ylinder”
LOCATE intStartLine + 10, 15: Print “[R]set Total”
LOCATE intStartLine + 12, 15: Print “[Q]uit”
LOCATE intStartLine + 14, 15: Print “Enter B,C,R,Q”
strCommand = “”
‘scan for menu choice
Do While strCommand = “”
‘note strCommand= ucase$(inkey$) is a better solution
strCommand = INKEY$
Loop
‘note strCommand= ucase$(inkey$) above is a better solution
‘convert to uppercase
strCommand = UCase$(strCommand)
Select Case strCommand
Case Is = “B”
Call subBlock
Case Is = “C”
Call subCylinder
Case Is = “R”
dblTotalVolume = 0
Case Is = “Q”
END
END SELECT
LOOP WHILE strCommand <> “Q”

Sub subBlock()
‘Procedure to calculate volume of a block

‘ Alphabetical Glossary of Local Variables
‘ sngJunk – used for pausing screen
‘sngLength – Length of Cylinder
‘sngWidth – Width of Block
‘sngHeight – height of block
‘dblVolume – Calulated Volume of Cylinder

‘Declare Local Variables
Dim sngRadius, sngWidth, sngLength As Single
Dim dblVolume As Double
Dim strJunk As String

‘input screen
Color 10, 1
Cls
LOCATE 2, 25: Print “Concrete Calculator”
LOCATE intStartLine + 5, 5: Print “Height”
LOCATE intStartLine + 7, 5: Print “Width”
LOCATE intStartLine + 9, 5: Print “Length”
LOCATE intStartLine + 15, 15: Print “Volume”
LOCATE intStartLine + 5, 12: INPUT ” “, sngHeight
LOCATE intStartLine + 7, 12: INPUT ” “, sngWidth
LOCATE intStartLine + 9, 12: INPUT ” “, sngLength
‘Calculate Volume and output
dblVolume = sngHeight * sngWidth * sngLength
dblTotalVolume = dblTotalVolume + dblVolume
LOCATE intStartLine + 15, 24: Print USING “#####.##”; dblVolume;
Print ” Cubic Metres”
LOCATE intStartLine + 17, 24: Print “Total so far: “;
Print USING “#####.##”; dblTotalVolume;
Print ” Cubic Metres”
LOCATE intStartLine + 19, 24: INPUT “Press enter to continue”; strJunk
End Sub

Sub subCylinder()
‘Subroutine to calulate volume of a concrete cylinder

‘Alphabetical Glossary of Local Variables
‘sngJunk – used for pausing screen
‘sngLength – Length of Cylinder
‘sngRadius – Radius of Cylinder
‘dblVolume – Calulated Volume of Cylinder

‘Declare Local Variables
Dim strJunk As String
Dim sngLength, sngRadius As Integer
Dim dblVolume As Integer
Const conPi = 3.142

‘Procedure to calculate volume of a cylinder
Color 10, 1
CLS
LOCATE 2, 25: Print “Concrete Calculator”
LOCATE intStartLine + 5, 5: Print “Radius”
LOCATE intStartLine + 7, 5: Print “Length”
LOCATE intStartLine + 15, 15: Print “Volume”
LOCATE intStartLine + 5, 12: INPUT ” “, sngRadius
LOCATE intStartLine + 7, 12: INPUT ” “, sngLength
‘Calculate Volume
dblVolume = conPi * sngRadius ^ 2 * sngLength
dblTotalVolume = dblTotalVolume + dblVolume
LOCATE intStartLine + 15, 24: Print USING “#####.##”; dblVolume;
Print ” Cubic Metres”
LOCATE intStartLine + 17, 24: Print “Total so far: “;
Print USING “#####.##”; dblTotalVolume;
Print ” Cubic Metres”
LOCATE intStartLine + 19, 24: INPUT “Press enter to continue”; strJunk
End Sub

Download the program here

 

Advanced Example

There is one final concept which has proven to be very successful in programming: a message loop. With QBasic, you can construct a loop which runs for the length of the program, receives input from the user, and executes a message based on what the user does. We will construct a basic application which receives input from the user in the form of an arrow key, and moves a box on the screen based on the direction the user pressed. The arrow keys are different from normal inputted keys received with INKEY$.

 

On the enhanced 101 keyboards which have arrow keys, INKEY$ returns two values: the ASCII text representation of the key pressed, and the keyboard scan code of the key pressed. Since the arrow keys do not have an ASCII text representation, we must use the keyboard scan codes for them. The keyboard scan codes can be viewed in the HELP | CONTENTS section of the QBasic menus. For this program, we will have two procedures in addition to the main procedure. The first will initialize the program settings and position the character in his starting position. The other will move the guy in the direction which we pass to the function. The main procedure will call the sub procedures and contains the main message loop which retrieves input from the user. First of all, here is the code for the main procedure:

 

CONST UP = 1
CONST DOWN = 2
CONST LEFT = 3
CONST RIGHT = 4

 

TYPE objectType

intX AS INTEGER
intY AS INTEGER

END TYPE

DIM object AS objectType

initScreen
object.x = 41
object.y = 24

 

 

DO

SELECT CASE INKEY$

CASE CHR$(0) + CHR$(72)

move UP, object

CASE CHR$(0) + CHR$(80)

move DOWN, object

CASE CHR$(0) + CHR$(75)

move LEFT, object

CASE CHR$(0) + CHR$(77)

move RIGHT, object

CASE CHR$(32)

EXIT DO

END SELECT

LOOP

LOCATE 1,1: PRINT “Thank you for playing”

END

 

This code is fairly self explanatory with the exception of the SELECT CASE… END SELECT structure which I have not yet explained. This type of conditional testing format tests a condition, and several cases for that condition are then tested. In this case, we are seeing IF INKEY$ = CHR$(0) + CHR$(72), IF INKEY$ = CHR$(0) + CHR$(80), and so on. This is just a more legible format than IF…THEN…ELSE. Note that in the QuickBasic compiler, a CASE ELSE statement is required in the structure for what reason

 

I have no idea. The above code is the driver for the rest of the program. First some CONSTants are declared which remain constant for the duration of the program and in any module. A user defined type is declared to store the coordinates of the character.

 

Then an endless loop is executed, calling the appropriate procedure for the arrow key pressed until the user presses the space bar (CHR$(32)). Here is the code for the initScreen procedure:

 

SUB initScreen ()

SCREEN 12

COLOR 9

WIDTH 80,50

LOCATE 24,41

PRINT CHR$(1)

END SUB

 

The WIDTH 80,50 statement sets the screen text resolution to 80 columns and 50 rows. We then print a smiley face in the middle of the screen in a nice bright blue colour. Next we need to write the move procedure, and then we will be done with the program.

 

SUB move (way AS INTEGER, object AS objectType)

LOCATE object.y, object.x

PRINT CHR$(0)       ‘ erase previous image

SELECT CASE way

CASE UP

IF object.y > 1 THEN

object.y = object.y – 1

END IF

CASE DOWN

IF object.y < 49 THEN

object.y = object.y + 1

END IF

CASE LEFT

IF object.x > 1 THEN

object.x = object.x – 1

END IF

CASE RIGHT

IF object.x < 79 THEN

object.x = object.x + 1

END IF

END SELECT

LOCATE object.y, object.x

PRINT CHR$(1)       ‘ draw current image

END SUB

 

And that’s the whole program… confusing as it may be! Ideas should be going through your head about what you could do with this information. Entire games can be created with this simple construct.

 

There are more things to consider, but they are beyond the scope of this tutorial. If you were to design an application in QBasic, you would only need the information from this section and  imagination. Programming takes knowledge of the language and a creative mind… programs are made by programmers with both. If you can develop a creative mind, then you can develop any program conceivable.

Validation Checking for Errors

This program checks the input of hours worked for erroneous data, i.e. working for more than 60 hours.

‘ Program to validate inputs
‘ Author Michael J Fabbro
‘ Date 16 December 2003
Dim sngHoursWorked As Integer
Const cntRed = 12
Const cntBlue = 9
Const cntYellow = 14
Color cntYellow, cntBlue
Cls
Do
LOCATE 5, 5: Print “Hours Worked: “;
INPUT ” “, sngHoursWorked
If sngHoursWorked >= 60 Then
‘ invalid hours input
Color , cntRed
LOCATE 7, 5: Print “Warning ‘con’ in progress”
Do
Loop While INKEY$ = “”
Color cntYellow, cntBlue
Cls
End If
Loop While sngHoursWorked >= 60

 

This is a final example of Validation

‘ Program to validate inputs
‘ Author Michael J Fabbro
‘ Date 16 December 2003
Dim strTitle As String
‘ Modification of valid titles?
Const strValidTitles = “Mr:Mrs:Ms:Master”
Const cntRed = 12
Const cntBlue = 9
Const cntYellow = 14
Color cntYellow, cntBlue
CLS
DO
LOCATE 5, 5: Print “Title: “;
INPUT ” “, strTitle
Select Case strTitle
Case Is = “Mr”
LOCATE 7, 5: Print “Male title known”
Case Is = “Mrs”
LOCATE 7, 5: Print “Female title known”
Case Is = “Ms”
LOCATE 7, 5: Print “Female title known”
Case Else
‘ invalid title
Color , cntRed
LOCATE 7, 5: Print “Title not known”
Do
Loop While INKEY$ = “”
Color cntYellow, cntBlue
Cls
End Select
Loop Until strTitle = “Mr” Or strTitle = “Ms” Or strTitle = “Mrs”