Day 10
This is the Day 10 page for computer programming course 101, an introduction to computer programming. Day 10 teaches the concept of complex user defined types.Below are the topics and course materials we are learning today.
Complex Types
In our previous lessons we touched on intrinsic types such a String, Integer, Char, and Single. In out last session we discussed user defined such as type aliases, sub ranges, enumerations, and sets. All of these types reference a single piece of information generally of a fixed size. Complex types are types that are user defined with various sizes dependent upon how you define them.Records
The first complex type we'll examine is the record. A record (called to a structure in some languages) represents a collection of various types. Each item in the collection is called a is called a field. The declaration of a record type specifies a name and type for each field. The syntax of a record type declaration is as follows:type TRecordName = record Field1: TypeName1; Field2: TypeName2; Field3: TypeName3; ... end;Where TRecordName is a valid identifier, Fieldn is a valid identifier or a comma-delimited list of identifiers, and each TypeName is a valid type. The record declaration terminates with the end keyword and a ; semicolon.
Record Example
For example, the following declaration creates a record type called TDateRec.type TDateRec = record Year: Integer; Month: (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); Day: 1..31; end;Each TDateRec contains three fields: an Integer value called Year, a value of an enumerated type called Month, and another Integer between 1 and 31 called Day. The identifiers Year, Month, and Day are the field designators for TDateRec, and behave like variables.
Using a Record
The TDateRec type declaration, however, does not allocate any memory for the Year, Month, and Day fields. Memory is allocated when you declare a variable of type, like so:var StartDate, FinishDate: TDateRec;This variable declaration creates two instances of TDateRec, called StartDate and FinishDate. You can access the fields of a record by qualifying the fields within the record:
StartDate.Year := 1776; StartDate.Month := Jul; StartDate.Day := 4;Or use may use a with statement:
with StartDate do begin Year := 1776; Month := Jul; Day := 4; end;You can also copy the values of StartDate's fields to FinishDate:
FinishDate := StartDate; FinishDate.Year := 2050;
Other Records
Here are a few example of other record types. Examine them and see if you can understand their meanings.type TPoint = record X, Y: Integer; end; TRectangle = record X, Y, Width, Height: Integer; end; TSuit = (Diamonds, Clubs, Hearts, Spades); TRank = (Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King); TCard = record Suit: TSuit; Rank: TRank; FaceDown: Boolean; end; TCard = record Suit: TSuit; Rank: TRank; FaceDown: Boolean; end; TAddress = record Street: string; City, State, ZipCode: string; end; TPerson = record Name: string; Birthday: TDateRec; Address: TAddress; end; TBusiness = record Name: string; StockSymbol: string; Headquarters: TAddress; ChiefExecutive: TPerson; end;
Arrays
Another complex type is the array type. An array represents an indexed collection of elements of the same type. The syntax of an array type declaration is as follows:type TArrayName = array [LowBound..HighBound] of SomeType;Where TArrayName is a valid identifier, LowBound and HighBound are Integers, and each SomeType is a valid type. The array declaration terminates with a ; semicolon.
Array Example
For example, the following declaration creates a array type called TDeck.type TDeck = array [1..52] of TCard;You can then make use of a TDeck like so
procedure BuildDeck(var Deck: TDeck); const Range = Ord(High(TRank)) + 1; var Deck: TDeck; I: Integer; begin for I := Low(Deck) to High(Deck) do begin Deck[I].Suit := Low(TSuit); Deck[I].Rank := Low(TRank); Inc(Deck[I].Suit, (I - 1) div Range); Inc(Deck[I].Rank, (I - 1) mod Range); Deck[I].FaceDown := True; end; end;
Array Boundaries
Arrays can have any upper and lower bounds. You set these bounds when you declare an array. For example:type TDeck = array[1..52] of TCard;Is just as valid as:
type TDeck = array[0..51] of TCard;The only difference is in how you use them. In the first example an instance of a Deck[1] would retrieve the first card, while Deck[0] would retrieve the first card in the second example. Typically it makes more sense, and it is more common to use 0 are the lower bound, but in some situations you may want to make the lower bound a value other than 1.
Array Dimensions
The array examples we've look at so far are one dimensional arrays. That is, they are arrays with a single pair of upper and lower bounds. In most programming languages, and Pascal as well, you can define multi dimensional arrays.Consider the following example:
type TDailyReminders = array[0..11, 0..31] of string;We could use a two dimensional array like TDailyReminders to store a reminder for each day of the year. You could retrieve the day's reminder use code like:
Reminder := DailyReminders[Month, Day];Note that the type within the array is always the same, in this case a string, and the indexers must always be an ordinal type.
Dynamic Arrays
Situations may arise where not know exactly how large to make an array. You may want to have the capability of changing the size of the array at runtime. A dynamic array declares an array with a type type, but no boundaries.var Students: array of string;The above code creates a one-dimensional dynamic array of strings. The declaration does not allocate memory for Students. To create the array in memory, we call SetLength procedure. For example, given the declaration above:
SetLength(Students, 14);Allocates an array of 14 strings, indexed 0 to 13. Dynamic arrays are always integer-indexed, always starting from 0 to one less than their size in elements.
To create a two-dimensional dynamic array, use the following code:
type TMatrix = array of array of Double; var Matrix: TMatrix; begin SetLength(Matrix, 10, 20) // ... end;This allocates space for a two-dimensional, 10-by-20 array of Double floating-point values. To remove a dynamic array's memory space, assign nil to the array variable, like:
Matrix := nil;