Home
Intro
LC
ACR
About

Day 8 - User Defined Types

-=-=-=-=-=-=-=-=-=-=-

What you are going to learn today:

  • What user-defined types are
  • How do we implement user-defined types
  • The different types of user types
  • And what this has to do with you

-=-=-=-=-=-=-=-=-=-=-

Horrors of horrors, you are going to learn how to make your own data types! Well, not really. Your so-called 'data types' are actually just your own customised way of storing values, as you'll soon find out. Feeling curious? Well, read on!

What are user-defined types?

Tetris Blocks Simple question. Imagine you have these wonderful data types, but you're getting messed up figuring out which variable belongs to square 2,3 and which belongs to square 7,1. (That is assuming you live by creating brick games, of course) Bricks start falling backwards and invert instead of rotating - with you going crazy inside! But you can't do anything, simply because you've got so many variables that you can't figure out which one is which. (Was that the variable representing its current X position or what?) What you really need is just a better way to store your values, and in this case, you could replace the entire game board with one array variable, saving you both time and sanity. (In fact, I have confirmed suspicions that Tetris is just one big array manipulating program...) What? You don't know what's an array? Well, don't worry, you'll find out soon. Hey, Polish writer Junis Bright once wrote: "Patience ends all waiting" (another fake quote), so just hang on, okay?

How do we implement User-Defined Types?

