home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
modula2
/
mod2txt.arc
/
CHAP11.TXT
< prev
next >
Wrap
Text File
|
1987-03-25
|
20KB
|
454 lines
CHAPTER 11 - Records
PREREQUISITES FOR THIS MATERIAL
In order to do a profitable study of this material, you
will need a good understanding of all of the material in
Part I. The material concerning the scalar type from
chapter 11 is also needed.
We come to the grandaddy of all data structures in
Modula-2, the RECORD. A record is composed of a number of
variables any of which can be of any predefined data type,
including other records. Rather than spend time trying to
define a record in detail, lets go right to the first
example program, SMALLREC.MOD. This is a program using
nonsense data that will illustrate the use of a record.
A VERY SIMPLE RECORD
There is only one entry in the TYPE declaration part of
the program, namely the record identified by "Description".
The record is composed of three fields, the "Year", "Model",
and "Engine" variables. Notice that the three fields are
each of a different type, indicating that the record can be
of mixed types. You have a complete example of the way a
record is defined before you. It is composed of the
identifier "Description", the reserved word RECORD, the list
of elements, and followed by END;. Notice that this only
defines a TYPE, it does not define any variables. That is
done in the VAR declaration where the variable "Cars" is
defined to have 10 complete records of the type
"Description". The variable "Cars[1]" has three components,
"Year", "Model", and "Engine", and any or all of these
components can be used to store data pertaining to
"Cars[1]".
In order to assign values to the various fields, the
variable name is followed by the sub-field with a separating
period. Keep in mind that "Cars[1]" is a complete record
containing three variables, and to assign or use one of the
variables, you must designate which sub-field you are
interested in. See the program where the three fields are
assigned meaningless data for illustration. The "Year"
field is assigned an integer number varying with the
subscript, all "Model" fields are assigned the name
"Duesenburg", and all "Engine" variables are assigned the
value "V8". In order to further illustrate that there are
actually 30 variables in use here, a few are changed at
random in the next few statements, being very careful to
maintain the required types as defined in the TYPE
declaration part of the program. Finally, all ten composite
variables, consisting of 30 actual variables in a logical
grouping are printed out using the same "var.subfield"
Page 65
CHAPTER 11 - Records
notation described above.
If the preceding description of a record is not clear in
your mind, review it very carefully. It's a very important
concept in Modula-2, and you won't have a hope of a chance
of understanding the next example until this one is clear.
A SUPER RECORD
Examine the example file BIGREC.MOD for a very
interesting record. First we have a constant defined.
Ignore it for the moment, we will come back to it later.
Within the TYPE declaration we have three records defined,
and upon close examination, you will notice that the first
two records are included as part of the definition of the
third record. The record identified as "Person", actually
contains 8 variable definitions, three within the "FullName"
record, two of its own, and three within the "Date" record.
This is a TYPE declaration and does not actually define any
variables, that is done in the VAR part of the program.
The VAR part of the program defines some variables
beginning with the array of "Friend" containing 50 (because
of the constant definition in the CONST part) records of
"Person". Since "Person" defines 8 fields, we have now
defined 8 times 50 = 400 separate and distinct variables.
Each of the 400 separate variables has its own type
associated with it, and the compiler will generate an error
if you try to assign any of those variables the wrong type
of data. Since "Person" is a TYPE definition, it can be
used to define more than one variable, and in fact it is
used again to define three more records, "Self", "Mother",
and "Father". These three records are each composed of 8
variables, so we have 24 more variables which we can
manipulate within the program. Finally we have the variable
"Index" defined as a simple CARDINAL type variable. Notice
that if we desired, we could also define a variable of type
"FullName" composed of 3 simple variables.
HOW TO MANIPULATE ALL OF THAT DATA
In the program we begin by assigning data to all of the
fields of "Self". Examining the first three statements of
the main program, we see the construction we learned in the
last example program being used, namely the period between
descriptor fields. The main record is named "Self", and we
are interested in the first part of it namely the "Name"
part of the person record. Since the "Name" part of the
person record is itself composed of three parts, we must
designate which part of it we are interested in. The
complete description "Self.Name.FirstName" is the complete
Page 66
CHAPTER 11 - Records
description of the first name of "Self" and is the first
assignment statement which is assigned the name of
"Charley". The next two fields are handled in the same way
and are self explanatory.
WHAT IS THE WITH STATEMENT?
Continuing on to the fourth field, the "City", there are
only two levels required because "City" is not another
record definition. The fourth field is therefore completely
defined by "Self.City". Notice the "WITH Self DO"
statement. This is a shorthand notation used with record
definitions to simplify coding. From the BEGIN at the next
statement to the matching END; about 10 statements later,
any variables within the "Self" record are used as though
they had a "Self." in front of them. It greatly simplifies
coding to be able to omit the leading identifier within the
WITH section of code. You will see that "City", and
"State", are easily assigned values without further
reference to the "Self" variable. When we get to the "Day"
part of the birthday, we are back to three levels and the
complete definition is "Self.Birthday.Day" but once again,
the "Self." part is taken care of automatically because we
are still within the "WITH Self DO" area.
To illustrate the WITH statement further, another is
introduced, "WITH Birthday DO", and an area is defined by
the BEGIN END pair. Within this area both leading
identifiers are handled automatically to simplify coding,
and "Month" is equivalent to writing "Self.Birthday.Month"
if both WITH statements were removed. You may be wondering
how many levels of nesting are allowed in record
definitions. There doesn't appear to be a limit according
to the Modula-2 definition, but we do get a hint at how far
it is possible to go. In most implementations of Modula-2,
you are allowed to have WITH statements nested to nine
levels, and it would be worthless to nest WITH statements
deeper than the level of records. Any program requiring
more levels than nine is probably far beyond the scope of
your programming ability, and mine, for a long time.
After assigning a value to the year, the entire record
of "Self" is defined, all eight variables.
SUPER-ASSIGNMENT STATEMENTS
The next statement, "Mother := Self;" is very
interesting. Since both of these are records, both are the
same type of record, and both therefore contain 8 variables,
Modula-2 is smart enough to recognize that, and assign all
eight values contained in "Self" to the corresponding
Page 67
CHAPTER 11 - Records
variables of "Mother". So after one statement, "Mother" is
completely defined. The next statement assigns the same
values to the eight respective fields of "Father", and the
next two lines assign all 50 "Friend" variables the same
data. We have therefore generated 400 + 24 = 424 separate
pieces of data so far in this program. We could print it
all out, but since it is nonsense data, it would only waste
time and paper. The next three lines write out three sample
pieces of the data for your inspection.
WHAT GOOD IS ALL OF THIS
It should be obvious to you that what this program does,
even though the data is nonsense, appears to be the
beginning of a database management program, which indeed it
is. It is a crude beginning, and has a long way to go to be
useful, but you should see a seed for a useful program.
Now to go back to the CONST as promised. The number of
friends was defined as 50 and used for the size of the array
and in the assignment loop near the end of the program. You
can now edit this number and see how big this database can
become on your computer. Your compiler should be capable of
storing about 1000 records even within the smallest model
available on any compiler. If your compiler uses a larger
memory model, you will be able to store significantly more
records. See how big you can make the number of friends
before you get the memory overflow message. Keep the number
in mind because when we get to the chapter on Pointers and
Dynamic Allocation, you should see a marked increase in
allowable size, especially if you have a large amount of RAM
installed in your computer. If your compiler uses a large
memory model, you won't see an increase in size but it will
be an interesting exercise anyway.
A VARIANT RECORD
If any part of this chapter is still unclear, it would
be good for you to go back and review it at this time. The
next example will really tax your mind to completely
understand it, especially if the prior material is not
clear.
Examine the program VARREC.MOD for an example of a
program with a variant record definition. In this example,
we first define a scalar type, namely "KindOfVehicle" for
use within the record. Then we have a record defining
"Vehicle", intended to define several different types of
vehicles, each with different kinds of data. It would be
possible to define all variables for all types of vehicles,
but it would be a waste of storage space to define the
Page 68
CHAPTER 11 - Records
number of tires for a boat, or the number of propeller
blades used on a car or truck. The variant record lets us
define the data precisely for each vehicle without wasting
data storage space.
WHAT IS A TAG-FIELD?
In the record definition we have the usual RECORD header
followed by three variables defined in the same manner as
the records in the last two example programs. Then we come
to the CASE statement. Following this statement, the record
is different for each of the four types defined in the
associated scalar definition. The variable "WhatKind" is
called the tag-field and must be defined as a scalar type
prior to the record definition. The tag-field is what
selects the variant used, when the program uses one of the
variables with this record type. The tag-field is followed
by a colon and its type definition, then the reserved word
OF. A list of the variants is then given, with each of the
variants having the variables for its particular case
defined. The list of variables for one variant is called
the field list.
A few rules are in order at this point. The variants do
not have to have the same number of variables in each field
list, and in fact, one or more of the variants may have no
variables at all in its variant part. If a variant has no
variables, it must still be defined with a blank followed by
a semi-colon. All variables in the entire variant part must
have unique names. The three variables, "Wheels", "Tires",
and "Tyres", all mean the same thing to the user, but they
must be different for the compiler. You may use the same
identifiers again in other records and for simple variables
anywhere else in the program. The Modula-2 compiler can
tell which variable you mean by its context. Using the same
variable name should be discouraged as bad programming
practice because it may confuse you or another person trying
to understand your program at a later date.
USING THE VARIANT RECORD
We properly define four variables with the record type
"Vehicle" and go on to examine the program itself.
We begin by defining one of our variables of type
"Vehicle", namely the variable named "Ford". The seven
lines assigning values to "Ford" are similar to the prior
examples with the exception of the fourth line. In the
fourth line the tag-field which selects the particular
variant used is set equal to the value "Truck", which is a
scalar definition, not a variable. This means that the
Page 69
CHAPTER 11 - Records
variables named "Motor", "Tires", and "Payload" are
available for use with the record "Ford", but the variables
named "Wheels", "Engine", "Tyres", etc. are not available in
the record named "Ford".
Next, lets define the record "Sunfish" as a boat, and
define all of its variables. All of sunfish's variables are
defined but in a rather random order to illustrate that they
need not be defined in a particular order. Recall the use
of WITH from the last example program.
To go even further in randomly assigning the variables
to a record, we redefine "Ford" as having an "Engine" which
it can only have if it is a car. This is one of the fine
points of the record. If you assign any of the variant
variables, the record is changed to that variant, but it is
the programmers responsibility to assign the correct tag-
field to the record, not the Modula-2 compiler's. Good
programming practice would be to assign the tag-field before
assigning any of the variant variables. The remainder of
the "Ford" variables are assigned to complete that record,
the non-variant part remaining from the last assignment.
The variable "Mac" is now set equal to the variable
"Sunfish". All variables within the record are copied to
"Mac" including the tag-field, making "Mac" a boat.
NOW TO SEE WHAT WE HAVE IN THE RECORDS
We have assigned "Ford" to be a car, and two boats
exist, namely "Sunfish" and "Mac". Since "Schwinn" was
never defined, it has no data in it, and is at this point
useless. The "Ford" tag-field has been defined as a car, so
it should be true in the IF statement, and the first message
should print. The "Sunfish" is not a bicycle, so it will
not print. The "Mac" has been defined as a boat in the
single assignment statement, so it will print a message with
an indication that all of the data in the record was
transferred to its variables.
Even though we can make assignment statements with
records, they cannot be used in any mathematical operations
such as addition, or multiplication. They are simply used
for data storage. It is true however, that the individual
elements in a record can be used in any mathematical
statements legal for their respective types.
One other point should be mentioned. The tag-field can
be completely eliminated resulting in a "free union" variant
record. This is possible because Modula-2, as you may
remember from above, will automatically assign the variant
Page 70
CHAPTER 11 - Records
required when you assign data to one of the variables within
a variant. This is the reason that all variables within any
of the variants must have unique names. The free union
record should be avoided in your early programming efforts
because you cannot test a record to see what variant it has
been assigned to.
A NOTE TO PASCAL PROGRAMMERS
A record with a free union variant is commonly used in
Pascal to do type transfers, but this should be discouraged
in Modula-2 since it has a complete set of carefully defined
type transfer functions for that purpose. In addition, the
method of data storage is not specified as a part of the
language and a free union would not operate the same way
with different compilers if used for the purpose of type
transfer.
PROGRAMMING EXERCISE
1. Write a simple program with a record to store the names
of five of your friends and display the names.
Page 71