PASCAL Lab Activiti Start Programming
PASCAL Lab Activiti Start Programming
using
Object Pascal
Chapter One
Language Basics
Our First Application
After installing and running Lazarus, we can start a new program from the main menu:
Project/New Project/Program
We will get this code in the Source Editor window:
program linesoftext(output);
begin
writeln('hi there.');
writeln('how are you today?');
writeln('are you ready for pascal?')
end.
PROGRAM CrunchNumbers(OUTPUT);
BEGIN
writeln('i can easily crunch numbers.');
writeln('here is multiplication of 50x4:',50*4);
writeln('..and here is division of 2400/8:',2400/8)
END.
program arithmetic(output);
{ variable declarations }
var
a, b :integer;
{ program block }
begin
a := 25;
b := 2;
writeln('a=',a);
writeln('b=',b);
writeln('a+b=',a+b);
writeln('a–b=',a–b);
writeln('a*b=',a*b);
writeln('a/b=',a/b);
writeln('a div b=',a div b); {used with integers only}
writeln('a mod b=',a mod b) {used with integers only}
end.
program constants(output);
{ constant declarations }
const
pi = 3.14159;
{ variable declarations }
var
radius, perimeter :real;
{ program block }
begin
radius := 4.9;
perimeter := 2 * pi * radius;
writeln('perimeter=', perimeter)
end.
program keyboardinput(output);
{ constant declarations }
const
pi = 3.14159;
{ variable declarations }
var
perimeter, radius :real;
roundedperimeter, truncatedperimeter :integer;
{ program block }
begin
write('please enter the radius:');
readln(radius);
perimeter := 2*pi*radius;
roundedperimeter := round(perimeter);
truncatedperimeter := trunc(perimeter);
writeln('perimeter=', perimeter);
writeln('perimeter (rounded)=', roundedperimeter);
writeln('perimeter (truncated)=', truncatedperimeter)
end.
program first;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
{$IFDEF WINDOWS}{$R first.rc}{$ENDIF}
begin
Writeln('This is Free Pascal and Lazarus');
Writeln('Press enter key to close');
Readln;
end.
Other examples
In the previous program change this line:
Writeln('This is Free Pascal and Lazarus');
to this one:
Writeln('This is a number: ', 15);
Then press F9 to run the application. You will get this result: This is a number: 15
Change the previous line as shown below, and run the application each time:
Code:
Writeln('This is a number: ', 3 + 2);
Output:
This is a number: 5
Code:
Writeln('5 * 2 = ', 5 * 2);
Output:
Variables
Variables are data containers. For example, when we say that X = 5, that means X is a
variable, and it contains the value 5. Object Pascal is a strongly typed language, which
means we should declare a variable's type before putting values into it. If we declare X
as an integer, that means we should put only integer numbers into X during its life time in
the application.
program FirstVar;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
var
x: Integer;
begin
x:= 5;
Writeln(x * 2);
Writeln('Press enter key to close');
Readln;
end.
We will get 10 in the application's output. Note that we used the reserved word Var,
which means the following lines will be variable declarations:
x: Integer;
This means two things:
var
x, y: Integer;
begin
x:= 5;
y:= 10;
Writeln(x * y);
Writeln('Press enter key to close');
Readln;
end.
var
c: Char;
begin
c:= 'M';
Writeln('My first letter is: ', c);
Writeln('Press enter key to close');
Readln;
end.
This type can hold only one letter, or a number as an alphanumeric character, not as
value. In the next example we introduce the real number type, which can have a
fractional part:
var
x: Single;
begin
x:= 1.8;
Writeln('My Car engine capacity is ', x, ' liters');
Writeln('Press enter key to close');
Readln;
end.
var
x: Integer;
begin
Write('Please input any number:');
Readln(x);
Writeln('You have entered: ', x);
Writeln('Press enter key to close');
Readln;
end.
In this example, assigning a value to X is done through the keyboard instead ofassigning
it a constant value in the application. In the example below we show a multiplication table
for a number entered by the user:
program MultTable;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
var
x: Integer;
begin
Write('Please input any number:');
Readln(x);
Writeln(x, ' * 1 = ', x * 1);
Writeln(x, ' * 2 = ', x * 2);
Writeln(x, ' * 3 = ', x * 3);
Writeln(x, ' * 4 = ', x * 4);
Writeln(x, ' * 5 = ', x * 5);
Writeln(x, ' * 6 = ', x * 6);
Writeln(x, ' * 7 = ', x * 7);
Writeln(x, ' * 8 = ', x * 8);
Writeln(x, ' * 9 = ', x * 9);
Writeln(x, ' * 10 = ', x * 10);
Writeln(x, ' * 11 = ', x * 11);
Writeln(x, ' * 12 = ', x * 12);
Writeln('Press enter key to close');
Readln;
end.
var
x, y: Integer;
Res: Single;
begin
Write('Input a number: ');
Readln(x);
Write('Input another number: ');
Readln(y);
Res:= x / y;
Writeln(x, ' / ', y, ' = ', Res);
Writeln('Press enter key to close');
Readln;
end.
Since the operation is division, it might result in a number with a fraction, so for that reason
we have declared the Result variable (Res) as a real number (Single). Single means a
real number with single precision floating point.
Sub types
There are many sub types for variables, for example, Integer number subtypes differ in
the range and the number of required bytes to store values in memory. The table below
contains integer types, value ranges, and required bytes in memory: Type Min value Max
Value Size in Bytes
program Types;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes;
begin
Writeln('Byte: Size = ', SizeOf(Byte),
', Minimum value = ', Low(Byte), ', Maximum value = ',
High(Byte));
Writeln('Integer: Size = ', SizeOf(Integer),
', Minimum value = ', Low(Integer), ', Maximum value = ',
High(Integer));
Write('Press enter key to close');
Readln;
end.
Conditional Branching
One of the most important features of intelligent devices (like computers, programmable
devices) is that they can take actions in different conditions. This can be done by using
conditional branching. For example, some cars lock the door when the speed reaches or
exceeds 40 K/h. The condition in this case will be: If speed is >= 40 and doors are
unlocked, then lock door. Cars, washing machines, and many other gadgets contains
programmable circuits like micro controllers, or small processors like ARM. Such circuits
can be programmed using assembly, C, or Free Pascal according to their architecture.
AirConditioner
program:
var
Temp: Single;
begin
Write('Please enter Temperature of this room :');
Readln(Temp);
if Temp > 22 then
Writeln('Please turn on air-condition')
else
Writeln('Please turn off air-condition');
Write('Press enter key to close');
Readln;
end.
We have introduced the if then else statement, and in this example: if the temperature is
greater than 22, then display the first sentence:: Please turn on air-conditionerelse, if the
condition is not met (less than or equal to 22) , then display this line: Please turn off air-
conditioner
We can write multiple conditions like:
var
Temp: Single;
begin
Write('Please enter Temperature of this room :');
Readln(Temp);
if Temp > 22 then
Writeln('Please turn on air-conditioner')
else
if Temp < 18 then
Writeln('Please turn off air-conditioner')
else
Writeln('Do nothing');
You can test the above example with different temperature values to see the
results. We can make conditions more complex to be more useful:
var
Temp: Single;
ACIsOn: Byte;
In the above example, we have used the new keyword (and) which means if the first
condition returns True (ACIsOn = 1), and the second condition returns True (Temp > 22),
then execute the Writeln statement. If one condition or both of them return False, then it
will go to the else part. If the airconditioner is connected to a computer via the serial port
for example, then we can turn it on/off from that application, using serial port
procedures/components. In this case we need to add extra parameters for the if condition,
like for how long the airconditioner was operating. If it exceeds the allowable time (for
example, 1 hour) then it should be turned off regardless of room temperature. Also we
can consider the rate of losing coolness, if it is very slow (at night), then we could turn if
off for longer time.
Weight program
In this example, we ask the user to enter his/her height in meters, and weight in Kilos.
Then the program will calculate the suitable weight for that person according to the
entered data, and then it will tell him/her the results:
program Weight;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Writeln('Invalid values');
Writeln('Please enter proper values');
It has been converted to one statement using begin end:
if (Height < 0.4) or (Height > 2.5) or (Weight < 3) or
(Weight > 200) then
begin
Writeln('Invalid values');
Writeln('Please enter proper values');
end
4. We have used the procedure Format, which displays values in a specific format. In
this case we need to display only 2 digits after the decimal point. We need to add the
SysUtils unit to the
Case .. of statement
There is another method for conditional branching, which is the Case .. Of statement. It
branches execution according to the case ordinal value. The Restaurant program will
illustrate the use of the case of statement:
Restaurant program
var
Meal: Byte;
begin
Writeln('Welcome to Pascal Restaurant. Please select your order');
Writeln('1 - Chicken (10$)');
Writeln('2 - Fish (7$)');
Writeln('3 - Meat (8$)');
Writeln('4 – Salad (2$)');
Writeln('5 - Orange Juice (1$)');
Writeln('6 - Milk (1$)');
Compiled by Engineer Mulimbi Bricious 15
Writeln;
Write('Please enter your selection: ');
Readln(Meal);
case Meal of
1: Writeln('You have ordered Chicken,',
' this will take 15 minutes');
2: Writeln('You have ordered Fish, this will take 12 minutes');
3: Writeln('You have ordered meat, this will take 18 minutes');
4: Writeln('You have ordered Salad, this will take 5 minutes');
5: Writeln('You have ordered Orange juice,',
' this will take 2 minutes');
6: Writeln('You have ordered Milk, this will take 1 minute');
else
Writeln('Wrong entry');
end;
Write('Press enter key to close');
Readln;
end.
If we write the same application using the if condition, it will become more complicated,
and willcontain duplications:
In the next example, the application evaluates students' marks and converts them to
grades: A, B, C, D, E, and F:
In the previous sample we have used a range, like (0 .. 39), which means the condition
will return True if the Mark value exists in this range.
Keyboard program
In this example, we will get a character from keyboard and the application will tell us the
row number of the entered key on the keyboard:
var
Key: Char;
begin
Write('Please enter any English letter: ');
Readln(Key);
Writeln;
case Key of
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p':
Writeln('This is in the second row in keyboard');
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l':
Writeln('This is in the third row in keyboard');
'z', 'x', 'c', 'v', 'b', 'n', 'm':
Writeln('This is in the fourth row in keyboard');
else
Writeln('Unknown letter');
end;
Write('Press enter key to close');
Readln;
end.
Note that we have used a new technique in the case condition, which is a set of values:
'z', 'x', 'c', 'v', 'b', 'n', 'm': which means execute case branch statement if the Key was one of
these values set: z, x, c, v, b, n or m We can also mix ranges with values set like this:
'a' .. 'd', 'x', 'y', 'z': which means execute the statement if the value falls between a and d, or
equal to x, y or z.
Loops
Loops are used to execute certain parts of code (statements) for a specific number of
times, or until a condition is satisfied.
For loop
You can execute for statements for a specific number of cycles using a counter like this
example:
We should use ordinal types like Integer, Byte, and Char in for loop variables. We call this
variable a loop variable or loop counter. The value of loop counter can be initialized with
any number, and we can also determine the last value of loop counter. For example, if
we need to count from 5 to 10, then we can do this:
for i:= 5 to 10 do
We can display loop counter in every cycle of the loop, as in the modified example below:
var
i: Integer;
Count: Integer;
begin
Write('How many times? ');
Readln(Count);
for i:= 1 to Count do
begin
Writeln('Cycle number: ', i);
Writeln('Hello there');
end;
Write('Press enter key to close');
Readln;
end.
Note that this time we need to repeat two statements, and for that reason we have used
the begin . . end keywords to make them one statement.
program MultTableWithForLoop;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
var
x, i: Integer;
Instead of writing the Writeln statement 12 times, we write it once inside a loop which is
executed 12 times. We can make the for loop statement iterate in a backward direction
using downto keyword instead of to keyword using this syntax: for i:= 12 downto 1 do
Factorial program
Factorial in mathematics is the multiplication of a number by each one of its predecessors down to the
number 1. For example, 3! = 3 * 2 * 1 = 6.
var
Fac, Num, i: Integer;
begin
Write('Please input any number: ');
Readln(Num);
Fac:= 1;
for i:= Num downto 1 do
Fac:= Fac * i;
Writeln('Factorial of ', Num ,' is ', Fac);
Writeln('Press enter key to close');
Readln;
end.
var
Num : Integer;
begin
repeat
Write('Please input a number: ');
Readln(Num);
until Num <= 0;
Writeln('Finished, please press enter key to close');
Readln;
end.
In the previous example, the program enters the loop, then it asks the user to enter a
number. If the number is less than or equal to zero, it will exit the loop. If the entered
number is greater than zero, the loop will continue.
Note:
We could replace this line:
until (Selection = 'x') or (Selection = 'X');
By this abbreviated code:
until UpCase(Selection) = 'X';
This will change the Selection variable to upper case if it is a lowercase letter, and the
condition will return True in both cases (x or X)
While loop
The while loop is similar to the repeat loop, but it differs from it in these aspects:
1. In the while , the condition is checked first before entering the loop, but repeat enters
the loop first then it checks the condition. That means repeat always executes its
statement(s) once at least, but while loop could prevent entering the first cycle if the
condition returns False from the beginning.
2. while loop needs begin end if there are multiple statements that need to be executed
in a loop, but repeat does not need begin end, its block (repeated statements) starts
from the repeat keyword to the until keyword.
Example:
var
Num: Integer;
begin
Write('Input a number: ');
Readln(Num);
while Num > 0 do
begin
Write('From inside loop: Input a number : ');
Readln(Num);
end;
Write('Press enter key to close');
Readln;
end.
The while loop has no loop counter, and for that reason we have used the variable i to
work as a loopcounter. The loop counter value is initialized by the number for which we
need to get its factorial, then we decrease it manually in each cycle of the loop. When i
reaches 1, the loop will break.
Strings
The String type is used to declare variables that can hold a chain of characters. It can
be used to store text, a name, or a combination of characters and digits like a car
license plate number. In this example we will see how we can use the string variable to
accept a user name:
var
Name: string;
begin
Write('Please enter your name : ');
Readln(Name);
Writeln('Hello ', Name);
Writeln('Press enter key to close');
Readln;
end.
In the next example, we will use strings to store information about a person:
var
Name: string;
Address: string;
ID: string;
DOB: string;
begin
Write('Please enter your name : ');
Readln(Name);
Write('Please enter your address : ');
Strings can be concatenated to produce larger strings. For example we can concatenate
FirstName, SecondName, and FamilyName into another string called FullName, similar
to the next example:
var
YourName: string;
Father: string;
GrandFather: string;
FullName: string;
begin
Write('Please enter your first name : ');
Readln(YourName);
Write('Please enter your father name : ');
Readln(Father);
Write('Please enter your grand father name : ');
Readln(GrandFather);
FullName:= YourName + ' ' + Father + ' ' + GrandFather;
Writeln('Your full name is: ', FullName);
Writeln('Press enter key to close');
Readln;
end.
Note that in this example we have added a space (' ') between names (like YourName +
' ' + Father) tomake a separation between names. The space is a character too. We can
do many operations on strings, like searching for subtext in a string, copying one string
to another string variable, or converting text characters to capital or lowercase like the
examples below: This line converts the letters in the FullName string value to capital
letters: FullName:= UpperCase(FullName); And this converts it to lowercase letters: FullName:=
LowerCase(FullName); In the next example, we need to search for the letter a in a user name
using the Pos function. The Pos function returns the first occurrence (Index) of that
character in a string, or returns zero if that letter or substring does not exist in the searched
text:
If the name contains a capital A, then Pos function will not point to it, because A is different
from a as we mentioned earlier. To solve this problem we can convert all user name
letters to lowercase case, and then we can do the search: If Pos('a', LowerCase(YourName))
> 0 the In the next modification of the code, we will display the position of the letter a in a
user name:
var
YourName: string;
begin
Write('Please enter your name : ');
Readln(YourName);
If Pos('a', LowerCase(YourName)) > 0 then
begin
Writeln('Your name contains a');
Writeln('a position in your name is: ',
Pos('a', LowerCase(YourName)));
end
else
Writeln('Your name does not contain a letter');
Write('Press enter key to close');
Readln;
end.
You may notice that if the name contains more than one letter a , the function Pos will
return the index of the first occurrence of the letter a in the user name. You can get the
count of characters in a string using the function Length: Writeln('Your name length is ',
Length(YourName), ' letters'); And you can get the first letter/character of a string using its
index number: Writeln('Your first letter is ', YourName[1]); And the second character: Writeln('Your
second letter is ', YourName[2]); The last character: Writeln('Your last letter is ',
YourName[Length(YourName)]); You can also display a string variable character by character
using a for loop: for i:= 1 to Length(YourName) do Writeln(YourName[i]);
Copy function
We can copy part of a string using the function copy. For example, if we need to extract
the word 'world' from the string 'hello world', we can do it if we know the position of that
part, as we have done in the example below:
Note that we have used the Copy function using this syntax:
Part:= Copy(Line, 7, 5);
Here is an explanation of above statement:
• Part:= This is the string variable in which we will put the function result (sub string,
'world').
• Line This is the source string which contains the 'Hello world' sentence.
• 7 This is the starting point or index of sub string that we need to extract, in this
case it is the character w.
• 5 This is the length of the extracted part. In this case it represents the length of the
word 'world'.
In the next example, we will ask the user to enter a month name, like February, then the
program will type the short version of it, like Feb:
var
Month: string;
ShortName: string;
begin
Write('Please input full month name e.g. January : ');
Readln(Month);
ShortName:= Copy(Month, 1, 3);
Writeln(Month, ' is abbreviated as : ', ShortName);
Writeln('Press enter key to close');
Readln;
end.
Insert procedure
The Insert procedure inserts a substring into a string. Unlike the string concatenation
operator (+) which links two substrings together, Insert adds the substring in the middle
of another string. For example, we can insert the word Pascal into the string 'Hello world',
resulting in 'Hello Pascal World' as in the following example:
var
Line: string;
begin
Line:= 'Hello world';
Insert('Pascal ', Line, 7);
Writeln(Line);
Writeln('Press enter key to close');
Readln;
Delete procedure
This procedure is used to delete a character or substring from a string. We need to know
the start position and the length of substring that should be deleted. For example, if we
need to delete the letters ll from the string 'Hello World' to make 'Heo World', we
can do it like this:
var
Line: string;
begin
Line:= 'Hello world';
Delete(Line, 3, 2);
Writeln(Line);
Writeln('Press enter key to close');
Readln;
end.
Trim function
This function is used to remove spaces from the start and the end of strings. If we have
a string that contains the text ' Hello ' it will be 'Hello' after using this function. We can not
display spaces in a terminal window unless we put characters between them. Look at the
example below:
program TrimStr;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, SysUtils
{ you can add units after this };
var
Line: string;
begin
Line:= ' Hello ';
Writeln('<', Line, '>');
Line:= Trim(Line);
Writeln('<', Line, '>');
Writeln('Press enter key to close');
Readln;
end.
StringReplace function
The StringReplace function replaces characters or substrings with other characters or
substrings in the desired string.
program SٍtrReplace;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, SysUtils
{ you can add units after this };
var
Line: string;
Line2: string;
begin
Line:= 'This is a test for string replacement';
Line2:= StringReplace(Line, ' ', '-', [rfReplaceAll]);
Writeln(Line);
Writeln(Line2);
Write('Press enter key to close');
Readln;
end.
var
Line: string;
begin
Line:= 'This is a test for string replacement';
Writeln(Line);
Line:= StringReplace(Line, ' ', '-', [rfReplaceAll]);
Writeln(Line);
Write('Press enter key to close');
Readln;
end.
var
Marks: array [1 .. 10] of Integer;
i: Integer;
begin
for i:= 1 to 10 do
begin
Write('Input student number ', i, ' mark: ');
Readln(Marks[i]);
end;
for i:= 1 to 10 do
begin
Write('Student number ', i, ' mark is : ', Marks[i]);
if Marks[i] >= 40 then
Writeln(' Pass')
else
Writeln(' Fail');
end;
Writeln('Press enter key to close');
Readln;
end.
We can modify the previous code to get the highest and lowest student marks:
var
Marks: array [1 .. 10] of Integer;
i: Integer;
Max, Min: Integer;
begin
for i:= 1 to 10 do
begin
Write('Input student number ', i, ' mark: ');
Readln(Marks[i]);
end;
Max:= Marks[1];
Min:= Marks[1];
for i:= 1 to 10 do
begin
// Check if current Mark is maximum mark or not
if Marks[i] > Max then
Max:= Marks[i];
// Check if current value is minimum mark or not
if Marks[i] < Min then
Min:= Marks[i];
Write('Student number ', i, ' mark is : ', Marks[i]);
if Marks[i] >= 40 then
Writeln(' Pass')
Note that we consider the first mark (Marks[1]) as the maximum and minimum mark, and
then we will compare it with the rest of the marks. Max:= Marks[1]; Min:= Marks[1]; Inside the
loop we compare Max, Min with each mark. If we find a number that is larger than Max,
we will replace Max value with it. If we find a number that is less than Min, then we will
replace Min with it. In the previous example we have introduced comments:
// Check if current Mark is maximum mark or not
We have started the line with the characters //, which means that this line is a comment
and will not affect the code and will not be compiled. This technique is used to describe
parts of code to other programmers or to the programmer himself/herself. // is used for
short comments. If we need to write multiline comments we can surround them by {} or
(**)
Example:
for i:= 1 to 10 do
begin
{ Check if current Mark is maximum mark or not
check if Mark is greater than Max then put
it in Max }
if Marks[i] > Max then
Max:= Marks[i];
(* Check if current value is minimum mark or not
if Min is less than Mark then put Mark value in Min
*)
if Marks[i] < Min then
Min:= Marks[i];
Write('Student number ', i, ' mark is : ', Marks[i]);
if Marks[i] >= 40 then
Writeln(' Pass')
else
Writeln(' Fail');
end;
We can also disable part of our code temporarily by commenting it:
Writeln('Max mark is: ', Max);
// Writeln('Min mark is: ', Min);
Writeln('Press enter key to close');
Readln;
In the above code, we have disabled the procedure for writing the minimum student mark.
Note:
We can declare an array as having a zero based index the same as in the C language:
Marks: array [0 .. 9] of Integer;
This can hold 10 elements too, but the first item can be accessed using the index 0:
Numbers[0]:= 30;
Second item:
Numbers[1]:= 315;
Records
While arrays can hold many variables of the same type, records can hold variables of
different types, and these variables are called 'Fields'. This group of variables/fields can
be treated as a single unit or variable. We can use records to store information that belong
to the same object, for example, car information:
1. Car type: string variable
2. Engine size: real number
3. Production year: integer value
We can collect these different types in one record which represents a Car as in the
following example:
program Cars;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
type
TCar = record
ModelName: string;
Engine: Single;
ModelYear: Integer;
end;
var
Car: TCar;
begin
Write('Input car Model Name: ');
Readln(Car.ModelName);
Write('Input car Engine size: ');
Readln(Car.Engine);
Write('Input car Model year: ');
Readln(Car.ModelYear);
Writeln;
Writeln('Car information: ');
Writeln('Model Name : ', Car.ModelName);
Writeln('Engine size : ', Car.Engine);
Writeln('Model Year : ', Car.ModelYear);
Write('Press enter key to close..');
Readln;
end.
We have added the letter (T) to Car to indicate that this is a type and not a variable.
Variable names could be like: Car, Hour, UserName, but type names should be like: TCar,
THouse, and TUserName. This is a standard in the Pascal language. When we need to
use this new type, then we should declare a variable of that type, for example:
var
Car: TCar;
If we need to store a value in one of its variables/fields, we should access it like this:
Car.ModelName
Records will be used in the Random access files section of this book.
Files
Files are important elements of operating systems and applications. Operating system
components are represented as files, and information and data are represented in files
too, like photos, books, applications, and simple text files. Operating systems control files
management like: reading, writing, editing and deleting files. Files are divided into many
types according to many perspectives. We can group files into two types: executable files,
and data files. For example compiled binary Lazarus applications are executable files,
while Pascal source code (.pas) are data files. Also PDF books, JPEG pictures, are data
files. We can divide data files into two types according to the representation of their
contents:
1. Text files: which are simple text files that can be written, or read using any simple
tool including operating system command lines like cat, vi commands in Linux and
type, copy con commands in Windows.
2. Binary data files: These are more complex and need special applications to open
them. For example, picture files cannot be opened using simple command line
tools, instead they should be opened using applications like GIMP, Kolour Paint,
MS Paint, etc. If we open picture, or voice files, we will get unrecognizable
characters which mean nothing to the user. Examples of binary data files are
database files, which should be opened using the proper application. There is
another way to categorize files according to access type:
1. Sequential access files: An example of a sequential file is a text file, which has no
fixed size record. Each line has its own length, so we can't know the position (in
characters) for the start of the third line for example. For that reason, we could
open the file for read only, or writing only, and we can also append text only to the
end of file. If we need to insert text in the middle of a file, then we should read file
contents into memory, do the modifications, erase the entire file from disk, then
overwrite it the file with the modified text.
2. Random access files: This type of file has a fixed size record. A record is the
smallest unit that we can read and write at one time, and it could be Byte, Integer,
Text files
Text files are the simplest files, but we should write to them in only one direction (only
forward). We cannot go back while writing to a text file. We should also define the
operation mode before opening the file: Read, Write or Append (writing at the end). In this
example, we will display the contents of a text file selected by a user. For example, a user
may have a text file name like c:\test\first.pas in Windows or /home/user/first.pas in Linux:
Typed files
Typed files are used for files that contain the same type of data that has the same size of
records, for example, if a file contains records of Byte type, that means the record size =
1 byte. If the file contains real numbers (Single), that means all record sizes are 4 bytes,
etc. In the next example, we will show how to use file of Byte:
Marks program
var
F: file of Byte;
Mark: Byte;
begin
AssignFile(F, 'marks.dat');
Rewrite(F); // Create file
Writeln('Please input students marks, write 0 to exit');
repeat
Write('Input a mark: ');
Readln(Mark);
if Mark <> 0 then // Don't write 0 value
Write(F, Mark);
until Mark = 0;
CloseFile(F);
Write('Press enter key to close..');
Readln;
end.
In the next example, we will show how to append new records without deleting the existing
data:
After running this program and entering new records, we can run it again to see the
appended data. Note that we have used Reset for opening the file for writing instead of
the Rewrite procedure. Rewrite erases all data for existing files, and creates an empty file
if the file does not exist, while Reset can only open an existing file without erasing its
contents.
Also, we have assigned 2 to the FileMode variable to indicate that we need to open the
file for read/write access mode. 0 in FileMode means read only, 1 means write only, 2
(Default) means read/write. FileMode:= 2; // Open file for read/write
Reset(F); // open file Reset puts the read/write pointer to the first record, and for that reason
if we start to write records immediately, we will overwrite the old records, so we have used
the Seek procedure to move the read/write pointer to the end of file. Seek can be used
only with random access files. If we try to access a record position that does not exist with
the Seek procedure (for example, record number 100, while we have only 50 records),
we will get an error. We have also used the FileSize function, which returns the current
record count in the file. It is used in combination with the Seek procedure to jump to the
end of the file: Seek(F, FileSize(F)); // Go to after last record Note that this example can be used
if the Student marks file already exists; if not, then we should run the first program (Storing
Student Marks) because it uses Rewrite which can create new files. We can combine
both methods (Reset and Rewrite) according to whether the file exists, as we have done
in the next example:
Note that in this example, we didn't use the Seek procedure, instead we read all file
contents first. This operation (Read all file) moves the pointer to the end of file. In the next
example, we will use a file of records to store Cars information.
In the previous example, we declared TCar type to define car information. The first field
(ModelName) is a string variable, but we limited its maximum length [20]: ModelName:
string[20];
File copying
All file types, like text files, binary files, are based on byte units, which are the smallest
representation of data in computer memory and on disk. Every file should contain one
byte, two bytes, etc, or no bytes at all. Every byte could hold an integer or a character
code from 0 to 255. We can open all file types using the File of Byte or File of Char
declaration. We can copy any file to another one using File of Byte files, and the result
will be a new file that is identical to the source file's contents.
After running the previous example, we should enter an existing source file and a new
destination file. In Linux we could enter file names like this: Input source file name:
/home/motaz/quran/mishari/32.mp3 Input destination file name:
/home/motaz/Alsajda.mp3 In Windows we could enter something like this: Input source
file name: c:\photos\mypphoto.jpg Input destination file name: c:\temp\copy.jpg If the
source file exists in the same directory as the FileCopy program, we could enter only the
file name like this: Input source file name: test.pas Input destination file name:
testcopy.pas If we use this method to copy large files, it will take a very long time
compared with operating system copy procedures. That means the operating system
uses a different technique to copy files. If we want to copy a 1 megabyte file, that means
the while loop will repeat about 1 million times, that means a million read and a million
write operations. If we replace the file of Byte declaration with file of Word, that means it
will take about 500,000 cycles for read and write, but this will work only for the files whose
size is even not odd. It will succeed if a file contains 1,420 bytes, but it will fail with a file
of 1,423 bytes. To copy a file of any kind using a faster method, we should use untyped
files.
Untyped files
Untyped files are random access files,that have a fixed record length, but are not linked
to any data type. Instead, they treat data (records) as an array of bytes or characters.
program DateTime;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes , SysUtils
{ you can add units after this };
begin
Writeln('Current date and time: ', DateTimeToStr(Now));
Write('Press enter key to close');
Readln;
end.
We have used the DateTimeToStr function contained in the SysUtils unit to convert a
TDateTime type returned by the Now function to a readable date/time string
representation. If we do not use this conversion, we will get an encoded date/time
displayed as a real number: Writeln('Current date and time: ', Now); There are also two date/time
conversion functions that display the date part only and the time part only : Writeln('Current
date is ', DateToStr(Now)); Writeln('Current time is ', TimeToStr(Now)); The Date function returns
only the date part of today, and the Time function returns the current time only:
Writeln('Current date is ', DateToStr(Date)); Writeln('Current time is ', TimeToStr(Time)); These two
functions put zeroes in the other part, for example, the Date function returns the current
day and puts zero in the time part (Zero in time means 12:00 am). The Time function
returns the current system time, and puts zero in the date part (Zero in date means
30/12/1899). We can check this by using DateTimeToStr function:
begin
Writeln('Current date and time is ',
FormatDateTime('yyyy-mm-dd hh:nn:ss', Now));
Writeln('Yesterday time is ',
FormatDateTime('yyyy-mm-dd hh:nn:ss', Now - 1));
Writeln('Tomorrow time is ',
FormatDateTime('yyyy-mm-dd hh:nn:ss', Now + 1));
Writeln('Today + 12 hours is ',
FormatDateTime('yyyy-mm-dd hh:nn:ss', Now + 1/2));
Writeln('Today + 6 hours is ',
FormatDateTime('yyyy-mm-dd hh:nn:ss', Now + 1/4));
Write('Press enter key to close');
Readln;
end.
If we add one to or subtract one from a date, it will add/subtract a complete day. If we
add, for example,
½ or 0.5, this will add half a day (12 hours).
In the next example, we will generate a date value using a specific year, month and day:
var
ADate: TDateTime;
begin
ADate:= EncodeDate(1975, 11, 16);
Writeln('My date of birth is: ', FormatDateTime('yyyy-mm-dd', ADate));
Write('Press enter key to close');
Readln;
end.
The EncodeDate function accepts year, month and days as inputs, and returns
year/month/day values in one variable of type TDateTime. The EncodeTime function
accepts hour, minute, second and Milli second and returns time values as one TDateTime
value:
var
ATime: TDateTime;
begin
ATime:= EncodeTime(19, 22, 50, 0);
Writeln('Almughrib prayer time is: ', FormatDateTime('hh:nn:ss', ATime));
Write('Press enter key to close');
Readln;
Date/time comparison
You can compare two date/time variables the same as comparing real numbers. For
example in real numbers: 9.3 is greater than 5.1, the same happens for TDateTime
values. Now + 1, which represents tomorrow, is greater than today (Now), and Now +
1/24 which means an hour after now is greater than Now – 2/24 which means two hours
before now. In the next example, we will put the date 1/Jan/2012 in a variable and
compare it with current date and check if this date is passed or not yet.
var
Year2012: TDateTime;
begin
Year2012:= EncodeDate(2012, 1, 1);
if Now < Year2012 then
Writeln('Year 2012 is not coming yet')
else
Writeln('Year 2012 is already passed');
Write('Press enter key to close');
Readln;
end.
We can add new functions to this example, which displays the remaining days or passed
days to/from that date:
var
Year2012: TDateTime;
Diff: Double;
begin
Year2012:= EncodeDate(2012, 1, 1);
Diff:= Abs(Now - Year2012);
if Now < Year2012 then
Writeln('Year 2012 is not coming yet, there are ',
Format('%0.2f', [Diff]), ' days Remaining ')
else
Writeln('First day of January 2012 is passed by ',
Format('%0.2f', [Diff]), ' Days');
Write('Press enter key to close');
Readln;
end.
Diff is a real number variable that will hold the difference between current date and the
2012 date. We also used the Abs function, which returns the absolute value of a number
(the number without the negative sign).
Constants
Constants are similar to variables. They have names and can hold values, but differ from
variables in modifying that value. Constant values can not be modified while running the
application, and their values should be determined before compiling the application. We
have used constants in a different way before, without naming them, just as an Integer
value or string as in this example: Writeln(5); Writeln('Hello'); The value 5 will never change
after running the application. 'Hello' is also a string constant. We can define constants
using the Const keyword after the application's uses clause as in the following example:
In the previous example, we will calculate the kilometers that the car could run with its
current fuel according to these facts:
1. Car fuel consumption: we have used the Consumption variable to store kilometers
per gallon for the current car
2. Fuel: we have used the Payment variable to store how much money we paid for
the current fuel
3. Gallon Price: we have used the GallonPrice constant to store the price for a gallon
of fuel for the current country. This value shouldn't be entered by the user; instead,
it should be defined by the programmer. Constants are recommended when using
the same value many times in the application. If we need to change this value, we
can do it once at the header of code.
Ordinal types
Ordinal types are integer values that use literal indications instead of numbers. For
example, if we need to define language variables (Arabic/English/French) we could use
the value 1 for Arabic, 2 for English, and 3 for French. Other programmers wouldn't know
the values for 1, 2 and 3 unless they find comments with these values. It will be more
readable if we do it with ordinal types as in the below example:
program OrdinalTypes;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
type
TLanguageType = (ltArabic, ltEnglish);
var
Lang: TLanguageType;
AName: string;
Integer, character and boolean types are ordinal types, while real numbers and strings
are not.
Sets
Set types can hold multiple properties or characteristics in one variable. Sets are used
only with ordinal values. For example, if we need to define the operating system's support
for applications, we can do it as in the following:
1. Define ordinal type that represents operating systems: TApplicationEnv:
TApplicationEnv = (aeLinux, aeMac, aeWindows);
2. Define the application as set of TApplicationEnv: for example: FireFox: set of
TApplicationEnv;
3. Put operating system values in the application set variable: FireFox:= [aeLinux,
aeWindows];
program Sets;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
Also we can use set syntax for other ordinal types, like Integers:
if Month in [1, 3, 5, 7, 8, 10, 12] then
Writeln('This month contains 31 days');
Or character:
if Char in ['a', 'A'] then
Writeln('This letter is A');
Exception handling
There are two types of errors: compilation errors like using a variable without defining it
in the Var section, or writing statements with incorrect syntax. These types of errors
prevent the application from compiling, and the compiler displays a proper message and
points to the line containing the error. The second type is the runtime error. This type of
error occurs while the application is running, for example, division by zero, In a line like
this: x:= y / z; This is valid syntax, but at run time a user could enter 0 in the Z variable, and
then the application will crash and display a division by zero error message. Trying to
open a nonexistent file will generate a runtime error also (File not found), or trying to
create a file in a read only directory. The compiler cannot catch such errors, which only
occur after running the application. To build a reliable application that will not crash from
runtime errors, we should use exception handling. There are different methods of
exception handling in Object Pascal:
There are two sections of the try statement. The first one is the block that we need to
protect, which resides between try … except. The other part exists between except .. end.
If something goes wrong in the first section (try except), the application will go to the
except section (except.. end) and it will not crash, but rather it will display the proper error
message and continue execution. This is the line that could raise the exception if the
value of y is zero:
Res:= x / y; If there is no exception, the except .. end part will not be executed.
This time the finally .. end part will be executed in all cases, regardless of whether there
is an error.
Raise an exception
Sometimes we need to generate/raise an exception to prevent some logical error. For
example if the user enters the value 13 for Month variable, we could raise an exception
telling him/her that he/she has violated the range of months.
Example:
program RaiseExcept;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
If the user enters a value outside of 1 to 10, an exception will be generated (X is out of
range), and if there is no exception handling for this part, the application will crash.
Because we have written try except around the code that contains the raise keyword, the
application will not crash, but instead it will display the error message.