You may not know any of the user-defined types yet, but before we can discuss them, we have to know how to use them, right? (You don't give a person a PC without the manual right?) There are two ways to declare User-Defined Types:

First, you can declare it in a normal var declaration, with the data type representing what you want it to store. We'll use a known example - the string type:

  var
    ASmallString: String(10);
This declares a string with 10 characters, but wait! There are two problems with this method: First, it is highly irritating to type 'String(10)' everytime you want to declare a variable with the same type. Second, 'String(10)' has no meaning on its own - wouldn't ir be better to call it 'TenCharacters' or something? Well, here's where the second method comes in!

You've learnt uses, const, and var right? Well, here's type! The type keyword can replace a data type with another name:

  type
    TenCharacters = String(10);

  var
    ASmallString: TenCharacters;
As you can see, type works almost the same way as const. TenCharacters is now the same as String(10)! Yes, that is true power. You can replace any data type with any other legal variable name. Ooo, ahh, that's how it works...

The different User-Types follow...

Note that these aren't all the user data types available, (we originally had all of them here, but halfway through we realised we were well behind schedule...) These types are only those which we feel are absolutely neccesary, such as records, sets, and arrays. Besides that, no way!

1. Arrays

Array(2, 1) Can you imagine making a Game of Life program and having to declare a variable for each and every cell? Not only would it be terribly confusing, it would require a Computer Science degree to make it efficient enough to use. So, what do we do? We use arrays! Arrays are like dimensional tables - A one-dimensional array is like a sequence of values, a two-dimensional array is like a table of values, and a three-dimensional array is like a cube of values. A four-dimensional one is like a, em, never mind. Arrays are much simpler than what they sound, it's just that it's so abstract that this is the only logical way to explain it - don't believe me? Well, let's see an example of an array declaration to prove it:
  type
    GameGrid = array [1..32, 1..32] of integer;

  var
    Grid1: GameGrid;
    Grid2: array [1..32, 1..32] of integer;
In case you're wondering, Grid1 and Grid2 are exactly the same. Now how does this array work? Well, you can say that the first number is the X coordinate and the second number is the Y coordinate. Thus, cell 3, 1 is represented by Grid1[3, 1]. Note that those are square brackets, not curly or round ones. And yes, you must also specify the data type for the entire array when you declare it. Want more examples? Ahh, here you go:
  var
    Line: array[0..255] of integer;
    Table: array[0..255, 67..127] of char;
    Cube: array['A'..'Z', 1..10, 1..10] of real;
Now you see why the dimensional method is always the most logical way to explain arrays. Also, note that you can also use characters to specify a dimension. In such a case, you refer to the array like this:
  begin
    Cube['S', 5, 5] := 70;
  end.
In the statement above, you assign cell 'S', 5, 5 the value 70. Fantastic, isn't it? Now, get ready for another example program! This ones simple, but is fantastic at clarifying any doubts you have in your mind.

Type

1: program ArrayCrazy;
2:
3:   type
4:     TTable = array [1..2, 1..5] of integer;
5:
6:   var
7:     Table: TTable;
8:     a, b: integer;
9:
10:  begin
11:    for a := 1 to 2 do
12:      for b := 1 to 5 do
13:        begin
14:          Writeln('Input value for ',a ,', ', b,' : ');
15:          Readln(Table[a, b]);
16:        end;
17:    for a := 1 to 2 do
18:      for b := 1 to 5 do
19:        Writeln('Value ', a, ', ', b, ' is ', Table[a, b]);
20:  end.

Run

Input value for 1, 1 :
1
Input value for 1, 2 :
2
Input value for 1, 3 :
3
Input value for 1, 4 :
4
Input value for 1, 5 :
5
Input value for 2, 1 :
6
Input value for 2, 2 :
7
Input value for 2, 3 :
8
Input value for 2, 4 :
9
Input value for 2, 5 :
10
Value 1, 1 is 1
Value 1, 2 is 2
Value 1, 3 is 3
Value 1, 4 is 4
Value 1, 5 is 5
Value 2, 1 is 6
Value 2, 2 is 7
Value 2, 3 is 8
Value 2, 4 is 9
Value 2, 5 is 10

Analyse

This program may look a little complex, but actually it's very simple. If you're having problems visualising, we suggest that you change the default colours under Options, Environment, Colors... to make the different elements of code clearer. Let's begin!

  • Line 4 - This defines the type TTable
  • Line 7 - Declaration of variable Table of type TTable
  • Line 8 - Declares two counters, a and b
  • Line 11 - This starts a loop for the X coordinate
  • Line 12 - This starts a loop for the Y coordinate: notice that this is a for loop in a for loop, this loop must finish before the first loop can loop again. Programmers call these loops nested loops.
  • Line 14 & 15 - Prints a message and inputs what you type into the array at the specified coordinates.
  • Line 17 & 18 - Starts another nested loop.
  • Line 19 - This time, the loop prints out the value of Table at the specified coordinates. Ta-da! The End!

2. Records

A record is like a box with stores boxes Imagine you're the principal of your school. Now, you're supposed to keep track of the Name, Class, Height, and Weight, of all those 15,000 little brats running around driving your teachers crazy. Well, how are you going to do it? Ahh, isn't this simple. Let's just create a big, gigantic array to arrange all this information. Or even better, let's make 4 separate arrays to store each detail about each brat in your school! Of course, the above are very possible, and very feasible feats, but the more intelligent, and logical, choice would be to use a record to represent each brat. Well, what's a record? In a way, a record is like one big variable holding lots of other variables. Something like one big box holding lots of boxes. Thus, each brat could be stored as a record with variables representing his name, class, height, and weight - a perfect conclusion to an imperfect education. Now, how does a record look like? Well, here it is:
  type
    Student = record
      Name, Class: string;
      Height, Weight: integer;
    end;
In this example, we have a type Student which contains the variables Name, Class, Height and Weight inside. The so called 'Little Boxes' are encased inside the 'Bigger Box' between the keywords record and end. How to declare a record variable then? Look:
  var
    Brat: Student;
It's essentially the same method you would use to declare normal variables, isn't it? Well, here's question No. 2! How would you refer to the little boxes inside the big giant box? Ahh, you simply just use the dot operator! For example, you want to refer to the 'Little Boxes' inside variable Brat:
  begin
    Brat.Name := 'Lee Yang Yang';
    Brat.Class := '1M';
    Brat.Height := 12;
    Brat.Weight := 6;
  end.
What you type would be the name of the variable, followed by a dot, then the name of the 'Little Box' you want to refer to. Yes, you have successfully contained all the bio-data of one student into one little variable! Fantastic! Do you see how it works now? Brat is the name of the big box, Name, Class, Height, and Weight are the names of the littles boxes. Great, eh? But that's not all - Many of you may find using the record variable name again and again irritating, (especially after you're suffering from CTS). See?
  begin
    { How many times do we type "Brat"? }
    Brat.Name := 'Lee Yang Yang';
    Brat.Class := '1M';
    Brat.Height := 12;
    Brat.Weight := 6;
  end.
