In part 1 of this series you built your first Delphi app. Now it’s time to learn the language underneath it: Object Pascal.
This article covers the building blocks you’ll use in every Delphi program: variables, constants, data types, conditions and loops. Every example is short, and you can try them all in one small project.

How to Try the Examples
The quickest way is a console application, which prints text in a black window:
- Choose File > New > Console Application – Delphi.
- Put your code between
beginandend.in the main program. - Add
ReadLn;as the last line so the window stays open until you press Enter.
program Basics;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
begin
WriteLn('Hello from the console!');
ReadLn;
end.
WriteLn prints a line. You can pass it several values separated by commas: WriteLn('Total: ', Total);
Variables
A variable is a named box that holds a value. In Delphi you declare every variable with a type before you use it, in a var section:
var
CustomerName: string;
Age: Integer;
Price: Currency;
IsActive: Boolean;
begin
CustomerName := 'Sara';
Age := 31;
Price := 19.99;
IsActive := True;
WriteLn(CustomerName, ' is ', Age, ' years old.');
end.
The rules:
- The declaration is
Name: Type; - Assignment uses
:=. A single=is for comparisons and constants. - Delphi is not case-sensitive:
age,AgeandAGEare the same variable. Pick one style (usually PascalCase) and stick to it. - Local variables in a procedure are not set to zero for you. Always give them a value before reading them.
Since Delphi 10.3 you can also declare a variable inline, right where you need it, and let Delphi infer the type:
begin
var Total := 0; // Integer
var Greeting := 'Hi'; // string
for var I := 1 to 3 do
Total := Total + I;
end.
Inline variables are handy, but many existing projects use the classic var section, so you need to read both styles.
Constants
A constant is a value that never changes. Use const and a single =:
const
VatRate = 0.10;
CompanyName = 'SimplifyDatabase';
MaxRetries = 3;
Constants make code easier to read and change: if the VAT rate changes, you edit one line instead of hunting for 0.10 everywhere.
Common Data Types
| Type | Holds | Example |
|---|---|---|
Integer | Whole numbers (about ±2.1 billion) | 42 |
Int64 | Very large whole numbers | 9000000000 |
Double | Decimal numbers (floating point) | 3.14159 |
Currency | Money, exact to 4 decimal places | 19.99 |
Boolean | True or False | True |
Char | One character | 'A' |
string | Text of any length | 'Hello' |
TDateTime | Date and time | Now |
Two tips that save real bugs:
- Use
Currencyfor money, notDouble.Doublecan’t store values like 0.10 exactly, so totals can end up as 29.999999. TDateTimeis really aDouble: the whole part is the day and the fraction is the time of day. Use the date functions (Date,Now,IncDay,FormatDateTime) instead of doing maths on it by hand.
Working With Strings
Strings use single quotes. To put a quote inside a string, double it:
var
S: string;
begin
S := 'It''s easy'; // It's easy
S := S + ' with Delphi'; // join with +
WriteLn(Length(S)); // 21
WriteLn(UpperCase(S)); // IT'S EASY WITH DELPHI
WriteLn(Copy(S, 1, 4)); // It's
WriteLn(Pos('easy', S)); // 6
end.
Important: classic Delphi strings start at position 1, not 0. Copy(S, 1, 4) takes 4 characters starting at the first one.
Converting Between Types
Delphi won’t silently turn a number into text or text into a number. You convert explicitly:
| From → To | Function |
|---|---|
| Integer → string | IntToStr(42) |
| string → Integer | StrToInt('42') |
| string → Integer (safe) | StrToIntDef('abc', 0) returns 0 if the text isn’t a number |
| Double → string | FloatToStr(3.5) or FormatFloat('0.00', 3.5) |
| string → Double | StrToFloat('3.5') |
| Date → string | DateToStr(Date) or FormatDateTime('yyyy-mm-dd', Now) |
Format is the most flexible way to build text:
WriteLn(Format('%s bought %d items for %.2f', ['Sara', 3, 59.97]));
// Sara bought 3 items for 59.97
Operators
| Operator | Meaning | Example |
|---|---|---|
+ - * | Add, subtract, multiply | A * 2 |
/ | Divide, always gives a decimal | 7 / 2 = 3.5 |
div | Integer division | 7 div 2 = 3 |
mod | Remainder | 7 mod 2 = 1 |
= <> | Equal, not equal | A <> 0 |
< > <= >= | Comparisons | Age >= 18 |
and or not xor | Logic | (A > 0) and (B > 0) |
Watch out: in Delphi,
andandorbind tighter than=and>. Always put brackets around each comparison:if (Age >= 18) and (Age <= 65) then. Without them, the compiler reads it differently and gives an error.
If Statements
if Total > 1000 then
WriteLn('Free delivery')
else
WriteLn('Delivery costs 5.00');
Notice there’s no semicolon before else. The if ... then ... else is a single statement, and a semicolon would end it too early.
To run several statements in one branch, wrap them in begin ... end:
if Stock = 0 then
begin
WriteLn('Out of stock');
OrderMore := True;
end
else if Stock < 10 then
WriteLn('Low stock')
else
WriteLn('In stock');
Case Statements
When you check one value against many options, case is cleaner than a chain of ifs:
case Month of
12, 1, 2: Season := 'Winter';
3..5: Season := 'Spring';
6..8: Season := 'Summer';
9..11: Season := 'Autumn';
else
Season := 'Unknown';
end;
You can list several values (12, 1, 2) or a range (3..5).
The limitation: case only works with ordinal types such as Integer, Char, Boolean and enumerations. It does not work with strings. For text, use if ... else if, or the IndexStr function from System.StrUtils:
case IndexStr(Status, ['NEW', 'PAID', 'SHIPPED']) of
0: WriteLn('Waiting for payment');
1: WriteLn('Ready to ship');
2: WriteLn('On the way');
else
WriteLn('Unknown status');
end;
Loops
Delphi has three loops.
For Loop: When You Know How Many Times
var
I, Total: Integer;
begin
Total := 0;
for I := 1 to 10 do
Total := Total + I;
WriteLn('Sum of 1..10 = ', Total); // 55
for I := 5 downto 1 do
Write(I, ' '); // 5 4 3 2 1
WriteLn;
end.
tocounts up,downtocounts down, always by 1.- Don’t change the loop variable inside the loop. Its value after the loop is not defined, so don’t rely on it.
To loop over every item in an array or string, use for ... in:
var
C: Char;
begin
for C in 'SQL' do
WriteLn(C);
end.
While Loop: Check First, Then Run
var
Balance: Currency;
Years: Integer;
begin
Balance := 1000;
Years := 0;
while Balance < 2000 do
begin
Balance := Balance * 1.07;
Inc(Years);
end;
WriteLn('Doubles after ', Years, ' years'); // 11
end.
A while loop may run zero times if the condition is false at the start. Inc(Years) is the short form of Years := Years + 1.
Repeat Loop: Run First, Then Check
repeat
Write('Enter a number between 1 and 10: ');
ReadLn(N);
until (N >= 1) and (N <= 10);
A repeat loop always runs at least once, so it’s perfect for “ask until the answer is valid”. Note that repeat ... until doesn’t need begin ... end.
Break and Continue
Breakleaves the loop immediately.Continueskips to the next round.
for I := 1 to 20 do
begin
if I mod 2 = 0 then
Continue; // skip even numbers
if I > 9 then
Break; // stop after 9
Write(I, ' '); // 1 3 5 7 9
end;
Arrays in One Minute
A static array has a fixed size. A dynamic array can grow:
var
Scores: array[1..3] of Integer; // static, 3 items
Names: TArray<string>; // dynamic
I: Integer;
begin
Scores[1] := 90; Scores[2] := 75; Scores[3] := 82;
Names := ['Ali', 'Sara', 'Omar'];
SetLength(Names, 4); // now 4 items
Names[3] := 'Lina'; // dynamic arrays start at 0
for I := 0 to High(Names) do
WriteLn(Names[I]);
end.
High(Names) gives the last index and Length(Names) the number of items. For lists that grow and shrink a lot, you’ll later use TList<T> and TStringList, covered in the classes article.
Putting It Together: A Small Invoice Calculator
program Invoice;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
const
VatRate = 0.10;
var
Prices: TArray<Currency>;
Subtotal, Discount, Vat, Total: Currency;
I: Integer;
begin
Prices := [120.00, 45.50, 310.25, 18.00];
Subtotal := 0;
for I := 0 to High(Prices) do
Subtotal := Subtotal + Prices[I];
if Subtotal >= 400 then
Discount := Subtotal * 0.05
else
Discount := 0;
Vat := (Subtotal - Discount) * VatRate;
Total := Subtotal - Discount + Vat;
WriteLn(Format('Items: %d', [Length(Prices)]));
WriteLn(Format('Subtotal: %10.2f', [Subtotal]));
WriteLn(Format('Discount: %10.2f', [Discount]));
WriteLn(Format('VAT 10%%: %10.2f', [Vat]));
WriteLn(Format('Total: %10.2f', [Total]));
ReadLn;
end.
Output:
Items: 4
Subtotal: 493.75
Discount: 24.69
VAT 10%: 46.91
Total: 515.97
%% in a Format string prints a single % sign.
Common Beginner Mistakes
- A semicolon before
else.WriteLn('A'); elseis a compile error. Remove the semicolon. - Forgetting brackets in conditions. Write
if (A > 0) and (B > 0), notif A > 0 and B > 0. - Using
/for whole numbers./always returns a decimal. Usedivwhen you need an integer result. - Reading an unassigned local variable. It contains random leftover memory. Assign a value first.
- Using
casewith strings. It doesn’t compile. UseiforIndexStr. - Using
Doublefor money. UseCurrency.
Practice Exercises
Exercise 1. Print the multiplication table of 7 (7 × 1 to 7 × 10).
Exercise 2. Given Score: Integer, print the grade: 90 and above is A, 80 to 89 is B, 70 to 79 is C, below 70 is F. Use a case statement.
Exercise 3. Count how many vowels are in the string 'Simplify Database'.
Answers
Exercise 1:
for I := 1 to 10 do
WriteLn(Format('7 x %d = %d', [I, 7 * I]));
Exercise 2:
case Score of
90..100: Grade := 'A';
80..89: Grade := 'B';
70..79: Grade := 'C';
else
Grade := 'F';
end;
Exercise 3:
Count := 0;
for C in LowerCase('Simplify Database') do
if CharInSet(C, ['a', 'e', 'i', 'o', 'u']) then
Inc(Count);
WriteLn(Count); // 6
CharInSet checks whether a character is in a set of characters.
Summary
- Declare variables with
Name: Typeand assign with:=. Constants useconstand=. - Use
Integerfor whole numbers,Currencyfor money,stringfor text andTDateTimefor dates. - Convert types explicitly with
IntToStr,StrToIntDef,FormatFloatandFormat. if ... then ... elsehas no semicolon beforeelse.caseworks with ordinal values, not strings.forruns a known number of times,whilechecks first, andrepeat ... untilruns at least once.
Next in the series: procedures, functions and units, so you can split your code into reusable pieces. All parts are in the Delphi category.
Related articles
- What Is Delphi? Install Delphi Community Edition and Build Your First App: part 1 of this series.
- SQL Data Types Explained Simply: how the database side stores numbers, text and dates, which you’ll map to Delphi types later.
- The SQL CASE Expression Explained Simply: the SQL cousin of Delphi’s
casestatement.