Data Types & Variables Grade 10
Every value in Delphi has a data type. Variables are the containers that hold these values while your program runs. Constants hold values that never change.
Data Types
| Data Type | What it stores | Examples | Quotes? |
|---|---|---|---|
Integer | Whole numbers (positive & negative, no decimals) | 3, -15, 1250 | No |
Real | Numbers with decimals (floating point) | 3.14, -13.24, 125.89 | No |
String | One or more characters — text | 'Banana', '23.45', '@!jkl' | Single quotes '…' |
Char | A single character only | 'S', '!', 'a' | Single quotes '…' |
Boolean | Only True or False | True, False | No |
Delphi lets you go one way but not the other: a whole-number result can be poured into a Real variable without any fuss, but a Real value can never be poured into an Integer variable — there is no automatic way to throw away a decimal part. Worth remembering too: the / operator always hands back a Real answer, even when both of the numbers you divide happen to be whole numbers.
rTotalStock := iBoxesIn + iBoxesReturned; // fine — a whole number fits happily into a Real
iBoxesIn := rTotalStock * 2; // rejected — a Real value won't fit into an IntegerVariables
A variable is a named storage location that holds a value during program execution. Think of it as a labelled cup — it holds one thing at a time, but you can empty it and refill it whenever you like.
Variables must be: Declared → Populated → Used.
A variable holds one value at a time, but the value can change. Your cup might hold coffee now, tea after break and hot chocolate tonight — same cup, different contents. In the same way iScore could be 5 now and 12 later.
The data type is the kind of container, and it decides what may go inside — just as a cup is made for liquids and a plate is made for food. Each type is its own kind of container:
Integer— holds whole numbers, e.g. 3, 15, −7Real— holds numbers with decimals, e.g. 3.14String— holds text, e.g.'Banana'Boolean— holds onlyTrueorFalse
And just as you would not serve soup on a plate, you cannot store the word 'Banana' in an Integer — the value has to match the type of container.
Rules for Variable Names
Delphi won't accept just any piece of text as a variable name — a handful of rules apply every time you choose one:
- It has to begin with a letter or an underscore
_— never a digit or another symbol - Spaces are not allowed anywhere in the name
- Once past the first character, digits and underscores may join the letters — but nothing else
- You can't reuse one of Delphi's own reserved words, since words like
begin,varorendalready have a fixed meaning to the compiler - Delphi stops paying attention after the 255th character, so an extremely long name gains you nothing beyond that point
When a single word isn't descriptive enough, run several together and capitalise each new one instead of using spaces or an unbroken run of lowercase letters — sFirstName and rTotalCost read far more clearly than sfirstname or rtotalcost.
Naming Convention — Prefixes
| Prefix | Data Type | Example |
|---|---|---|
i | Integer | iAge |
r | Real | rPrice |
s | String | sName |
c | Char | cGrade |
b | Boolean | bFound |
Declaring Variables
Declaring a variable means creating a named container that we can populate later, in the var section, using the format: variableName : DataType;
Local Declaration (inside a procedure)
procedure TForm1.btnClickClick(Sender: TObject);
var
sName: string;
iNumber: integer;
begin
// code here
end;
Global Declaration (available to all procedures)
var
Form1: TForm1;
sName: string; // declared here, below existing var block
iNumber: integer;
Populating (Assigning) Variables
Use the assignment operator := to put a value into a variable that has already been declared.
sName := 'Jannie';
sName := edtName.Text; // from a text box
iNumber := 15;
iNumber := sedNum.Value; // from a spin edit
bFlag := True;
The := operator always works right → left: it takes the value on the right and stores it in the variable on the left.
Think of pouring coffee. You put the coffee (the value) into the cup (the variable) — you would never put the cup into the coffee! So the container always goes on the left.
In sName := 'Jannie'; the coffee is 'Jannie' (on the right) and the cup is sName (on the left). Read it backwards: "take 'Jannie' and pour it into sName".
It works the same with a calculation: iTotal := iPrice * iQty; — work out the answer (the coffee) on the right first, then pour it into iTotal (the cup) on the left. This is also why 5 := iAge; is impossible — you cannot pour a variable into a plain number.
Initialising Variables
Set a starting value before using a variable, especially counters and totals — otherwise Delphi may assign a random garbage value.
i := 0;
iTotal := 0;
sReverse := '';
cLetter := '';
Using Variables
lblFullName.Caption := sName + ' ' + sSurname;
memOut.Lines.Add(sName + ' ' + sSurname);
iAnswer := iNum1 + iNum2;
memOut.Lines.Add(IntToStr(iNum1) + ' + ' + IntToStr(iNum2)
+ ' = ' + IntToStr(iAnswer));
Two ASCII character codes are handy for laying out text: #13 forces whatever follows onto a new line (it is the code for a carriage return), and #9 inserts a tab space. Join either one into a string with +, exactly like any other piece of text:
lblResult.Caption := 'Test 1: 78%' + #13 + 'Test 2: 84%';
memOut.Lines.Add('Player' + #9 + 'Score');Incrementing and Decrementing Variables
Instead of writing out a full assignment every time a counter needs to move up or down by one, Delphi gives you two ready-made procedures: Inc and Dec. Call one with just the variable name and it steps by one; give it a second number and it steps by that amount instead.
| Statement | Equivalent to |
|---|---|
Inc(iVisitors); | iVisitors := iVisitors + 1; |
Inc(iVisitors, 5); | iVisitors := iVisitors + 5; |
Dec(iStock); | iStock := iStock - 1; |
Dec(iStock, 5); | iStock := iStock - 5; |
You'll reach for Inc most often inside a loop, nudging a counter forward one step per repetition — Inc(iCount); reads more naturally than repeating the full assignment statement every time.
Getting Input with InputBox
Not every value needs its own Edit box sitting on the form. The InputBox function opens a small dialog of its own, waits for the user to type something, and hands back whatever they entered — always packaged as a string, no matter what kind of data it looks like.
sTeam := InputBox('House Team', 'Which house are you in?', '');
Since the result is always text, wrap it in a conversion function whenever you actually need a number or a single character:
| Required type | Example |
|---|---|
string | sTeam := InputBox('House Team', 'Which house are you in?', ''); |
integer | iAge := StrToInt(InputBox('Age', 'How old are you?', '')); |
real | rHeight := StrToFloat(InputBox('Height', 'What is your height in metres?', '')); |
char | cGrade := InputBox('Grade', 'Enter your grade symbol:', '')[1]; — the [1] keeps only the first character typed |
Constants
A constant holds a value that is known before the program runs and cannot change while it runs. Use const instead of var. No data type is needed, and use = not :=.
const
VAT = 0.15;
MAX_ITEMS = 100;
// Using a constant — exactly like a variable
rVatAmount := rCostPrice * VAT;
rTotal := rCostPrice + rVatAmount;
Type Conversion
Components like TEdit only hold strings. You must convert to the right type before using in calculations.
| Function | Converts | Example |
|---|---|---|
StrToInt() | String → Integer | iAge := StrToInt(edtAge.Text); |
StrToFloat() | String → Real | rPrice := StrToFloat(edtPrice.Text); |
IntToStr() | Integer → String | lblOut.Caption := IntToStr(iTotal); |
FloatToStr() | Real → String | lblOut.Caption := FloatToStr(rAverage); |
Val procedure — converting safelyStrToInt crashes (runtime error) if the text isn't a valid number. The Val procedure converts a string to a number without crashing: it gives back the converted value AND an error code that tells you whether the conversion worked (0 = success, otherwise the position of the first bad character).
var
iValue, iCode : Integer;
begin
Val(edtAge.Text, iValue, iCode);
if iCode = 0 then
ShowMessage('Valid number: ' + IntToStr(iValue))
else
ShowMessage('Not a valid number!'); // iCode = position of the bad character
end;Formatting Real Numbers
// FloatToStrF(value, format, totalDigits, decimals)
lblPrice.Caption := FloatToStrF(rPrice, ffCurrency, 4, 2); // → R24.50
lblPrice.Caption := FloatToStrF(rPrice, ffFixed, 4, 2); // → 24.50
| Format | Description |
|---|---|
ffCurrency | Adds a currency symbol to the formatted value |
ffExponent | Writes the value out in scientific notation |
ffFixed | Rounds the value to however many decimal places you ask for |
ffGeneral | Plain number formatting — decimals are shown only when the value actually has them |
ffNumber | Works like ffFixed, but breaks large numbers up with thousands separators |
Types of Errors
| Error Type | When it occurs | Example |
|---|---|---|
| Syntax Error | Code is typed incorrectly — won't compile | Missing semicolon, missing end |
| Runtime Error | Crashes while the program is running | Dividing by zero |
| Logical Error | Runs, but gives wrong answer | Calculating average before total, infinite loop |
Only a syntax error stops the program from compiling at all — Delphi catches it immediately. Runtime and logical errors both let the program compile and run, which makes them harder to catch: a runtime error only shows itself when the exact conditions that break it occur (e.g. the user finally types a letter instead of a number), and a logical error may never show itself at all — the program keeps running and simply produces the wrong answer.
| Common causes of runtime errors | Common causes of logical errors |
|---|---|
Converting text that isn't a valid number (StrToInt/StrToFloat) | Using the wrong variable in a calculation (e.g. a property was never transferred into it) |
| Dividing by zero | Getting the sequence of instructions wrong (e.g. calculating a total before all the values were added) |
| Calculating the square root of a negative number | Using AND/OR/NOT incorrectly in a compound condition |
| A calculated answer too big for its variable type (overflow) | Ignoring the order of precedence of operators |
| Accessing an array index that is out of range | A mistake with the variable controlling a loop, causing it to run forever |
Many runtime and logical errors trace back to invalid data: Garbage In, Garbage Out. A program is only as reliable as the checks it makes on the data it receives — see Input Validation on the Decision Making page.
Preventing and Handling Runtime Errors with Try..Except
A try..except block protects against any runtime error, not just a bad conversion. Code that might fail — a conversion, a calculation, anything risky — goes inside the try section. The moment something in there raises an error, Delphi abandons whatever was left in that section and jumps straight to except, running the recovery code written there instead of letting the program crash.
try
// risky code that might raise a runtime error
except
// code that runs only if an error occurred above
end;var
rAmount : real;
begin
try
rAmount := StrToFloat(edtAmount.Text);
except
ShowMessage('Invalid amount entered');
end;
end;The Val procedure above and a try..except block solve the same problem in different ways. Val checks a conversion specifically and gives you an error code to test. try..except is more general — it protects any block of code (a conversion, a calculation, a file operation) and reacts only if something actually goes wrong.
Finding Logical Errors — Debugging Tools
Logical errors are the hardest to find because the program runs without crashing. Besides tracing the code by hand with a paper-based trace table, Delphi's built-in debugger lets you watch a program execute one line at a time and see exactly what is happening inside it.
| Tool | What it does |
|---|---|
| Breakpoint | Click in the grey margin next to a line of code to mark where execution must pause. When the program reaches that line, Delphi stops and lets you take control instead of running straight through. |
| Step (F8) | Executes only the highlighted line, then pauses again on the next one — lets you watch the program run one instruction at a time. |
| Watch List (Run → Add Watch) | Displays the current value of one or more variables, updated live as each line executes — so you can see exactly where a variable gets the wrong value. |
It is tempting to change lines of code at random when the output looks wrong, hoping something sticks. That approach wastes time and can introduce new bugs on top of the original one. Watching the variables change value one line at a time pinpoints the exact instruction responsible, so the fix is targeted instead of accidental.