Now isn't that long-winded. Hmm, one shortcut you can use to shorten this is the with keyword, which lets you refer to any of the 'Little Boxes' without typing the variable name. Ahh, isn't that nice? No more extra strain on your keyboard. Here's how it looks - the with statement states the name of the record first before you use its members.
  with Brat do
    begin
      Name := 'Lee Yang Yang';
      Class := '1M';
      Height := 12;
      Weight := 6;
    end;
See, the word 'Brat' only appears once! No extra 'Brats' to block your way - True efficiency! And yes, that also marks the end of our introduction to records. There's only one thing left to do: an example program. Well, you can't run away from it, so why not type it?

Type

1: program RecordingTime;
2:
3:   type
4:     Student = record
5:       Name, Class: string;
6:       Height, Weight: integer;
7:     end;
8:
9:   var
10:    TheBrat: Student;
11:
12:  begin
13:    { We first assign TheBrat values }
14:    TheBrat.Name := 'Augustus Gloop';
15:    TheBrat.Class := '5F';
16:    TheBrat.Height := 145;
17:    TheBrat.Weight := 67;
18:
19:    { Now we print them out! }
20:    with TheBrat do
21:      begin
22:        Writeln('Name: ', Name);
23:        Writeln('Class: ', Class);
24:        Writeln('Height: ', Height);
25:        Writeln('Weight: ', Weight);
26:      end;
27:  end.

Run

Name: Augustus Gloop
Class: 5F
Height: 145
Weight: 67

Analyse

