Delphi
Basics - Variables
Variables:
- Variables in Delphi must be declared before you can use
them.
- Most variables (except pointers, linked lists) have their
memory automatically allocated and freed according to
their scope
- Scope of variables:
- this depends on where they are declared:
- within a routine: last only as long as
the routine is being processed
- as a field of a form:
- created when the form is created
and destroyed when the form is
destroyed
- if declared in the private
section, not available to other
units or forms
- if declared in the public
section, then available to other
units which have the unit in its
uses clause
Variable
Data Types:
- Delphi numeric types:
Type |
Format |
Range |
Bytes |
Integers: |
|
|
|
Byte |
unsigned 8bit |
0..255 |
1 |
Word |
unsigned 16bit |
0..65535 |
2 |
Cardinal/LongWord |
unsigned 32bit |
0..4294967295 |
4 |
ShortInt |
signed 8bit |
-128..127 |
1 |
SmallInt |
signed 16bit |
32768..32767 |
2 |
Integer/LongInt |
signed 32bit |
2147483648..2147483647 |
4 |
Int64 |
signed 64bit |
2^63..2^631 |
8 |
Floating Point: |
|
|
|
Single |
7-8 sign.digits |
1.5 x 10^45 .. 3.4 x 10^38 |
4 |
Real/Double |
15-16sign.digits |
5.0 x 10^324 .. 1.7 x 10^308 |
8 |
Extended |
19-20sign.digits |
3.6 x 10^4951 .. 1.1 x 10^4932 |
10 |
- Delphi character/string types:
- Char/Ord:
- represents 1 character of the character
set:
- can be assigned directly as a
character eg. Ch := 'A'
- can be assigned directly by its
position in a character set eg. Ch
:= #65 or Ch := Chr(65)
- to determine its position in a
character set use Ord(Ch)
- examples of special characters:
- #9 = tabstop; #13
or CR = carriage
return; #169 =
copyright;
- #177 = +/-;
- Pascal Strings:
- ShortString = up to 255 chars
- String / AnsiString = up to 2^31
chars (4bytes - 2Gb) ie. "long
string"
- WideString = up to 2^30 chars
(for use in Unicode or for COM
interfaces)
- can set the length of a string by SetLength(s)
- can limit the length by defining it as a
variable "String[x]"
where x = length
- can determine length of a string by Length(s)
(in early Delphi, used s[0] to
determine length)
- can convert to uppercase by UpCase(s)
- can get a character from position x in a
string by s[x] (1st character is
in position s[1])
- can find 1st occurrence of a substring
"sub" within a string
"s" and gets its position via pos(sub,s)
- can delete a substring from a string
using delete(s,startIndex,Count)
- can copy to a PChar via StrPCopy
- can cast as a PChar via PChar(s)
if certain conditions exist (eg. string
is a long String, see help)
- cannot be used in case statements, thus
need to use if then else statements when
checking for strings
- Null terminated strings (these
are used in Windows API):
- instead of having the 1st byte as being a
length, the end of the string is
determined by the character #0
- PChar
- True/False:
- Variant:
- typeless variables that can contain any type of
data or object automatically
- used for compatibility with Windows OLE/COM
technology but although convenient are
inefficient
- there are 2 special values:
- null: variable is unknown or
missing data
- unassigned: not been assigned
- variant routines:
- Enumerated types:
- you can define your own type which has the
following advantages:
- being an array-based type, it will:
- save memory by taking only 1 byte
- allow usage in case statements
- make your code potentially more
understandable
- eg. type CardTypes =
(ctHearts,ctDiamonds,ctSpades,ctClubs);
Data
Structures
(Aggregates of variables):
- Records:
- you can define a record variable as follows:
- type MyRec: Record
- varName1: variableType;
- varName2: variableType;
- end;
- reference a field in the record by MyRec.varName
- you can even create variant records
that can be of different structure depending on
its utility, for example:
- type
- TLegType = (Healthy, Damaged);
- TAnimalEnum = (Mammal, Bird, Insect);
- TLegs = Record
- Right, Left: TLegType;
- end;
- TAnimal = Record
- AnimalType: TAnimalEnum;
- case TAnimalEnum of //create
different number of fields
depending on type
- Mammal: (MFrontleg,
MBackLeg: TLegs);
- Bird: (BLegs: TLegs);
- Insect: (Foreleg,
Midleg, Backleg: TLegs);
- end;
- var Animal: TAnimal;
- begin
- Animal.AnimalType := Mammal;
- Animal.MFrontleg.Right :=
Damaged;//as the type is a
mammal, can use MFrontLeg
- end;
- you can store
records in a text file
- Arrays:
- arrays are widely used by Delphi (eg.
Form.Components[x]; Screen.Forms[x];Lists, etc)
- you can define an array as follows:
- type MyArray = array[a..b] of
variableType;
- a = starting index for array
(usually 0 or 1)
- b = ending index for array =>
number of items in array = b-a
- dynamic arrays:
- can leave brackets out to
declare a dynamic array
where length is variable
- memory for it is either
automatically allocated
as values are assigned to
elements or manually via SetLength(dynArray,length)
- dynamic arrays are always
zero-based index
- to deallocate memory,
either:
- assign the variable
that references the array
to nil, or,
- use the finalise
procedure
- reference a value in the array by MyArray[x]
where x is the value index
- can get the size of an array by SizeOf(MyArray)
(this is number of items in array * variableType
length)
- to set all items in an array to character #0: FillChar(MyArray,
SizeOf(MyArray),#0)
- you can define a multidimensional array as
follows (example shows a 2 dimensional array):
- type MyArray = array[a..b, a..b] of
variableType;
- thus number of items in this array would
be (b-a)^2
- NB. you could create a database file by: type
MyArray = array of MyRec;
- Sets:
- sets are unordered collections of data that
closely resemble mathematical sets
- sets can only contain ordinal values (integers,
char, boolean, enumerated types)
- eg. type TCapitals = set of Char;
- var Capitals : TCapitals;
- begin
- end;
- sets are used in Delphi to specify options for a
control eg. Font.style := (fsBold, fsItalic);
- Pointers:
- these are addresses of data structures in memory
and are more complicated to use than variables
- nb. actually all delphi classes are actually
implemented as pointers but this is hidden to the
programmer!
- they are widely used in C++ and in Windows API
but fortunately Delphi protects the user from
having to use them, unless you:
- directly access the windows API, or,
- wish to save memory usage where large
data structures are used, or,
- wish to speed up complicated routines
that access large variables by only
accessing their addresses, or,
- wish to use linked lists,
or,
- wish to access memory larger than 64K in
Win 3.1x
- importantly, you must allocate then free the
memory to a pointer variable
- eg. an example of using a pointer to a string
variable:
- type PString = ^String; //the
carat indicates that it is referencing
the address of the string, not the string
itself
- var MyStringPtr : PString;
- begin
- New(MyString); //allocate
memory for the actual string not
just the address
- MyString^ := 'Hello'; //the
terminal caret dereferences the
pointer so that the actual string
can be assigned a value
- Edit.text := MyString^; //assign
the value of the string to an
edit control text property
- Dispose(MyString);
//deallocate memory, forgetting
to do this will gradually lose
system resources!
- Linked lists:
- this data structure uses pointers to records that
contain a field which is also a pointer to the
same sought of record, thereby allowing one to
string a series of records together out on to the
heap part of memory
- the main advantages are:
- they are very quick & convenient way
to store many records in a single data
structure
- move all the records out on to the heap
thereby enabling you to keep track of
large volumes of data that exceed many
times the limits of the data segment
(64Kb in Win3.1x)
- Delphi uses linked lists to create TStrings,
TStringList, TList objects
- Procedural variables:
- allow you to declare variables that are either
procedures, functions or methods, allowing you to
call a routine by assigning the address of the
routine you wish to call to a variable, then
using the variable to call the routine.
- procedural variables are assignment compatible if
all the following are met:
- same number of parameters which must be
in the same order & of the same type
- same calling convention (eg. pascal,
cdecl, stdcall, safecall)
- for functions, the return values must be
of the same type
- this allows one then to create generic routines,
for example, when running multiple reports with
various options:
- type TRptProc =
procedure(Params:Variant); //variant
allows flexibility as can even store
array of variant!
- procedure
RunReport(PreProcessing,PostProcessing:TRptProc;PreParams,PostParams:Variant);
- begin
- RptDlg :=
TRptDlg.Create(Application);
- try with RptDlg do begin
- ShowModal; //get user
report options
- Rpt.copies :=
StrToInt(CopiesEdit.text);
- Rpt.StartPage :=
StrToInt(StartPageEdit.text);
- Rpt.EndPage :=
StrToInt(EndPageEdit.text);
- if Assigned(PreProcessing)
then
- PreProcessing(PreParams);
- Rpt.Print;
- if Assigned(PostProcessing)
then
- PostProcessing(PostParams);
- end;
- finally RptDlg.free; end;
- end;
- see references: