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
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
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” |
|