This is a simple one. (Then again, I say that for all the programs, don't I?) What it does is to simply input some values into a record and print them out again. Here's the final breakdown:

  • Line 4, 5, 6 - Defines type Student with Name, Class, Height, and Weight. (Bet you've seen this before!)
  • Line 10 - Declares variable TheBrat as type Student.
  • Line 14, 15, 16, 17 - Here, we gave TheBrat some values, the hard way. See how irritating repeated typing can be? Oooo... (That tingling sensation!)
  • Line 20 - This with statement refers to record TheBrat
  • Line 22, 23, 24, 25 - Finally, these lines print out the values of TheBrat the easy way. Ahh, see that we can leave out 'TheBrat' now? So relaxing! We're finished for now, so let's go on to type No. 3

3. Set Types

Sets are just like check-boxes If you ever need a virtual check-list, sets are the closest you'll ever get. What sets do is to provide a list of objects, no more than 255, for you to 'check' on and off. As you continue learning Pascal, you'll find that sets can be pretty useful instead of a whole long list of Boolean variables - for obvious reasons.
    Rem - Opps! Of all the data types, we still haven't introduced Boolean yet, haven't we? Well never mind, we'll explain it now. You see, a Boolean type is just a type which is either true or false. Thus, you can type things like 'aBoolean := a = b;' - if a is equal to b, aBoolean is true. Otherwise, it's not. That simple!
Excited yet? Well, you may be wondering how do you declare sets then? Patience, patience! These things are not meant to be rushed. Ahh, the set definition looks like this:
  type
    aSet = set of 1..255;
    aSet2 = set of Char;
    aSet3 = set of ( Alpha, Beta, Gamma );
In this example, aSet has 'Check-Boxes' labelled from 1 to 255, and aSet2 has 'Check-Boxes' labelled with the different characters from the ASCII table. Notice aSet3 - Alpha, Beta, and Gamma are not any type of value, but just names for the 'Check-Boxes' in the set.
    Rem - Wait a minute! Remember I said that a set can only 255 values? How come I can declare a set with type Char - (aSet2 = set of Char;)? Well, simple. If you look up the ASCII chart, you'll notice that there are exactly 255 characters available (minus the null chracter, of course.) What the set does is to use all those characters as 'Check-Boxes', see? Don't try this with integer or real though, there are just too many possible values.
Now that you know how to declare sets, how to you tell it what to check on and what to check off? Well, there are two very simple ways, depending on what you want to do:

The first way is very simple - you place the values you want to turn on inside square brackets and assign it to the set, like this:

  begin
    aSet := [1, 7, 10..12, 5];
    aSet2 := ['A', 'K', 'X'..'Z'];
    aSet3 := [Alpha];
  end.
For aSet, values 1, 5, 7, 10, 11, and 12 will be turned on. For aSet2, values 'A', 'K', 'X', 'Y', and 'Z' are turned on instead. aSet3 just turns on 'Check-Box' Alpha. See how simple this whole thing works? Innovative, isn't it?

The second method to assign values is to use set operators: +, -, *. Unlike the plus, minus, and multiply functions, these are the add, minus, and intersect values! What? Well, here are the three set operator rules:

  1. Value C will only be on in (Set A + Set B) if C is on in either A or B
  2. Value C will only be on in (Set A - Set B) if C is on in A but not in B
  3. Value C will only be on in (Set A * Set B} if C is on in both A and B
Ahh, get the idea? Worked in the same way you expected it to, didn't it? Well, in case you're still confused, here's a nice little example to illustrate this wonderful concept:
  begin
    aSet := [1, 3, 5, 7];      { 1 3 5 7 }
    aSet := aSet + [2, 3, 5];  { 1 2 3 5 7 }
    aSet := aSet - [3, 5];     { 1 2 7 }
    aSet := aSet * [7];        { 7 }
  end.
Yes! Yes! That's the way sets should be. Now that you know how to assign values to sets, it is time to take the next step, learning how to test if a value is on! ( Hey, you did turn them on for something, right? )

The operator to use when testing if a value is on in a set is the in operator. For example, to test if the number 3 is turned on in aSet, you would type the following piece of code:

  begin
    if (3 in aSet) then
      Writeln('Omigosh! 3 is on!');
  end.
    Rem - Now, we realise that you might be confused about why the operator is called 'in' - why isn't it called 'on', 'check', or something like that? Well, it's all very simple. The analogy we used for sets is to use a bunch of Check-Boxes. However, Pascal uses the analogy of testing whether a value is inside the set or not. ( Now you know why it's called a set! ) A set just contains a list list of values and in tests if the value you gave it is in that list. Confused? Well, don't worry, you don't need to know this to use sets - what you need is just a lot of common sense!
In the example above, the line 'Omigosh! 3 is on!' displays only when 3 is 'turned on' inside set aSet. Funny way of doing things, right? But never mind, once you get the hang of it, it gets better. And now that you've learnt the fundamentals of sets, we also think it's time for the example program! Here it is:

Type

1: program SetItUp;
2: 
3:   type
4:     TSet = set of 1..10;
5: 
6:   var
7:     i: integer;
8:     Numbers: TSet;
9: 
10:  begin
11:    Numbers := [3, 6, 8..10];
12:    for i := 1 to 10 do
13:      if (i in Numbers) then
14:        Writeln(i);
15:  end.

Run

3
6
8
9
10

Analyse

Simple program, simple explanation. In fact, this program probably needs no explanation at all! But still, let's be fair, okay?

  • Line 4 - This line defines type TSet which is a set of 1 to 10
  • Line 7 - This declares a counter variable
  • Line 8 - The set, Numbers, is declared here
  • Line 11 - Here, we assign for Numbers to have values 3, 6, 8, 9, 10 turned on
  • Line 12 - A for loop starts looping the counter from 1 to 10
  • Line 13 & 14 - Here, we test if the counter is turned on in Numbers. If it is, it executes Line 14, which prints out the counter. (You see how it works now?)

End of Day 8

Ahh, now that we have finished sets, we can safely close this chapter on User-Defined Types... Or can we? Remember, many other different types are around, so your task isn't finished yet! But for now, since we can't continue anymore (without critical damage to our hands), we shall close this tutorial, to go on to Day 9 - Pointers and Such!

-=-=-=-=-=-=-=-=-=-=-

HomeIntroLCACRAbout
Back to Class I

-=-=-=-=-=-=-=-=-=-=-

This page is ThinkQuest entry 11127.
email: tq97-11127@advanced.org