Pascal Programming Lecture Notes
Pascal Programming Lecture Notes
LECTURE NOTES
1993
INTRODUCTION
Pascal has three main advantages over most other languages. These
advantages are:
Efficiency: This concerns the size of programs and the speed at which
they run on the computer. To be efficient, a program should be small
and fast - it does not matter how long the Pascal source program is.
Getting Started
PROGRAM n (output)
BEGIN
END.
The first line of the program is called the 'program heading'. The rest of
the program is the 'program body'.
PROGRAM, BEGIN and END are 'reserved words'. This means that they
can be used only in the context they are intended. They cannot serve as
names.
1.2 Output
1.2.1 'writeln'
writeln('...')
Merry Christmas
The writeln-statement may produce various outputs as it can be seen in the
following examples:
Merry Christmas
Happy New Year
Merry Christmas
1.2.2 'write'
The effect at rub time is the same except that the current output line is not
terminated; output from successive write-statements appears on the same
line.
A writeln-statement with three parameters "a", "b" and "c"
writeln(a, b, c)
write(a, b, c);
writeln
write(a);
write(b);
write(c);
writeln
(b) PROGRAM, BEGIN and END are aligned but information between
BEGIN and END (and, as it will be seen later, between PROGRAM and
BEGIN) is idented two or three spaces.
(d) Two statements on the same line are separated by few spaces.
(e) A statement does not extend across one a line boundary (but this
constrain will be relaxed when statements get longer.
Because a semicolon separates one statement from the next, no semicolon
should follow a statement which precedes END. However, a semicolon at
this point is allowed and some people find that its inclusion simplifies the
task of inserting further statements at a later date.
1.4 Comments
A comment may also be set between the compound symbols (* and *). A
comment may appear at any point in the program at which a space would
be legal.
BEGIN
writeln('Merry Christmas');
writeln;
writeln('Happy New Year')
END.
CHAPTER 2
Think of a Number
2.1 Constants
There are two ways of representing real numbers: 'fixed point' form, as
above, and 'floating point' form. The later has the form
aEb
-347.8216 -3.478216E2
0.00001 1E-5
7200000000.0 7.2E9
2.2 Expressions
+ represents addition
- represents subtraction
* represents multiplication
/ represents (real) division
These operators are applied from left to right at any one bracket level
subject to the fact that
5 + 2 * 3 = 11 (integer)
(5 + 2) * 3 = 21 (integer)
9.7 - 14.82 = -5.12 (real)
10 / 5= 2.0 (real)
7 + 8.4 / 2.1 * 2 = 15.0 (real)
PROGRAM Recta1(output);
BEGIN
writeln('A rectangle of length 3 cm and width 2 cm');
writeln('has area ', 3 * 2, ' sq cm')
END.
CONST
i1 = c1;
i2 = c2;
... ...
CONST
length = 3;
width = 2;
BEGIN
write('A rectangle of length ', length, ' cm');
writeln(' and width ', width, ' cm');
writeln(' has area ', length * width, ' sq cm')
END.
Apart from spacing and some minor modifications, this program produces
the same output as the previous version. But there are some
improvements:
If the field is too wide, the output is 'right-justified' and the field 'space-
filled' from the left.
write(parameter : fieldwidth)
or writeln(parameter : filedwidth)
*7bbbbbb423bbbb6
*bbbbbb49bbbbbFred
*b5.6
2.5 Variables
VAR
a1, a2, a3, ..., an : type1;
b1, b2, b3, ..., bm : type2;
... ... ... ... ...
For the present types are restricted to the types "integer" and "real". These
are said to be 'scalar' types and "integer" types are also known as 'ordinal'
type.
Integer variables are used for things which can only be whole numbers.
Real variables are used for things which may be fractional numbers.
Supplying data at run-time has the advantage that different runs of one
program utilize different data; there is no need to change the program.
2.6.1 'read'
VAR
agenow : integer;
BEGIN
write('How old are you? ');
readln(agenow);
writeln('After your next birthday you will be ', agenow+1)
END.
When this program is run nothing will happen until the user types an
integer. The program will then respond with the appropriate output.
2.6.2 'readln'
readln
readln(a, b, ..., z)
is equivalent to
The program
PROGRAM PetShop1 (input, output);
VAR
pet1, pet2, pet3, pet4 : integer;
BEGIN
writeln('Type the number in stock of each of your ',
'four species');
writeln(' - one per line');
readln(pet1);
readln(pet2);
readln(pet3);
readln(pet4);
writeln('Total number of pets in stock is ',
pet1 + pet2 + pet3 + pet4 : 1)
END.
accumulates the total stock in a pet shop which offers four different types
of pet. Each number is read from a different line and anything typed after
the number is ignored.
7 cats
4 dogs
2 birds
1 fish
Doing Arithmetic
v := e
where v is a variable,
e is an expression
and := is the 'assignment operator'
Expression e may include variables in the same way that in can include
constants.
VAR
pet1, pet2, pet3, pet4, totpets : integer;
BEGIN
writeln('Type the number in stock of each of your ',
'four species');
writeln(' - one per line');
readln(pet1);
readln(pet2);
readln(pet3);
readln(pet4);
totpets := pet1 + pet2 + pet3 + pet4;
writeln('Total number of pets in stock is ',
totpets :1)
END.
Also, a variable may appear on both the left hand side an the right hand
side of the same assignment statement.
Both of these points are illustrated in the following program which prints
a number and its three successors together with their squares and
reciprocals.
VAR
n: integer;
BEGIN
write('What is the starting value? ');
readln(n);
writeln;
writeln(' 2');
writeln(' n n 1 / n');
writeln(n :4, n * n :6, 1 / n :8:3);
n := n+1;
writeln(n :4, n * n :6, 1 / n :8:3);
n := n+1;
writeln(n :4, n * n :6, 1 / n :8:3);
n := n+1;
writeln(n :4, n * n :6, 1 / n :8:3)
END.
3.2 Arithmetic expressions
The two operators +, -, * and / are applicable to integer and real operands.
There are two operators which are applicable only to two integer operands
and each produces an integer result.
DIV and MOD have the same precedence as * and /; i.e., {* / DIV MOD}
are applied before {+ -}.
The first operand should be positive or zero and the second should be
positive.
15 DIV 7 = 2 15 MOD 7 = 1
7 DIV 15 = 0 7 MOD 15 = 7
6 DIV 6 = 1 6 MOD 6 = 0
The following program takes a 3-digit integer, introduced as a user
defined constant, and prints it backwards.
CONST
n = 472;
VAR
hundreds, tens, units : integer;
BEGIN
hundreds := n DIV 100;
tens := (n MOD 100) DIV 10;
units := n MOD 10;
writeln(n, ' reversed is ', units :1, tens :1, hundreds :1)
END.
There are six functions which are applicable to real and integer operands
'x' (called parameters) and each produces a real result.
PROGRAM Pi (output);
(* Compute the value of pi to the maximum accuracy *)
BEGIN
write('According to the computer the value of pi is ');
writeln(4 * arctan(1) :1:15)
END.
The expression
exp(b * ln(a))
There are two functions which can supply an integer or a real result,
depending upon the type of parameter supplied.
VAR
h, s1, s2, a1, a2 : real;
sin1, sin2, cos1, cos2, tan1, tan2 : real;
BEGIN
writeln;
writeln('The right-angled triangle is:');
writeln;
writeln(' ¦ \ ');
writeln(' ¦a1\ ');
writeln('s1 ¦ \ h');
writeln(' ¦ \ ');
writeln(' ¦ a2 \ ');
writeln(' --------- ');
writeln(' s2 ');
writeln;
write('Enter length of side s1 = ');
readln(s1);
write('Enter length of side s2 = ');
readln(s2);
(* Start Computations *)
(* Write results *)
writeln;
writeln('The hypotenuse is = ',h :1:4);
writeln;
writeln('The angle a1 is = ',a1 :1:4, ' radians');
writeln('The sine of a1 is = ',sin1 :1:4);
writeln('The cosine of a1 is = ',cos1 :1:4);
writeln('The tangent of a1 is = ',tan1 :1:4);
writeln;
writeln('The angle a2 is = ',a2 :1:4, ' radians');
writeln('The sine of a2 is = ',sin2 :1:4);
writeln('The cosine of a2 is = ',cos2 :1:4);
writeln('The tangent of a2 is = ',tan2 :1:4)
END.
Two functions which map a real value onto an integer are
round(7.4) = 7 trunc(7.4) = 7
round(-7.4) = -7 trunc(-7.4) = -7
round(7.5) = 8 trunc(7.5) = 7
round(-7.5) = -8 trunc(-7.5) = -7
round(7.6) = 8 trunc(7.6) = 7
round(-7.6) = -8 trunc(-7.6) = -7
Within the computer, integers are stored exactly but reals involve some
inherent error. This is because only certain number of significant figures
can be stored.
Being Choosy
4.1 If-statement
The if-statement exists in a full and a shortened form. The full form is
IF t THEN
s1
ELSE
s2
where t is a test
and s1 and s2 are any statements
When the statement is encountered at run-time the test t is made. If the test
holds then s1 is obeyed (and s2 is not); if the test does not hold then s2 is
obeyed (and s1 is not). I either case control then passes to the statement
next in sequence after the if-statement.
IF t THEN s
where t is a test
and s is any statement
VAR
n1, n2, n3, min : integer;
BEGIN
write ('Type three integers: ');
readln(n1, n2, n3);
IF n1 < n2 THEN
min := n1
ELSE
min := n2;
4.2 Case-statement
A case-statement provides a multi-way selection based on a range of
values. The usual form is
CASE e OF
v1 : s1;
v2 : s2;
...
vn ; sn
END (* CASE *)
The only ordinal type it has been met is "integer" so, for the present, "t"
must be integer.
At run-time, only one of the 'limbs' s1, s2, ..., sn will be obeyed.
The selector must evaluate to one of the supplied case labels; failure to do
so constitutes an error.
VAR
digit : integer;
BEGIN
write('Give me a digit ');
readln(digit);
write('This is ');
CASE digit OF
0 : writeln('zero');
1 : writeln('one');
2 : writeln('two');
3 : writeln('three');
4 : writeln('four');
5 : writeln('five');
6 : writeln('six');
7 : writeln('seven');
8 : writeln('eight');
9 : writeln('nine')
END (* CASE *);
END.
In the above program, it has been assumed that the cases listed are the
only possible ones.
Now assume that the number 23 is typed. This number is not a digit and,
when running the program, 23 in never encounter.
Pascal standard does not indicate what should happen if a value other than
those listed is encountered. For some compilers it will result in a run-time
error; for others, no statement is executed.
Some implementations of Pascal include, as a nonstandard extension, an
"else" case.
VAR
digit : integer;
BEGIN
write('Give me a digit ');
readln(digit);
write('This is ');
CASE digit OF
0 : writeln('zero');
1 : writeln('one');
2 : writeln('two');
3 : writeln('three');
4 : writeln('four');
5 : writeln('five');
6 : writeln('six');
7 : writeln('seven');
8 : writeln('eight');
9 : writeln('nine')
ELSE
writeln('no a digit')
END (* CASE *);
END.
One case limb may be prefixed by more than one case-label.
The next program illustrates this. This program converts number grades to
letter grades.
VAR
grade : integer;
BEGIN
write('Enter the numeric grade: ');
readln(grade);
write('The letter grade is ');
CASE grade DIV 10 OF
9, 10 : writeln('A');
8 : writeln('B');
7 : writeln('C');
6 : writeln('D');
0..5 : writeln('F')
ELSE
writeln('no recorded')
END (* CASE *)
END.
4.3 Compound statement
VAR
first, second, temp : integer;
BEGIN
write('Type two integer numbers: ');
readln(first, second);
IF first > second THEN
BEGIN
temp := first;
first := second;
second := temp;
END;
writeln('In order they are: ',first, ' ', second)
END.
4.4 Nested conditionals
IF ... THEN
...
ELSE
IF ... THEN
...
ELSE
...
IF ... THEN
...
ELSE
...
This form is illustrated in the following program
VAR
n : real;
BEGIN
write('Enter a real number : ');
readln(n);
IF n > 0 THEN
writeln('The number is positive')
ELSE
IF n < 0 THEN
writeln('The number is negative')
ELSE
writeln('The number is zero')
END.
IF t1 THEN
IF t2 THEN
s1
ELSE
s2
One, often the best, is to rewrite this section of program so that the
problem does not arise.
Two, is to use statement brackets to explicitly associate the ELSE with its
intended THEN. BEGIN and END may be used to enclose a single
statement. The earlier schema can be transformed into either
IF t1 THEN
BEGIN
IF t2 THEN
s1
END
ELSE
s2
IF t1 THEN
BEGIN
IF t2 THEN
s1
ELSE
s2
END
IF ... THEN
CASE ... OF
...
END (* CASE *)
ELSE
...
CHAPTER 5
Character by Character
A third scalar type is "char". It comprises all the characters available in the
set of characters used by the computer.
The most common sets are ASCII (American Standard Code for
Information Interchange) and EBCDIC (Extended Binary Coded Decimal
Interchange Code).
As with the real and integer types, it can be defined constant and variables
of type "char". Here are some character constant definitions:
CONST
space = ' ';
dot = '.';
zero = '0';
VAR
x : char;
Variable x can take as its value any character in the set available.
When a value is read into a character variable only one character (string of
length 1) is read from the input stream.
VAR
c1, c2, c3, c4 : char;
BEGIN
write('Please type a four-letter word: ');
readln(c1, c2, c3, c4);
writeln('Reversed, this is: ', c4, c3, c2, c1)
END.
The ASCII set form an ordered sequence - this is called the 'lexicographic'
order:
The first character has ordinal number 0, the second one ordinal number 1,
and so on.
Any data type whose values form a countable, ordered sequence is called
an 'ordinal' type.
That is why "integer" was described as an ordinal type (but "real" was
not). Thus characters can be used as case-statement selectors:
PROGRAM GiveName (input, output);
(* Prints one of four names given the initial *)
VAR
initial : char;
BEGIN
write ('What is your initial? : ');
readln(initial);
write('Hi ');
CASE initial OF
'B' : writeln('Brian');
'A' : writeln('Amanda');
'F' : writeln('Frank');
'C' : writeln('Christine')
END (* CASE *)
END.
Since the ASCII set is an ordered sequence, the relational operators can be
applied to any to operands of (the same) ordinal type.
are true.
Be clear in mind of the difference between the characters '0', '1', ..., '9' and
the integers 0, 1, ..., 9.
For example
VAR
ch : char;
BEGIN
write('Give me a character: ');
readln(ch);
writeln('Five characters centred on ', ch, ' are ',
pred(pred(ch)), pred(ch), ch,
succ(ch), succ(succ(ch)) )
END.
Two functions map between characters and their ordinal numbers. These
ones are
ord(xx) - ord('a') + 1
and the letter at position "yy" in the alphabet (if "yy" is an integer variable
with a value in the range 1 to 26 is given by
chr(ord('a') + n -1)
The functions "ord(x)", "succ", and "pred" can be applied to items of any
ordinal type.
The two identifiers "input" and "output", used in the program heading, are
the names of the 'standard' text files, one to be used for reading and one
for writing.
In both cases the procedure "reset" can be applied to the file several times
during the execution of a program and, each time, the file concerned is
initialized for reading from the beginning.
The file "g" need no to exist before the program is run. If it does exist, it
will be overwritten; if it does not, and empty file "g" will be automatically
created when the program is about to be run.
and two characters would be written to a text file "g" by a statement of the
form
This new program reads the four-letter word from a file, say
"inrever4.$$$", and produces the reversed copy in another file, say
"outreve4.$$$".
PROGRAM Reverse4 (infile, outfile);
VAR
infile, outfile : text;
c1, c2, c3, c4 : char;
BEGIN
assign(infile, 'inrever4.$$$');
reset(infile);
readln(infile, c1, c2, c3, c4);
close(infile);
assign(outfile, 'outreve4.$$$');
rewrite(outfile);
writeln(outfile, 'Reversed word: ', c4, c3, c2, c1);
close(outfile)
END.
CHAPTER 6
6.1 Loops
Computers are often wanted to repeat some process several times. When a
program obeys a group of statements several times, it is said to be
'looping'.
6.2 'For-statement'
FOR v := e1 TO e2 DO
s
and its new value is compared with the value of e2. Thus, in some sense, v
is a control variable of the number of loops or repetitions.
5. If e2 < e1, the loop body s is not obeyed at all; otherwise the body is
executed a number of times equal to
ord(e2) - ord(e1) + 1
FOR v := e1 DOWNTO e2 DO
s
If e1 < e2 the loop body s is not obeyed at all; otherwise the loop body is
obeyed a number of times equal to
ord(e1) - ord(e2) + 1
For each successive iteration of the loop body the control variable, v,
takes successive values
PROGRAM Alphabet(output);
VAR
xx : char;
BEGIN
FOR xx := 'a' TO 'z' DO
write(xx);
writeln;
The following program raises two numbers to a specified power and the
control variable merely governs the number of iterations.
In this program it is also shown that a loop body may comprise several
statements if they are bracketed to form a compound statement.
VAR
x, xx, y, yy : real;
n, power : integer;
BEGIN
write('Please give me two numbers: ');
readln(x, y);
write('To what power would you like it raised? ');
readln(n);
xx := 1;
yy := 1;
(* Start computations *)
FOR power := 1 TO n DO
BEGIN
xx := xx * x;
yy := yy * y
END;
writeln(x:1:4, ' raised to the power ', n:1, ' is ', xx :9:4);
writeln(y:1:4, ' raised to the power ', n:1, ' is ', yy :9:4)
END.
When one loop occurs within the body of another, the loops are said to be
'nested'.
CONST
max = 10;
VAR
f : text;
i, j, n : integer;
BEGIN
write('Input the number of the maximum multiplication
table: ');
readln(n);
assign(f, 'MULTIPLI.$$$');
rewrite(f);
writeln(f, 'MULTIPLICATION TABLES UP TO ', n:1);
FOR i := 1 TO n DO
BEGIN
writeln(f);
writeln(f, 'TABLE OF ', i :2);
writeln(f);
FOR j := 1 TO max DO
writeln(f, i :2, ' * ', j :2, ' = ', i*j :3)
END;
close(f)
END.
6.3 While-statement
Pascal provides two non-deterministic loops: a while-statement and a
repeat-statement.
WHILE t DO s
where t is a test
and s is any statement
The test (t) is made 'prior' to each execution of the loop body (s).
If the test proves false, control leaves the while-statement and passes to
the next in sequence after the while-statement.
If the test holds true, the loop is obeyed and the process repeated until the
test eventually proves false.
If test is false upon first entry, the loop body is not entered at all.
The loop body (s) may be composed of either one or several statements. In
the last case, it must be bracketed to form a compound statement.
If the first step is omitted, the initial test of the loop control-variable will
be meaningless. If the last step is omitted, the loop control variable value
cannot change and the loop will execute "forever".
The above facts are illustrated in the following program which finds and
prints the time required to double a given amount of money.
PROGRAM Banker(input, output);
VAR
year : integer;
depos, balanc, rate, intrst, double : real;
BEGIN
write('Enter the deposit amount : ');
readln(depos);
write('Enter the interest rate as a decimal fraction: ');
readln(rate);
year := 0;
balanc := depos;
double := 2 * depos;
Consider the following while-loop used to find the sum of the first "n"
integers, and the respective for-loop
WHILE-LOOP FOR-LOOP
sum := 0; sum := 0;
nxtint := 1; FOR nxtint := 1 TO n DO
WHILE nxtint <= n DO sum := sum + nxtint;
BEGIN
sum := sum + nxtint;
nxtint := nxtint + 1
END;
The most obvious difference between the loops is that the while-loop is
longer.
The for-loop is easier to write and should be used when the number of
loop repetitions need can be determined before loop entry.
The main reason for the extra length of the while-loop involves the
manner in which the loop-control variable "nxtint" is manipulated:
Although these three steps are implicit in the for-loop, they must be
specified explicitly when the while-loop is used.
If the loop-control variable is not initialised properly before the while-
statement is reached, the loop-repetition test will be meaningless.
If the loop control variable is not updated, the loop-repetition test will
always be true and the loop will not be exited (infinite loop).
6.5 Repeat-statement
REPEAT
s1;
s2;
...
sn;
UNTIL t
where t is a test
and s1, s2, ..., sn are any statements
The test (t) is made 'after' each execution of the loop body (s1, s2, ..., sn).
If the test holds true, the loop is terminated and control passes to the
statement next in sequence after the repeat-statement.
If the test proves false, control returns to the start of the loop body and the
whole process is repeated until the test eventually holds true.
Once the loop is under way, a while-loop and a repeat-loop are equivalent.
The difference is upon the first entry.
With WHILE, the test is made 'before' the first execution of the loop body;
with REPEAT, the test is made 'after' the first execution.
The body of a repeat-loop is obeyed at least once
More than one statement can be included within the body of a repeat-loop
without being bracketed between BEGIN and END.
The above facts are illustrated in the following program which computes
the smallest Fibonacci number greater than some specified bound.
The first two terms of the Fibonacci sequence are 0 and 1. Each
successive term is the sum of the previous two.
The program insists that the bound be greater than 1 and it must therefore
be computed 'at least one' new term. So REPEAT must be used.
PROGRAM Minfib (input, output);
VAR
bound, term1, term2, term3 : integer;
BEGIN
write('Specify the bound: ');
readln(bound);
IF bound < 1 THEN
writeln(' *** bound is too small ***')
ELSE
BEGIN
term3 := 1;
term2 := 0;
REPEAT
term1 := term2;
term2 := term3;
term3 := term2 + term1
UNTIL term3 > bound;
writeln('Smallest Fibonacci number greater',
' than ', bound :1, ' is ', term3 :1)
END
END.
CHAPTER 7
True or False?
Boolean data types are those which can only take values "true" or 'false".
These are called 'Boolean values'.
The two values ("true" and "false") applied to Boolean data types for an
ordered set where "false" precedes to "true". "false" has ordinal number 0
and "true" has ordinal number 1. Consequently
Boolean values can be written to a text file but not read from one.
CASE t OF
true : s1;
false : s2
END (* CASE *)
is equivalent to
IF t THEN s1 ELSE s2
7.3 Boolean constants
A user-defined constant may have type Boolean.
For example, if "const1" and "const2" are two constants taken values
"true" and "false", respectively, then they are declared as:
CONST
const1 = true;
const2 = false;
A Boolean variable can take either of the two values "true" and "false" and
can acquire one of these values directly
VAR
b1, b2 : boolean;
...
b1 := true;
b2 := false;
VAR
negative, posdisc, factorfound,
usersaysno, dhasreachedn : boolean;
...
negative := digit < 0;
posdisc := disc > 0;
factorfound := n MOD d = 0;
usersaysno := reply = 'n';
dhasreachedn := d = n
In the following program is applied these facts. This program prints two
supplied three-letter words in alphabetical order.
VAR
a1, a2, a3, b1, b2, b3 : char;
ab : boolean;
BEGIN
writeln('Type two three-letter words, one per line:');
readln(a1, a2, a3);
readln(b1, b2, b3);
CASE ab OF
true : writeln(a1, a2, a3, ' ', b1, b2, b3);
false : writeln(b1, b2, b3, ' ', a1, a2, a3)
END (* CASE *)
END.
VAR
f1, f2 : text;
ch : char;
licount, chcount : integer;
BEGIN
writeln;
writeln('COPYING "FILE1.$$$" to "FILE2.$$$" ...');
assign(f1, 'FILE1.$$$');
assign(f2, 'FILE2.$$$');
reset(f1);
rewrite(f2);
licount := 0;
chcount := 0;
(* Start copy *)
REPEAT
REPEAT
(* Counting characters *)
chcount := chcount + 1;
read(f1, ch);
write(f2, ch)
UNTIL eoln(f1);
(* Counting lines *)
licount := licount + 1;
UNTIL eof(f1);
(* Display results *)
writeln('COPY FINISHED');
write('The number of lines is');
IF odd(licount) THEN
writeln(' odd and equals ', licount:1)
ELSE
writeln(' even and equals ', licount:1);
(* Close files *)
close(f1);
close(f2)
END.
7.6 Boolean operators
NOT
If "b" has the value "true" then "NOT b" is "false"; if "b" has the value
"false then "NOT b" is "true".
AND
OR
OR { same precedence as + - }
Square brackets, [ and ], are used as 'set constructors' and members are
separated by commas.
All members of a set must have the same type, and this must be an ordinal
type (and, hence, not "real"). This is called the base type of the set.
can be written
is the set
IN
The right hand operand must be a set and the left hand operand must be an
expression whose type is the same as the base type of the set. The operator
yields "true" only if the value of the left hand operand is currently a
member of the right hand set.
For example the best way to check that an integer is in the range 1 to 9 is
with a set:
One final note: sets are 'implementation dependent'. Both the maximum
size of a set and the range of ordinal numbers that set members may
possess vary from one computer to another.
CHAPTER 8
A Matter of Routine
Some standard procedures have already been found (write, writeln, read,
readln, etc), as well as some functions (sin, cos, sqrt, odd, etc).
Routines must be declared between the variable declarations (if there are any)
and the BEGIN of the program body.
8.2 Procedures
PROCEDURE p;
BEGIN
s1; s2; ...; sn
END (* p *);
The procedure can be "called" from the main program by simply quoting its
name. This gives the "procedure call statement". When a procedure is called,
the statements of the procedure body are obeyed and the control returns to the
statement following the call.
The complete program might have the following structure, where the actions
are declared as procedures:
PROGRAM Copyfilp (f1, f2);
VAR
f1, f2 : text;
ch : char;
licount, chcount : integer;
(* ***************************************************** *)
PROCEDURE Inifiles;
BEGIN
assign(f1, 'FILE1.$$$');
assign(f2, 'FILE2.$$$');
reset(f1);
rewrite(f2)
END; (* initialization of files *)
(* ***************************************************** *)
PROCEDURE Inilicha;
BEGIN
licount := 0;
chcount := 0
END; (* initialization of counters *)
(* ***************************************************** *)
PROCEDURE Copychar;
BEGIN
REPEAT
(* Counting characters *)
chcount := chcount + 1;
read(f1, ch);
write(f2, ch)
UNTIL eoln(f1)
END; (* copy of characters *)
(* ***************************************************** *)
PROCEDURE Copyline;
BEGIN
REPEAT
copychar;
licount := licount +1
UNTIL eof(f1)
END; (* copy each line *)
(* ***************************************************** *)
PROCEDURE Copyfile;
BEGIN
copyline
END; (* copy of lines *)
(* ***************************************************** *)
PROCEDURE Dispresu;
(* Display results *)
BEGIN
writeln('COPY FINISHED');
write('The number of lines is');
IF odd(licount) THEN
writeln(' odd and equals ', licount:1)
ELSE
writeln(' even and equals ', licount:1);
write('The number of characters is');
IF odd(chcount) THEN
writeln(' odd and equals ', chcount:1)
ELSE
writeln(' even and equals', chcount:1)
END; (* display results *)
(* ***************************************************** *)
PROCEDURE Clofiles;
(* Close files *)
BEGIN
close(f1);
close(f2)
END; (* close files *)
(* ***************************************************** *)
Notice in this program that one procedure may call another. The only
restriction is that the declaration of a procedure must precede its calls.
A procedure may even call itself. It is then said to display "recursion" but this is
beyond the scope of the present lecture notes.
8.3 Localized information
It have been seen that a program can contain declarations specifying entities
which may be used by procedures which are declared within the program and
by statements of the program body.
The same applies to procedures. A procedure declaration may contain its own
declarations.
Any entity declared within a procedure may be used by any procedure declared
within the procedure and by statements of the procedure body.
Declarations within a procedure appear between the PROCEDURE line and the
BEGIN of the procedure body and are subject to the same rules of order as in
the main program.
CONST
k = 10; (* this is a global constant *)
VAR
ch : char; (* this is a global variable *)
(* ***************************************************** *)
PROCEDURE Writchar;
CONST
m = 5; (* this a local constant *)
VAR
i, km : integer; (* these are local variables *)
BEGIN
km := k - m;
writeln('The character ', ch,' repeated ', k-m,' times is:');
FOR i := 1 TO km DO
writeln(ch)
END;
(* ***************************************************** *)
8.4 Functions
The fundamental difference between a function and a procedure is that a
function call constitutes an "expression" because a function "delivers" a "result"
whereas a procedure call constitutes a "statement" and no value is associated
with the call.
A function is a suitable form for a routine when one is interested in only one
value computed by the routine and the routine produces no "side effects".
In Pascal, a function may deliver a result of any ordinal type (boolean, char,
integer), of type real, on of any other type defined by the user (these are defined
in future chapters).
(* ********************************************* *)
VAR
xsquared, p : real;
power : integer;
BEGIN
If n = 0 THEN
xtothen = 1
ELSE
BEGIN
xsquared := sqr (x)
IF odd (n) THEN
p := x
ELSE
p := 1;
FOR power := 1 TO n DIV 2 DO
p := p * xsquared;
xtothen := p
END
END (* to then n *) ;
(* ********************************************* *)
In order to give more examples illustrating the use of functions, consider the
following two programs
VAR
age : integer;
(* **************************************************** *)
BEGIN
CASE age DIV 5 OF
3: groupforage := 'A';
4, 5: groupforage := 'B';
6..9: groupforage := 'C';
10..12: groupforage := 'D'
ELSE
groupforage := 'F
END; (* case *)
END; (* group for age *)
(* **************************************************** *)
VAR
a1, a2, a3, b1, b2, b3 : char;
(* ************************************************** *)
BEGIN
IF a1 < b1 THEN
abinorder := true
ELSE
IF a1 > b1 THEN
abinorder := false
ELSE
IF a2 < b2 THEN
abinorder := true
ELSE
IF a2 > b2 THEN
abinorder := false
ELSE
abinorder := a3 <= b3
END; (* a b in order *)
(* ************************************************** *)
Routine Information
VAR
a, b, eo : boolean;
inta, intb : integer;
(* ********************************************** *)
BEGIN
CASE booleanvalue OF
true : write ('YES');
false: write ('NOT')
END (* CASE *)
END; (* Yesno *)
(* ********************************************** *)
BEGIN (* Main program *)
REPEAT
write ('Enter two integer values, 0 is no: ');
readln (inta, intb);
a := true;
IF inta = 0 THEN
a := false;
b := true;
IF intb = 0 THEN
b := false;
VAR
test : integer;
(* ********************************************** *)
BEGIN
number := number * number * number;
writeln ('The cube of the number is: ', number)
END; (* Cube *)
(* ********************************************** *)
The cube of 3, which is 27, is given when the program is run with 3 is given as
input, but when the procedure has finished the value of "test" is still 3.
Therefore, if a procedure modifies a value parameter then only its own
temporary copy is modified.
The above program has modified its own local copy, called "number", but
"test" has not been modified.
VAR
test : integer;
(* ********************************************** *)
BEGIN
number := number * number * number;
writeln ('The cube of the numbers is: ', number);
END;
(* ********************************************** *)
The reserved word "VAR" in the list of parameters specifies that "number" is a
variable parameter.
When the procedure modifies "number", the variable "test" is also modified.
This is an important difference.
Here x is a real value parameter. The other ones are variable parameters.
For the case of functions, these may take parameters, they are always value
parameters.
VAR
x, y : real;
m, n : integer;
(* ********************************************* *)
VAR
i : integer;
p, xsquared : real;
BEGIN
IF n = 1 THEN
powered := x
ELSE
BEGIN
xsquared := sqr (x);
IF odd (n) THEN
p := x * xsquared
ELSE
p := xsquared;
FOR i := 2 TO n DIV 2 DO
p := p * xsquared;
powered := p
END
END; (* powered *)
(* ********************************************* *)
It was stated at the end of section 8.2 that the declaration of a procedure must
precede its calls. Pascal provides a relaxation of this rule: A "routine heading"
must be declared before the routine is called but its "body" may be declared
later (but in the same block of procedures). The declaration of the heading
takes the form of a "forward reference". The routine heading is presented but
its body is replaced by
forward;
In order to illustrate the above remarks, suppose procedures A and B are given
as shown next:
END; (* A *)
Since A is defined first, it can be called from B., however, B may not be called
from A. According to the remarks given in order to make B callable from A,
two changes must be made in the procedures as written:
I) The heading line of procedure B, with the reserved word "forward" and a
semicolon appended, is written before the definition of procedure A.
II) The other change is in the actual heading line that accompanies procedure
B; it is simple written
PROCEDURE B;
END; (* A *)
PROCEDURE B;
BEGIN (* B *)
END; (* B *)
CHAPTER 10
Give it a Name
In the preceding chapters it has been studied "real"; "integer", "boolean" and
"char" types.
The types "real", "integer" and "char" can be written to and read from a text
file.
Boolean types can be written to a text file but not read from one.
"Integer", "boolean" and "char" types form an ordered set. This means that they
can be used for selection in a case-statement or as an index in a for-loop.
For any ordered type the following functions are well defined:
For example:
succ (3) = 4;
pred ('q') = 'p'
succ (false) = true;
succ (true) gives an error
A series of type definitions may appear between the constant declarations (if
there are any) and the variable declarations (if there are any), heralded by the
reserved word TYPE. Thus a "type definition" has the form.
TYPE
i = t;
where i is an identifier
and t is a type.
A variable of ordinal type, boolean, char, integer and symbolic (this will be
studied in the next section) can be restricted to a subrange. The variable is then
said to have a subrange type but inherits all the properties of its "host" type.
Any attempt to give a subrange variable a value outside its permitted range
constitutes an error. Notice that subranges or type "real" are not allowed.
A subrange type is denoted by the upper and lower bounds separated by two
dots. These bounds must be constants and the ordinal number of the lower
bound must not exceed the ordinal number of the appear bound.
1.. maxint
'A'..'Z'
-1..17
Subrange types allow the user to check the sensible use of variables. From the
"problem domain" the user decides what range of values should be sensible for
each variable and specify this range in the declaration of the variable. Any
attempt to assign a value outside the expected range will be prevented.
Using subranges the user helps the computer to detect his or her mistakes.
"Minimal subranging" should always be the aim.
As examples, consider the subranges that should have been used in some
previous examples.
CONST
maxage = 120;
VAR
agenow: 0..maxage;
II) For any practical box, the length of each side must exceed 0:
VAR
length, width, depth: 1..maxint;
III) In the program which asks for initials A,B,C, or F the minimal subrange is
A to F:
VAR
initial: 'A'..'F'
TYPE
digits = 0..9;
VAR
digit : digits
V) Within a function which raises a real number to a positive power "n", the
parameter "n" cannot be negative and so should be constrained to the natural
numbers:
TYPE
naturals = 0..maxint;
VAR
m,n: naturals;
VAR
d: 0..9;
dtyped: integer;
REPEAT
write ('please type a digit ' );
readln (dtyped)
UNTIL dtyped IN [0..9];
d: = dtyped
Of course, even this is not completely safe because an execution error will
result if anything other than an integer is typed.
TYPE
rainbow = (red, orange, yellow, green, blue, violet);
Where the type rainbow has six given values. In this example:
ord (red) = 0
ord (orange) = succ (red) = 1
Variables of type "rainbow" can be created:
VAR
pallet: rainbow;
is opposite to function
As it was said, function "ord" can be used for symbolic types, however there is
not opposite to it in symbolic types. This program shows how to construct the
opposite to "ord" for symbolic types: unord (integer) must be the opposite to
ord (month).
PROGRAM Months (output);
(* Shows the conversion of elements of symbolic type: an integer is
transformed to a month and the month is displayed *)
TYPE
month = (jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov,
dec);
numonth = 1..12;
VAR
testmonth : month;
(* ********************************************** *)
PROCEDURE Givemonth (Thismonth : month);
(* Displays the full month name *)
BEGIN
writeln;
write ('This month is ');
CASE thismonth OF
Jan : writeln (' January ');
Feb : writeln (' February ');
Mar : writeln (' March ');
Apr : writeln (' April ');
May : writeln (' May ');
Jun : writeln (' June ' );
Jul : writeln (' July ');
Aug : writeln (' August ');
Sep : writeln (' September ');
Oct : writeln (' October ');
Nov : writeln (' November ');
Dec : writeln (' December ');
ELSE
writeln('not a month')
END; (* CASE *)
writeln
END;
(* ********************************************** *)
FUNCTION Ordmonth (imonth : numonth): month;
(* Converts an ordered integer to a month type *)
VAR
domonth : month;
index : numonth;
BEGIN
domonth := jan;
FOR index := 2 To imonth DO
domonth := succ(domonth);
ordmonth := domonth
END;
(* ********************************************** *)
BEGIN
writeln;
write ('Enter the number 1..12 of a month: ');
readln (imonth);
Thismonth := ordmonth (imonth)
END;
(* ********************************************** *)
Subranges of symbolic types can be defined, for example with the type
"month":
TYPE
month = (jan, feb, mar, apr, may, jun, jul, aug, sep, oct,
nov, dec);
Subranges are created inside the "type" declaration itself, or in the "type"
declaration of a contained block.
File it
The files used in Pascal programs up to this point have been "text files", whose
components are characters and these characters are organized into lines.
The predefined file type "text" is a standard type identifier used to declare text
files. The standard system files "input" and "output" associated with the
standard input (keyboard) and output (screen) devices are examples of text
files, and in Chapter 5. user-defined text files were described. The predefined
procedures "readln", "writeln", and "eoln" may be used only with text files.
Pascal also supports nontext files, whose components may be of any type,
simple or structured, except that they may not be of file type. Although
attention in this section is restricted to text files, much of the discussion also
applies to the other types of files considered in subsequent sections.
The principal rules governing the use of text files in Pascal programs as
discussed in Chapter 5 may be summarized as follows:
4. Opening files for input. Each file from which data is read must first be
opened for input with the predefined procedure "reset" in a statement of the
form.
reset (file-variable);
Each such procedure call results the data pointer to the beginning of
the specified file. (The standard system file "input" need not be opened
for input.)
5. Each file to which data values are to be written must first be opened
for output. For text files, this can be done by using the predefined
procedure "rewrite" in a statement of the form.
rewrite (file-variable);
6. File input: Information can be read from a text file by using the
predefined procedures read and readln in the forms
close (file-variable)
While text files are frequently used in programming applications, "nontext file"
are sometimes more convenient.
Data written to a nontext file are transcribed, bit by bit, in exactly the same
form that they have within the computer. This has several advantages over text
files.
Only characters, integers, and real numbers may be read from a text file; it can
be printed only these three types and boolean variables. However, anything that
can be represented within the computer can be written to or read from a nontext
file.
Nontext files have some disadvantages, too. The cannot be printed because
they are not in a printable (i.e., character) form. Similarly, they cannot be
created by an editor as a text file is. There are also certain restrictions on the
reading and writing that will be considered later in this section.
The above disadvantages suggest the uses for nontext files. It might no want to
have the output printed or displayed on the screen when the output is simply
used as the input for another (or the same) program: As already seen in Chapter
2 the output of the compiler is the input for the loader. Such output is not given
in a readable (that is, readable by humans) form.
Now let consider their declaration and use. In order to declare such a file, it is
used
VAR
filename: file of type;
or alternatively,
TYPE
typename = file of type;
VAR
filename: typename;
The "type" here can be almost any type: the simple types, arrays (chapters 12
and 13), or record (chapter 14) types. The only restriction is that it may not be
a file type or a record type with a file type component.
TYPE
file1 = file of integer;
file2 = file of char;
file3 = file of boolean;
VAR
f1 : file1;
f2 : file2;
f3 : file3;
While the types "text" and "file of char" might appear to be equivalent, there
are significant differences. The declaration
VAR
FileA : file of char;
does not declare FileA to be a text file; it is imply a nontext file containing only
characters. It is nor organized into lines: so we cannot use readln, writeln, on
eoln. Furthermore, a write statement will not convert numeric or boolean
values into strings of characters; nor will a read statement convert a string of
numeric character into an integer or real value. If it is given the command
READ
(FileA, x) or write (FileA, x)
VAR
data: FILE OF real;
value, square1, square2, root1, root2 : real;
count : integer;
BEGIN
assign(data, 'data.$$$');
rewrite(data);
FOR count := 1 TO 10 DO
BEGIN
value := count;
square1 := sqr(value);
root1 := sqrt(value);
write( data, value, square1, root1)
END;
reset(data);
WHILE NOT eof(data) DO
BEGIN
read(data, value, square2, root2);
writeln(value :6:2, square2 :8:2, root2 :6:2)
END;
readln
END.
CHAPTER 12
Line up
So far, real and integer variables have been used for representing just one value
reach one. However there are a lot of situations for which a program must have
a list of variables of the same type represented by one only identifier.
identifier [expression]
The identifier is subject to the normal restrictions of identifiers; in particular,
there may be no space within it. Nevertheless, there may be one or more spaces
between the identifier and the left bracket, between the left bracket and the
expression, or between the expression and the right bracket.
The variables used above may be declared by (if they are of integer type)
VAR
x: ARRAY [1..100] OF integer
TYPE
arraytype = ARRAY [1..100] OF integer;
VAR
x: arraytype;
Pascal requires named, rather than anonymous, types when passing arrays as
parameters.
i = 3, j = 2
Then
a[1] = a[3] = 3,
It is this evaluation of the subscript that makes arrays so useful. With the added
facility of arrays the problem of reading a list of numbers and writing it in
reverse order is quite simply. This is show for a list of exactly 10 numbers in
the following program.
TYPE
numarraytype = ARRAY [1..10] OF integer;
VAR
num : numarraytype;
index : integer;
BEGIN
writeln ('Give a list of 10 integers: ');
FOR index :=1 TO 10 DO
read (num[index]);
TYPE
realarray = ARRAY [1..25] OF real;
VAR
a,b: realarray;
Then
a: = b
is a valid assignment.
TYPE
arraytype = ARRAY[1..25] OF real;
VAR
a,b : arraytype;
VAR
c: arraytype;
Then the procedure P may be called by P (a) or P(b). When passing an entire
array, both the formal parameter and the actual parameter must be declared
using the same "named" type.
TYPE
demoray = ARRAY [1..4] OF integer;
VAR
one, two : demoray;
max, index : integer;
(* ********************************************** *)
(* An array is input *)
VAR
i : integer;
BEGIN
writeln ('Input 4 values for an array: ');
FOR i :=1 TO 4 DO
read (inarray [i]);
writeln
END;
(* ********************************************** *)
VAR
i:integer;
BEGIN
value := sweeparray[1];
position := 1;
FOR i := 2 TO 4 DO
IF Sweeparray[i] > value THEN
BEGIN
value := Sweeparray[i];
position := i
END;
END;
(* ********************************************** *)
On the other hand, Pascal does not permit the following procedure or function
heading:
12.2. Sorting
The method begins searching for in the array the lowest number and
exchanging it with the first element of the array. The lowest number will now
at the top of the list.
As a second step, the lowest number of the remaining n-1 numbers is going to
be searched and it will be exchanged with the second element of the array. The
second lowest number will be now the second in the list.
Continuing with this process, it will be searched for the lowest number among
the remaining n-2 numbers and it will be exchanged with the third element in
the array, and so on until all of the array be sorted.
It will be required a total of n-1 steps for sorting the array, but the length of
each search will be diminished at each step.
In order to find the lowest number at each step, each number x[i] in the array
will be sequentially compared to a starting number x[loc], where "loc" is an
integer variable used to "mark" one of the elements of the array.
If x[i] is lower than x[loc], both numbers are exchanged themselves, if not they
stay at their original places.
Once the above method has been applied to the complete array, the first
number will be the lowest one. Continuing with the above method, the process
is repeated n-2 times, until complete a total of n-1 steps (loc =1, 2,...,n-1).
The only question to be answered is how to exchange two numbers. Firstly, the
value of x[loc]. is reserved for future reference. After that the actual value of
x[i] is assigned to x[loc]. Finally, the "original value" of x[loc], which has been
previously reserved, is assigned to x[i]; the exchange of numbers has been
completed.
BEGIN
FOR loc := 1 TO n-1 DO
FOR i := loc + 1 TO n DO
IF x[i] < x [loc] THEN
BEGIN
temp := x[loc];
x[loc] := x[i];
x[i] := temp
END
END;
In the above procedure is assumed that "loc", "i" and "n" are integer variables
in the range 1 to 100. It is also assumed that "temp" is a real variable used to
temporarily storage x[loc]. Notice that the procedure uses nested for-loops.
VAR
n, i, loc : 1..100;
x : ARRAY [1..100] OF real;
temp : real;
(* ********************************************** *)
PROCEDURE Exchange;
BEGIN
FOR loc := 1 TO n-1 DO
FOR i := loc + 1 TO n DO
IF x[i] < x[loc] THEN
BEGIN
temp := x[loc];
x[loc] := x[i];
x [i] := temp
END
END; (* Exchange *)
(* ********************************************** *)
It has been probably though of an string as an array of type "char". This is true
with two exceptions:
VAR
stringname : STRING[length];
TYPE
stringtype = STRING[length];
VAR
stringname : stringtype;
Pascal stores string data a little differently than integers or reals. Strings have
two parts:
With the storing of integers and reals it is used an analogy of a box inside the
computer.
With the storing of strings, think of a series of adjacent boxes. The first box
stores the number of characters in the string and is called the "length byte". The
remaining boxes store the characters of the string (one character per box).
String variables can hold strings as long as 255 characters. This should be more
than ample for most applications.
Obviously the "length byte" can be computed using function "ord" in the
following way".
length (stringname);
This current length consists only of the number of characters in the string. It
does not include the length byte.
The following program illustrates the above remarks and how a string can be
treated as an array. The last "writeln" shows how it is usually displayed an
string.
PROGRAM Strarray (input, output);
TYPE
familyname = STRING[30];
VAR
family : familyname;
i : integer;
BEGIN
write('Enter a string : ');
readln(family);
writeln;
writeln('The length byte is ', ORD(family[0]));
writeln;
FOR i := 1 TO length(family) DO
write(family[i]);
writeln(' ':8, 'This is as an array of char');
writeln;
writeln(family, ' ':8, 'This is as a string variable');
readln;
END.
CONST
space = ' ';
name = 'B A Head';
date = '01/09/93';
taxrate = 0.40;
max = 65;
VAR
i : integer;
hours, rate : real;
grosspay, taxes, netpay : real;
BEGIN
writeln;
write('Input the hours worked: ');
readln(hours);
write('Input the rate per hour: ');
readln(rate);
writeln;
(* Compute the pay *)
writeln;
FOR i := 1 TO max DO
write('*');
writeln;
writeln(space : 40, 'Date: ', date);
writeln;
writeln('Pay to the Order of: ', name);
writeln;
writeln('Pay the full amount of: $', netpay : 10:2);
writeln(space : 25,'----------');
writeln;
writeln(space : 40,'-----------------------');
writeln(space : 40,'Dan Chambers, Treasurer');
writeln;
FOR i := 1 TO max DO
write('*');
readln
END.
12.4 String functions
There are several string functions that manipulate strings. It has been
previously seen one of such a functions. That is the "length(x) which returns
the length (the number of characters) of the string variable, constant, or
expression inside its parentheses.
The length-function is useful to test whether a string variable has data (to see
whether the user typed anything before pressing Enter) with the following
section code:
Another useful function is the "pos-function". This function search for a "char"
or substring within another string. It returns the index of the string where the
substring was found.
pos (x,y)
where x is the "char" or substring wanted to find.
y is the string wanted to search.
For example
Notice that the second example returns 3 and not 6 pos-function finds the first
match and stops. Because "xyz" is not in the search string, pos-function returns
0 for the last "writeln".
copy (x,y,z)
Copy-function can pull any number of characters from anywhere in the string.
The following example shows how the copy-function works:
Turbo Pascal
FORTRAN
COBOL
C
BASIC
This is only a test. If this had been an actual emergency, you would
have been instructed...
VAR
arrayname : ARRAY [indextype1, indextype2,...,
indextype3] OF type
The index type could be simple ordinal types or subranges. It does not have to
be all of them of the same type. On the other hand, the elements of the array
must be always of the same type, including structured types.
VAR
table : ARRAY [1..60, 1..150] OF real;
TYPE
index1 = 1..60;
index2 = 1..150;
VAR
table: ARRAY [index1, index2] OF real;
Another possibility is:
CONST
limit1 = 60;
limit2 = 150;
TYPE
index1 = 1..limit1;
index2 = 1..limit2;
VAR
table : ARRAY [index1, index2] OF real;
Notice that both indexes in the definition are subranges of integer type, but the
elements of the array are of real type.
VAR
row, col : 1..11;
nrows, ncols : 1..10;
table : ARRAY[1..11,1..11] OF real;
(* ************************************ *)
PROCEDURE Sumsrows;
BEGIN
FOR row := 1 TO nrows DO
BEGIN
table[row,ncols+1] := 0;
FOR col := 1 TO ncols DO
table[row,ncols+1] := table[row,ncols+1] +
table[row,col]
END
END; (* sum rows *)
(* ************************************ *)
PROCEDURE Sumscols;
BEGIN
FOR col := 1 to ncols DO
BEGIN
table[nrows+1,col] := 0;
FOR row := 1 to nrows DO
table[nrows+1,col] := table[nrows+1,col] +
table[row,col]
END
END; (* sum columns *)
(* ************************************ *)
PROCEDURE Readdata;
BEGIN
write('How many rows (1..10)? : ');
readln(nrows);
writeln;
write('How many columns (1..10)? : ');
readln(ncols);
writeln;
FOR row := 1 TO nrows DO
BEGIN
writeln('Enter data for row number ', row:2, ' : ');
FOR col := 1 TO ncols DO
read(table[row,col]);
writeln
END
END; (* Read data *)
(* ************************************ *)
PROCEDURE Results;
BEGIN
writeln('Original table, with sum of rows and columns: ');
writeln;
FOR row := 1 TO nrows + 1 DO
BEGIN
FOR col := 1 TO ncols + 1 DO
write(table[row,col]:6:1);
writeln
END
END; (* Results *)
(* ************************************ *)
TYPE
color = (red, white, yellow, green);
index = 1..100;
VAR
test: ARRAY [color, index] OF boolean
Since "test" is a boolean array, the assigned values to the elements of the array
will be boolean; i.e., they will be "false" or "true".
As it was said before, an array can be of any type, including of structured type.
Therefore it is possible to define a one-dimensional array whose elements be
one-dimensional arrays (all of them of the same type). Such a definition is
equivalent to define a two-dimensional array.
VAR
test: ARRAY [1..25] OF ARRAY [1..50] OF char;
is equivalent to
VAR
test : ARRAY [1..25, 1..50] OF char;