                  Turbo Pascal for DOS Beginning Tutorial
                              by Glenn Grotzinger
                 Part 4 -- Writing Procedures and Functions
           all parts copyright 1995-96 (c) by Glenn Grotzinger.

        Hello, again, and lets get started...

An example of a solution of last week's programming problem:

program part3;

  { This program enables a user to play a guessing game.
    Range: 1-100     Guesses: 6 }

  var
    choice: char;
    randnum, number_given, attempts: integer;

  begin
    randomize; { start random # generator }
    while upcase(choice) <> 'N' do   { while we want to play }
      begin
        randnum := random(100) + 1;  { generate random number for game }
        attempts := 6; { set initial number of attempts }
        number_given := 1000; { stuff number_given so while kicks in }
        writeln('I''m thinking of a number between 1 and 100.  What is it?');
        while (attempts > 0) and (number_given <> randnum) do
           { while we still have attempts to guess }
          begin
            readln(number_given);
            if number_given = randnum then
               writeln('Congratulations!  You got the number right!')
            else
               begin
                 attempts := attempts - 1;
                 if attempts = 0 then
                   writeln('Sorry, you ran out of choices. ',
                           ' The number I was thinking of is ',
                           randnum, '.')
                 else
                   if number_given > randnum then
                     writeln('It''s lower.  (', attempts,
                           ' guesses remaining)')
                   else
                     writeln('It''s higher. (', attempts,
                           ' guesses remaining)');
              end;
          end;
        writeln;
        writeln('Do you want to play again? (Y/N)');
        readln(choice);
      end;
   end.
If there are any questions or difficulties, write ggrotz@2sprint.net.

On to the new stuff...

PROCEDURE writing
=================
        This is a way a lot of things work in Pascal.  For example, the
write command is a procedure.  We say the procedure name, then a list of
parameters which describe what we want to write.  Write is defined in
Pascal itself, but we can write our own procedures to do things.  Before
the main part of the program, and after our variable declarations, we
place our procedures.  Procedures are essentially whole separate programs
which perform small tasks in a bigger program. Here is a short example of
what I mean:

program tutorial11;

  var
    one, two: integer;
    final: integer;

  procedure addtwonumbers(first, second: integer; var answer: integer);
    begin
      answer := first + second;
    end;

  begin
    writeln('Adding two numbers:');
    writeln('Type two numbers in (space after each number) to add.');
    readln(one, two);
    addtwonumbers(one, two, final);
    writeln('The answer is ', final, '.');
  end.

The procedure enables us to perform more modular, understandable, and
easier to debug programs.  We always code logical parts of the program
together in procedures and functions (will be discussed later).  This
example is pretty simplistic, as we include only one statement in a
procedure (generally a waste of time), which could easily be in the body
of the program.  We can use one statement procedures in more logical things,
such as conversions of one set of unit to another.  We describe the parts
of the procedure declaration above, and the calling of the procedure.

We can define a series of statements as long as they are the same type, and
we don't want to keep them without the use of the VAR section of the
procedure.  We don't care about, and don't modify first, and second, so we
place them in there without the var.  We modify the variable used as
answer, so we MUST have the VAR before it in order to have the variable
survive in a modified state by calling the procedure.  Play around with
what happens in tutorial11 when you remove the var from in front of the
third statement.  When we call the procedure, we use variables which match
and make sense to what we want each variable we want. we use one, and two
for the numbers to add, because our procedure is designed
to add those first two numbers.  Then we put final in the last one, because
that is our final answer.  We can SAFELY use the same variable names for
the procedure and the globals, but it is a good idea not to, as it will not
always be possible to correlate our items in that way.  We should always
have a goal to write procedures/functions with ability to drop them into
another program where all the parameters are passed to it.  We can easily
drop the procedure written above into any other program that needs a similar
function.  It is possible to have a parameterless procedure as well, if it
is predicted as required.  Say...In a multi-function menu system or something
that does a set thing (clrscr is an example).

NOTE: It is always good to keep your old code when you write and use
parameter passing in your procedures and functions, so you can easily 
re-use your code and save time in having to rewrite old code.

FUNCTION writing
================
Function declarations are exactly like procedures, except that functions
have the capability to return a value.  We see in the example, below, which
is a rewrite of tutorial11.

program tutorial12;
  var
    one, two: integer;
    final: integer;

  function addtwonumbers(first, second: integer):integer;
    var
      answer: integer;
    begin
      answer := first + second;
      addtwonumbers := answer;
      {we can also do addtwonumbers := first + second;}
    end;

  begin
    writeln('Adding two numbers:');
    writeln('Type two numbers in (space after each number) to add.');
    readln(one, two);
    final := addtwonumbers(one, two);
    writeln('The answer is ', final, '.');
  end.

In the function, we see we MUST define the final answer to the value of
the function.  The end part :integer; defines the return value of the
function.  The way to set up a function should be evident from this example.

SETS
====
It's possible in an IF/WHILE/REPEAT to set up a test on a group of statements.
For example:
   IF character in ['a'..'z'] then
   { if character is in the lowercase alphabet }
   IF character in ['1','2','3','5']
   { if character is 1, 2, 3, or 5 }
   IF number in [0..23] then
   { if number is between 0 and 23 }

TYPE and CONST statements.
==========================
It's possible to type-delineate variables.  Such as for example, we may want
to limit a string from it's standard 255 characters (if we say just string),
to say 10 characters (string[10]), we can not use something like that in
a procedure or function (we will see the types used a lot).  Therefore, we
use the type section to redefine this so we can use them in procedures/
functions.

It's also possible to set constants in a pascal program.  Say, if we want
to set up a constant tax rate, we just define it in a constant section.

We see this in an example:

program tutorial13;
  const
    tax_rate = 0.14; {14% tax rate}
  type
    string[15] = string15;
    { string[15] redefined so we can use it in a procedure/function,
      though we will not have procedures or functions here. }
  var
    total_pay: real;
    your_name: string15;
    {if we make type dec, we must carry it across.  This variable is
     a string with a limit of 15 characters. }
  begin
    writeln('Who are you? (15 char. max)');
    readln(your_name);
    writeln('How much did you earn this paycheck?');
    readln(total_pay);
    writeln('Assuming, you have a ', tax_rate * 100 :0:0, '% income tax ',
            'rate, you will have to pay $', total_pay * tax_rate :0:2,
            ' in income tax this paycheck.');
  end.

The use of tax_rate is a prime reason that we would want to define a
constant.  Instead of using that number everywhere we needed it, we used
the reference of tax_rate.  Why?  If the income tax ever changed in this
example, we would not need to go through the whole program and change that
number.  All we need to do is change that reference.
    
Clearing the screen
===================
This will be the first example of a command that we must call a unit for
to get.  The unit you call (as I did in tutorial1) would be CRT for TP/DOS,
and WINCRT for TP/WIN.  You use the statement clrscr; for this.  This
program example clears the screen.

program tutorial14; uses crt;
  begin
    clrscr;
    writeln('I cleared the screen for you.');
  end.

Final Note
-=========
You should lay out your programs in logical units using functions and
procedures, making them parameter passing if possible, and logical.
The best may be (especially for programs that do multiple things which
are unrelated on code level) to not parameter pass.  Whatever works
functionally is the best, and if you can't figure out a way to parameter
pass to the procedure or function....

Programming Practice Problem Notes
==================================
        This is the first program, that I would expect you to write using
functions and procedures.  All programs you should write in the future
should strive to use parameter-passed procedures.  The reasons are many-
fold for this, which I stated before.  Be sure you do this.  This program
should not be any more difficult than any of the previous programming
problems I gave.  All I expect this one to be is an exercise for you to
learn in using procedures and functions.  If you want more practice beyond
this problem in writing things using procedures and parameters, I suggest
you recode the programming problem out of part 2.  If you can get it more
easier understood to look at, and using parameter-passed procedures for the
logical parts of it, and make it work right, then you got it.

Practice Programming Problem #4
===============================
        Write a program in pascal and entirely Pascal which will present
a simple menu driven system (readable, and by pages -- use clrscr in the
appropriate spots) which will enable the user by choice to do the following,
as indicated by sample output for the menu.

sample output for menu
======================
1. Convert a number of seconds to hours, minutes, and seconds.
2. Convert a given military time to AM/PM time.
3. Quit the program.

Please enter your choice now:

sample output for option 1
==========================
Please enter a number of seconds: 3600

3600 seconds is 1 hour, 0 minutes, and 0 seconds.

Press ENTER to continue:

sample output for option 2
==========================
Enter a military time's hours: 14
Enter a miltiary time's seconds: 00

It is 2:00 PM.

Press ENTER to continue:
================

Notes: 1. there are 60 seconds in a minute, 60 minutes in an hour.
       2. "military time" is 24-hr time.  For example, 16:00 would be
          4 P.M.
       3. The program must continue to function in the menu system until
          the user wishes to quit.
       4. Remember to ask the user for appropriate data that you need.
       5. Be sure to pause the screen to enable the user to see the results
          of their query.  You may accomplish this by just calling readln;.
          It will call the computer to wait until the user presses a key.
       6. Be SURE your program is easily understood.


The solution to this program will be presented in the next part.  Good luck!

Next time
=========
        Next time, we will discuss the usage of text files for reading in
data and writing out results. We really are moving along with the concepts
rather readily...


