Procedures (subprograms) in Pascal

In this handout, we will be concerned with the basic design of subprograms in Pascal, called PROCEDURES. Essentially, procedures are self-contained "mini- programs" which communicate with the main program and do specific tasks during the execution of the program. In doing so, the main program, when it calls a procedure, sends data to the procedure (= "passes information", if any is needed) and the procedure reports back any answers it has found to the calling program (if indeed any were found).

The major challenge is using procedures is to:

  1. clearly confine the procedure to a single, simple task (it is very tempting to want to put too much into a single procedure; a rule of thumb: if your procedure is more than a page long (about 60 lines of code), it's TOO long);

  2. accurately judge what information the procedure will need to do it's job, no matter when it is called (i.e., when it runs);

  3. allow the procedure to report back its findings to the calling program.

Where are procedures defined and where are they called? It's simple:
Program Prog_name;

Uses
  .. 

Const
  <any global constants are declared here>

Var
  <any global storage locations are declared here>
.
.
Procedure definitions are placed here
.
.
Begin { MAIN }
  .
  .
  Procedures are called by name here in main line code
  .
End.
For example, how many times have you wanted to be able to draw a line of dashes or equal signs in your output? Here's how a procedure to write a line of characters might look; the character to print and how many of them to print are passed to the procedure (an example of pass by value):
Procedure Print_Line(Symbol: Char; Len: Integer);

Var
  LCV: Integer;  {local loop control variable}

Begin
  For LCV := 1 to Len Do
    Write(Symbol);
  Writeln;
End;  {Procedure Print_Line}
The name of the procedure is Print_Line. The list of identifiers inside the parentheses after the procedure name is called the formal parameter list and the individual identifiers are called formal parameters. They indicate the values being passed to the procedure for its use. At the time the procedure runs, storage will be assigned by Pascal using the names of the identifiers in the formal parameter list, and these storage locations will be typed as declared in the parameter list. Sometimes the formal parameter list is called the "communication section" of the procedure. The procedure is called by name in the calling program; we also say the procedure is invoked in the calling program. To invoke a procedure, we use its name exactly as it appears in its definition, and we are required to list in the calling statement storage locations of the same kind and in the same order as those in the procedure definition.

Let's see via an example:

We're going to write a short program which will add the integers 1 + 2 + 3 + ... + N for various values of N. We will design a loop and compare the results of the loop with a known formula for this sum, namely N * (N + 1) / 2.

Program Adding_methods;

Const
  Number_of_characters = 65;
  Double_Dash = '=';

Var
  Test, Count, Sum, Formula: Integer;

Procedure Print_Line(Symbol: Char; Len: Integer);

Var
  LCV: Integer;

Begin
  For LCV := 1 to Len Do
    Write(Symbol);
  Writeln;
End; { Print_Line }

Begin

  Readln(Test);
  Clrscr;


  { print banner }

  Print_Line(Double_dash, Number_of_Characters);
  Writeln('  N         1 + 2 + ... + N          N * (N+1) / 2');
  Print_Line(Double_dash, Number_of_Characters);

  Sum := 0;
  For Count := 1 to Test Do
    Sum := Sum + Count;
  Formula := N * (N + 1) DIV 2;
  
  Writeln(Test :5, Sum :15, Formula :15);
  Print_Line(Double_dash, Number_of_Characters);
  Readln
End. 
Again, the identifiers Symbol and Len found in the procedure header in our example are called the procedure's formal parameters. The places in the program where the procedure is invoked do so by the name of the procedure along with identifiers set up locally to the calling program. They are, in this case, Dash and Number_of_Characters. They are called the actual parameters used at the time the procedure is invoked. What Pascal sees in the actual parameter list must match those in the formal parameter list EXACTLY in both number of parameters and type of parameters. Rarely, if ever, do I want to see identical names of identifiers used in both lists!

The method of passing information to a procedure it will need to do its job (as illustrated in the previous example) is called PASSING BY VALUE. This notion is well-named, since we are sending to the procedure values via a one-way communication link in the actual parameter list to the formal parameter list. Values passed to the procedure via the actual parameter list are placed in storage locations which are created "on-the-fly" when the procedure runs and are, therefore, local to the procedure while it is running. Mechanically, it works this way: when a procedure runs, the storage needed by the procedure is created (all parameters in its formal parameter list together with all constants and variables declared in the procedure definition); values in the actual parameter list are copied into the matching identifiers in the formal parameter list. These values are then available to the procedure so that it can find the results you desire. For this reason, parameters in the formal parameter list into which values will be copied are called value parameters.

What do you do when you wish a procedure to report back to the calling program a value (or values) it has found when it runs? Remember, value parameters are one-way streets only; information can be copied into them, but that's it! The mechanism Pascal uses to return values to the calling program is called a VARIABLE PARAMETER. Such a parameter appears in a procedure's formal parameter list, but is preceded by the keyword VAR. Such parameters offer two- way communication between themselves and their matching parameter in the actual parameter list. A change in one is automatically a change in the other while the procedure is running.

Here's an example: suppose we want to design a simple procedure which will accept three integers and report back to the calling program the smallest of the three. The procedure is defined below in the context of a program in which it is used:

Program Testsmallest;

Var
  Exam1, Exam2, Exam3, Drop: Integer;
  Average: Real;


{ Procedure to find smallest of three integer values}

Procedure Smallest_of_3(Num1, Num2, Num3: Integer;
                      Var Smallest: Integer;

{ There are only six possible orderings of the three numbers:
  Num1 <= Num2 <= Num3
  Num1 <= Num3 <= Num2
  Num2 <= Num1 <= Num3
  Num2 <= Num3 <= Num1
  Num3 <= Num1 <= Num2
  Num3 <= Num2 <= Num1 }

Begin
  If (Num1 <= Num2) and (Num2 <= Num3)
    Then Smallest := Num1
  Else If (Num1 <= Num3) and (Num3 <= Num2)
    Then Smallest := Num1
  Else If (Num2 <= Num1) and (Num1 <= Num3)
    Then Smallest := Num2
  Else If (Num2 <= Num3) and (Num3 <= Num1)
    Then Smallest := Num2
  Else Smallest := Num3
End; { Smallest_of_3 }

Begin { MAIN }
  Readln(Exam1, Exam2, Exam3);
  Smallest_of_3(Exam1, Exam2, Exam3, Drop);
  Write('The average of the highest two scores is: ');
  Average := (Exam1 + Exam2 + Exam3 - Drop) / 2;
  Writeln(Average :0:2)
End.

Forward to next page Forward to
Page 2
on Procedures
    Return to
CS-171
Home Page
    Return to
UW-W
Home Page
   
This page last updated
19 May 2000