Copyright © by Mark Baker 1996
One of the chief arts of a successful programmer is the ability to break a complex task into a series of procedures and functions. Modular programs offer many advantages. They are much more readable and much easier to debug, since problems can be more readily traced to a particular module, which can then be examined in depth. Modules can often be transferred to libraries and reused in other programs and once they have been written and debugged, they will not need debugging in the future. So as you build up your libraries, you should find that the amount of debugging you have to do, when you write new programs, decreases. Modular design also allows teams of programmers to work in parallel, as each one can take a different module to work on. Individual modules can be redesigned/upgraded, without the need to alter other parts of the program, provided that the module interface (the parameter list) remains unchanged.
Pascal allows you to write two types of module, a procedure and a function. They are similar, but there are important differences and it is important that you clearly understand them. A function is used when you want to return a single data item, such as a number, a string or a boolean value. A procedure is used when you do not want to return any values, or when you want to return more than one value, or when you want to return one or more data structures, such as an array or a record.
.
.
a:= MyAge;
b:= YourAge;
AveAge:= Average(a,b); {Average is a function, with 2 parameters, a and b}
ResetScreen; {This procedure has no parameters}
WriteTitles; {ResetScreen and WriteTitles are both procedures}
DrawGraph(ExamResultsArray, ValidError); {DrawGraph is also a procedure}
.
.
Note that procedures and functions are called in different ways. A procedure is called by writing its name and any required parameters. A function always returns a value and that value normally has to be assigned somewhere. Functions can appear as part of various programming statements, replacing variables or constants:
writeln('The average age is: ', Average(a,b));
if > 50 then write ('Student has passed!')
else if Average(mark1, mark2) = 50 then write ('Borderline student')
else write ('Student has failed');
repeat
until (Average(score1, score2)>10) or (quit=true);
AveScore:= Average(mark1,mark2) {The parameters here are mark1 and mark2}
DrawGraph(ExamResultsArray,ValidError);{The parameters here are ExamResultsArray and ValidError}
Parameter passing can cause many problems, the worst of which is when the student gives up trying to use parameters and resorts to using global variables instead. This should be looked for and discouraged at all costs. Using global variables makes a program much harder to read and bugs are harder to find. Procedures/functions are no longer "independent" plug-in modules, but are tied to a particular program and cannot be transferred to a library unit. This can cause major problems in bigger programs. With Turbo Pascal, if the code generated by your main program reaches 64k in size, then the only way to continue programming is to transfer code into one or more units, each of which has a 64k limit.The simplest of procedures may not have any parameters. For example, you may write a procedure to reset the screen at the end of your programs. This might involve resetting the background colour to black and the text colour to grey and clearing the screen. Such a procedure would not need any parameters:
{----------------------------------------------}
procedure ResetScreen;
begin
textbackground(0);
textcolor(7);
clrscr;
end;
{----------------------------------------------}
However, most procedures and functions need parameters, either to pass data into them, to return data from them, or both.
{----------------------------------------------}
function Max(a,b: integer): integer;
var largest: integer;
begin
if a>b then largest:= a
else largest:= b;
Max:= largest;
end;
{----------------------------------------------}
When this function is called, you have to pass it two integer values, which are copied into the local variables a and b, before the function starts to execute:
oldest:= Max(age1,age2); {The value in age1 is copied into a and age2 is copied into b}
{----------------------------------------------}
procedure Max(a,b: integer; var largest: integer; var error: boolean);
begin
if (a<=0) or (b<=0) then error:= true
else
begin
error:= false;
if a>b then largest:= a
else largest:= b;
end;
end;
{----------------------------------------------}
In the above example, a and b are being used to pass the two integer values into the procedure. largest and error are used to pass the results of the procedure back out. a and b are being passed by value and largest and error are being passed by reference. The var that appears in front of largest and error tells the compiler that these parameters are being passed by reference.When a parameter is passed by reference, instead of copying a value into the local procedure or function variable, the memory reference saying where that parameter is stored in memory is passed in instead. The local variable then uses the same memory location, so that in effect any changes made inside the procedure or function are also made to the original parameter. Hence the term "pass by reference".
Getting students to create their own library, fairly early on in the course, emphasises the importance of modularity in programming and allows the students to start building up a resource of reusable code. Also, it is a vehicle for concentrating on "microprogramming", each procedure completes a single, clearly defined task. Most can be programmed in a few lines. It is the quality of thought that is important, with no need to produce a large program, with a complex interface. A simple test program that can call the library, is all that is needed as a framework. This exercise is designed to reinforce the fundamentals of programming and some students will need quite a lot of support during this exercise.
Students will need introducing to various string handling techniques, procedures and functions that will be needed for this exercise. I usually build up to this exercise by going through some algorithms in class and getting the students to work out what they do.
Procedure StarGow
Go to a given position, clear to the end of the line, write a *, followed by a given string, followed by another *.
Procedure StarLine
Go to a given Y coordinate and write a line of *'s across the screen.
Function StopsToSpaces
Take a string and replace any full stops with spaces.
Function StripLeadSpaces
Take a string and remove any leading spaces (spaces at the front of the string).
Function AllCaps
Take a string and convert all the letters to upper case (capitals).
Function StripSandS
Take a string and strip out any spaces and full stops.
Procedure MoveChar
Take a given character and make it appear to move across the screen.
Procedure MoveStr
Take a string and make it appear to move across the screen, stopping at a given position.
I take care to emphasise proper layout and indenting of programs. If students can be encouraged to indent properly from the beginning, it makes their work much more readable and debugging easier.
unit MyUnit; {The file should be saved with the file name MyUnit.pas, to match this line}
interface
uses crt,...etc;
procedure StarGow(x,y: integer; s: string);
procedure StarLine(y: integer);
function StopsToSpaces(s: string): string;
*
*
* etc.
implementation
{--------------------------------------------------------------------------------------}
procedure StarGow(x,y: integer; s: string);
begin
gotoxy(x,y);
clreol;
gotoxy(x,y);
write('*',s,'*');
end;
{---------------------------------------------------------------------------------------}
procedure StarLine(y: integer);
*
*
*
* ...etc.
end; {End of last procedure or function}
{---------------------------------------------------------------------------------------}
end. {End of unit}
To use the unit you have created you will need to do the following:
Teaching Programming I
Teaching Programming II
Teaching Programming IV