Cheatsheet Pascal
Linguagem estruturada clássica para ensino e desenvolvimento (Free Pascal/Delphi)
Pascal
Basic and Structure
Program Structure
program MyProgram;
uses SysUtils;
var
name: string;
begin
WriteLn('Hello World!');
Write('Name: ');
ReadLn(name);
WriteLn('Hello, ', name);
end.A Pascal program starts with program, followed by uses (libraries), var (variables) and the begin...end. block (with a final period).
Arithmetic Operators
var a, b: integer; r: real; begin a := 10; b := 3; WriteLn(a + b); // 13 addition WriteLn(a - b); // 7 subtraction WriteLn(a * b); // 30 multiplication WriteLn(a div b); // 3 integer division WriteLn(a mod b); // 1 remainder r := a / b; // 3.33 real division end.
div is integer division and mod the remainder. The / operator always returns real, even with integer operands.
The in Operator (Set)
var
x: integer;
c: char;
begin
x := 5;
if x in [1..10] then
WriteLn('between 1 and 10');
c := 'a';
if c in ['a', 'e', 'i', 'o', 'u'] then
WriteLn('vowel');
end.The in operator checks membership in a set. [1..10] is a range and [...] a list of values. Widely used in validations.
Simple Enumerated Type
type
TDay = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
var
d: TDay;
begin
d := Mon;
if d = Mon then
WriteLn('Start of the week');
end.An enumerated type lists fixed values between parentheses. It makes the code more readable and safer than using loose integers.
Data Types
var i: integer; // integer (32-bit) b: byte; // 0..255 r: real; // real number c: char; // 1 character s: string; // dynamic string ok: boolean; // true/false d: double; // double precision n: int64; // 64-bit integer
Pascal is strongly typed: each variable has a fixed type. integer and int64 for integers, real/double for decimals, boolean for logic values.
Comparison Operators
var x: integer; begin x := 5; WriteLn(x = 5); // true equal WriteLn(x <> 3); // true not equal WriteLn(x > 3); // true greater WriteLn(x <= 5); // true less or equal end.
Equality is = (a single equals sign) and inequality is <>. The operators >, <, >= and <= compare order.
Comments
// single-line comment
{ comment between
braces }
(* comment between
parenthesis-asterisk *)
begin
WriteLn('Hello'); // inline
end.Pascal accepts three comment styles: // (line), { } and (* *) (block). Block comments can span multiple lines.
Subranges
type TGrade = 0..20; TVowels = 'a'..'z'; var grade: TGrade; begin grade := 15; // grade := 25; // ERROR: out of range end.
A subrange restricts a variable to a range of values (e.g. 0..20). The compiler can validate the assigned limits.
Variables and Assignment
var x, y, z: integer; name: string; begin x := 10; // assignment with := y := x * 2; // 20 name := 'Anna'; z := x + y; end.
Assignment uses := (colon and equals), unlike = which is comparison. Several variables of the same type are declared on the same line.
Logical Operators
var a, b: boolean; begin a := true; b := false; WriteLn(a and b); // false (AND) WriteLn(a or b); // true (OR) WriteLn(not a); // false (negation) WriteLn(a xor b); // true (exclusive OR) end.
The logical operators are spelled out: and, or, not (negation) and xor (exclusive OR). They operate on boolean.
Formatted Output
var
n: integer;
r: real;
begin
n := 42;
r := 3.14159;
WriteLn(n:5); // " 42" (width 5)
WriteLn(r:8:2); // " 3.14" (2 decimals)
Write('no ');
WriteLn('break'); // same line
end.WriteLn writes with a line break and Write without one. The syntax value:width:decimals formats the output aligned.
Constants
const PI = 3.14159; MAX = 100; NAME = 'Pascal'; ACTIVE = true; begin WriteLn(PI * 2); // PI := 3; // ERROR: constant end.
Constants are declared with const and cannot be changed. The type is inferred from the value. Useful for fixed values like PI or limits.
String Concatenation
var name, greeting: string; begin name := 'Anna'; greeting := 'Hello, ' + name + '!'; WriteLn(greeting); // Hello, Anna! end.
The + operator concatenates strings. To join text with numbers, convert first with IntToStr() or use WriteLn with commas.
Reading Input
var
name: string;
age: integer;
begin
Write('Name: ');
ReadLn(name);
Write('Age: ');
ReadLn(age);
WriteLn('Hello ', name, ', ', age);
end.ReadLn reads a line from the keyboard into the variable. Write shows the prompt without a line break before the read.
Flow Control
If / Else
if age >= 18 then
WriteLn('Adult')
else if age >= 12 then
WriteLn('Teenager')
else
WriteLn('Child');The if/else evaluates conditions in order. Parentheses are not required and no semicolon is used before the else.
For (Ascending)
var
i: integer;
begin
for i := 1 to 10 do
WriteLn(i);
end.The for with to counts upward. The control variable must be an ordinal type (integer, char, enum). Do not modify it inside the loop.
Break
var
i: integer;
begin
for i := 1 to 100 do
begin
if i = 50 then
Break; // exits the loop
WriteLn(i);
end;
end.Break immediately ends the loop (for, while or repeat) and continues after it. Useful to exit when a result is found.
If with begin/end Block
if x > 0 then
begin
y := x * 2;
WriteLn('positive: ', y);
end
else
begin
y := 0;
WriteLn('not positive');
end;To run several statements in a branch, group them with begin...end. Without the block, only the first statement belongs to the if.
For (Descending)
var
i: integer;
begin
for i := 10 downto 1 do
WriteLn(i);
// 10, 9, 8, ... 1
end.The for with downto counts downward. Useful for countdowns or traversing arrays from the end to the start.
Continue
var
i: integer;
begin
for i := 1 to 10 do
begin
if i mod 2 = 0 then
Continue; // skips even numbers
WriteLn(i); // odd numbers only
end;
end.Continue jumps to the next iteration of the loop, skipping the rest of the current block. Here it prints only the odd numbers.
Case
case day of
1: WriteLn('Monday');
2: WriteLn('Tuesday');
3..5: WriteLn('Midweek');
6, 7: WriteLn('Weekend');
else
WriteLn('Invalid');
end;The case selects by value. It accepts single values, ranges (3..5) and lists (6, 7). The else handles the remaining cases.
While
var
x: integer;
begin
x := 5;
while x > 0 do
begin
WriteLn(x);
x := x - 1;
end;
end.The while repeats while the condition is true. It checks the condition before each iteration, so the block may never run.
Exit
function Divide(a, b: integer): integer;
begin
if b = 0 then
begin
WriteLn('Division by zero');
Exit; // exits the function
end;
Result := a div b;
end;Exit immediately ends the current function or procedure. In functions, it can return a value with Exit(value) (modern Delphi/FPC).
Case with Strings
case command of
'quit': Close;
'help': ShowHelp;
'save': Save;
else
WriteLn('Unknown command');
end;In Free Pascal and Delphi the case also accepts strings. Each branch compares against a string constant. Cleaner than several if statements.
Repeat / Until
var
x: integer;
begin
x := 0;
repeat
x := x + 1;
WriteLn(x);
until x >= 5;
end.The repeat/until runs the block before checking the condition, guaranteeing at least one execution. It repeats until the condition becomes true.
Nested Loops
var
i, j: integer;
begin
for i := 1 to 3 do
for j := 1 to 3 do
WriteLn('i=', i, ' j=', j);
end.You can nest loops to traverse matrices or generate combinations. Each level uses its own control variable (i, j).
Functions and Procedures
Simple Procedure
procedure Greet(name: string);
begin
WriteLn('Hello, ', name, '!');
end;
begin
Greet('Anna');
Greet('Ray');
end.A procedure is a subprogram that performs actions without returning a value. It is declared before the main begin and called by name.
const Parameter
procedure Print(const s: string); begin WriteLn(s); // s := 'x'; // ERROR: cannot modify end;
The const passes by reference but prevents modification. It avoids copying large types (strings, records) while keeping read-only safety.
Default Parameters
procedure Log(msg: string; level: integer = 1);
begin
WriteLn('[', level, '] ', msg);
end;
begin
Log('error', 3); // [3] error
Log('info'); // [1] info
end.Parameters with a default value (e.g. level: integer = 1) can be omitted in the call. They must come at the end of the parameter list.
Variable Scope
var globalVar: integer; // visible in the whole program procedure Test; var localVar: integer; // only visible here begin localVar := 5; globalVar := localVar; end;
Variables declared at the top are global; inside a routine they are local. Local variables cease to exist when the routine ends.
Function with Return Value
function Add(a, b: integer): integer; begin Add := a + b; // return via the name end; begin WriteLn(Add(2, 3)); // 5 end.
A function returns a value, assigned to the function name itself (here Add := ...). The return type comes after :.
Open Array
function Sum(const nums: array of integer): integer;
var
i: integer;
begin
Result := 0;
for i := Low(nums) to High(nums) do
Result := Result + nums[i];
end;
begin
WriteLn(Sum([1, 2, 3, 4])); // 10
end.An array of the a parameter accepts arrays of any size. Low() and High() give the bounds and you can pass [...] literals.
Forward Declaration
procedure B; forward;
procedure A;
begin
B; // calls B declared ahead
end;
procedure B;
begin
WriteLn('B');
end;The forward directive declares a routine before its implementation, allowing mutual references between procedures (e.g. A calls B and B calls A).
Result (Modern Form)
function Square(x: integer): integer; begin Result := x * x; end; function IsEven(n: integer): boolean; begin Result := (n mod 2 = 0); end;
The special variable Result holds the return value in a more readable way. It is the preferred form in modern Delphi and Free Pascal.
Recursion
function Factorial(n: integer): int64;
begin
if n <= 1 then
Result := 1
else
Result := n * Factorial(n - 1);
end;
begin
WriteLn(Factorial(5)); // 120
end.A recursive function calls itself. It needs a base case (n <= 1) to terminate. Here it computes the factorial of n.
Anonymous Functions (Delphi/FPC)
type
TIntFunc = reference to function(x: integer): integer;
var
double: TIntFunc;
begin
double := function(x: integer): integer
begin
Result := x * 2;
end;
WriteLn(double(5)); // 10
end.Anonymous functions (lambdas) use reference to function. They can be assigned to variables and passed the arguments, like in other modern languages.
Parameter by Reference (var)
procedure Increment(var x: integer); begin x := x + 1; // changes the original variable end; var n: integer; begin n := 10; Increment(n); WriteLn(n); // 11 end.
The var passes the parameter by reference: the function changes the original variable. Without var, it receives only a copy (by value).
Function Overloading
function Max(a, b: integer): integer; overload; begin if a > b then Result := a else Result := b; end; function Max(a, b: real): real; overload; begin if a > b then Result := a else Result := b; end;
The overload allows several functions with the same name but different parameters. The compiler picks the right version based on the argument types.
Higher-Order Functions
type TOperation = function(a, b: integer): integer; function Apply(x, y: integer; op: TOperation): integer; begin Result := op(x, y); end; function Add(a, b: integer): integer; begin Result := a + b; end;
You can pass functions the parameters using a function type (function(a,b): integer). This allows reusable higher-order functions.
Data Structures
Static Array
var
arr: array[1..5] of integer;
i: integer;
begin
for i := 1 to 5 do
arr[i] := i * 10;
WriteLn(arr[1]); // 10
WriteLn(arr[5]); // 50
end.A static array has a fixed size defined at compile time (array[1..5]). The starting index can be any ordinal value, here it starts at 1.
Record with Methods
type
TPoint = record
x, y: integer;
procedure Move(dx, dy: integer);
end;
procedure TPoint.Move(dx, dy: integer);
begin
x := x + dx;
y := y + dy;
end;Modern records (Delphi/FPC) can have methods and properties. The syntax TPoint.Move implements the method declared in the record.
Sets
type
TVowels = set of char;
var
v: TVowels;
begin
v := ['a', 'e', 'i', 'o', 'u'];
if 'a' in v then
WriteLn('is a vowel');
end.A set stores unique values of an ordinal type. The in operator checks membership. Useful for flags and small collections.
TDictionary
uses Generics.Collections;
var
dict: TDictionary<string, integer>;
begin
dict := TDictionary<string, integer>.Create;
try
dict.Add('Anna', 30);
dict.Add('Ray', 25);
WriteLn(dict['Anna']); // 30
finally
dict.Free;
end;
end.TDictionary<K,V> stores key-value pairs. Access the value through the key (e.g. dict["Anna"]). Equivalent to a map/hashtable.
Dynamic Array
var dyn: array of integer; begin SetLength(dyn, 5); // allocates 5 elements dyn[0] := 10; // starts at 0 dyn[4] := 50; WriteLn(Length(dyn)); // 5 WriteLn(Low(dyn)); // 0 WriteLn(High(dyn)); // 4 end.
A dynamic array (array of) is resizable with SetLength. It always starts at index 0. Length, Low and High give the bounds.
Variant Record
type
TShape = record
case kind: char of
'c': (radius: real);
'r': (width, height: real);
end;
var
f: TShape;
begin
f.kind := 'c';
f.radius := 5.0;
end.A variant record has fields that share memory according to a discriminant field (case). Similar to a union in C.
Set Operations
var A, B, C: set of integer; begin A := [1, 2, 3]; B := [2, 3, 4]; C := A + B; // union [1,2,3,4] C := A - B; // difference [1] C := A * B; // intersection [2,3] end.
Sets support mathematical operations: + (union), - (difference) and * (intersection). Ideal for set logic.
Array and Record Constants
const
Days: array[1..7] of string =
('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');
Origin: TPoint = (x: 0; y: 0);
begin
WriteLn(Days[1]); // Mon
end.You can create constant arrays and records with fixed initial values. Arrays use (...) and records use (field: value; ...).
Multidimensional Array
var
matrix: array[1..3, 1..3] of integer;
i, j: integer;
begin
for i := 1 to 3 do
for j := 1 to 3 do
matrix[i, j] := i * j;
WriteLn(matrix[2, 3]); // 6
end.A multidimensional array uses several indexes separated by commas (array[1..3, 1..3]). Ideal for matrices and two-dimensional grids.
With (Record Shortcut)
var
p: TPerson;
begin
with p do
begin
name := 'Anna';
age := 30;
active := true;
end;
end.The with avoids repeating the record name when accessing several fields. Inside the block, name refers to p.name. Use with moderation.
TStringList
uses Classes;
var
list: TStringList;
begin
list := TStringList.Create;
try
list.Add('item1');
list.Add('item2');
WriteLn(list.Count); // 2
WriteLn(list.IndexOf('item1')); // 0
finally
list.Free;
end;
end.TStringList is a dynamic string list from the RTL. It offers Add, IndexOf, Sort and Count. Create with Create and release with Free.
Simple Record
type
TPerson = record
name: string;
age: integer;
active: boolean;
end;
var
p: TPerson;
begin
p.name := 'Anna';
p.age := 30;
p.active := true;
end.A record groups fields of different types in one structure. Fields are accessed with a dot (p.name). It is the equivalent of a struct.
Enumerations (enum)
type
TColor = (Red, Green, Blue);
var
c: TColor;
begin
c := Green;
if c = Green then
WriteLn('Green');
WriteLn(Ord(c)); // 1 (position)
end.An enumeration defines an ordered set of named values. Ord() returns the position (starting at 0). More readable than integers.
Generics (TList)
uses Generics.Collections;
var
nums: TList<integer>;
begin
nums := TList<integer>.Create;
try
nums.Add(10);
nums.Add(20);
nums.Sort;
WriteLn(nums[0]); // 10
finally
nums.Free;
end;
end.Generics (TList<integer>) create safe typed collections. Generics.Collections brings TList, TDictionary and other dynamic lists.
Strings and Conversions
Length and Copy
var s: string; begin s := 'Hello World'; WriteLn(Length(s)); // 11 WriteLn(Copy(s, 1, 5)); // 'Hello' WriteLn(Copy(s, 7, 5)); // 'World' end.
Length() returns the number of characters. Copy(s, start, n) extracts a substring starting at start with n characters.
StringReplace
uses SysUtils;
var
s: string;
begin
s := 'hi world hi';
s := StringReplace(s, 'hi', 'hello',
[rfReplaceAll, rfIgnoreCase]);
WriteLn(s); // 'hello world hello'
end.StringReplace() replaces text. rfReplaceAll swaps every occurrence and rfIgnoreCase ignores case.
Format
uses SysUtils;
begin
WriteLn(Format('%d years', [30]));
WriteLn(Format('%.2f', [3.14159])); // 3.14
WriteLn(Format('%s is %d', ['Anna', 30]));
WriteLn(Format('%8d', [42])); // aligned
end.Format() builds strings with placeholders: %d (integer), %f (real), %s (string). The .2 sets the decimal places.
Uppercase and Lowercase
uses SysUtils; var s: string; begin s := 'Hello World'; WriteLn(UpperCase(s)); // 'HELLO WORLD' WriteLn(LowerCase(s)); // 'hello world' end.
UpperCase() converts to uppercase and LowerCase() to lowercase. They live in the SysUtils unit.
Trim
uses SysUtils; var s: string; begin s := ' text '; WriteLn(Trim(s)); // 'text' WriteLn(TrimLeft(s)); // 'text ' WriteLn(TrimRight(s)); // ' text' end.
Trim() removes spaces at the start and end. TrimLeft() only on the left and TrimRight() only on the right. Essential to clean input.
Char: Ord and Chr
var
c: char;
n: integer;
begin
n := Ord('A'); // 65 (ASCII code)
c := Chr(65); // 'A'
c := Chr(Ord('a') - 32); // 'A'
WriteLn(Succ('A')); // 'B'
WriteLn(Pred('B')); // 'A'
end.Ord() returns the numeric code of the character and Chr() does the inverse. Succ() and Pred() give the next/previous.
Pos (Search)
var
s: string;
p: integer;
begin
s := 'Hello World';
p := Pos('World', s);
WriteLn(p); // 7 (position)
if Pos('xyz', s) = 0 then
WriteLn('not found');
end.Pos(sub, s) returns the position of the first occurrence (starting at 1) or 0 if not found. Useful to check presence.
String to Number
uses SysUtils;
var
n: integer;
r: real;
begin
n := StrToInt('42'); // 42
r := StrToFloat('3.14'); // 3.14
n := StrToIntDef('abc', 0); // 0 (safe)
end.StrToInt() and StrToFloat() convert strings into numbers and raise an exception if invalid. StrToIntDef() returns a default value instead of failing.
Concat and Length
var a, b, c: string; begin a := 'Hello'; b := 'World'; c := Concat(a, ' ', b); WriteLn(c); // 'Hello World' WriteLn(Length(c)); // 11 end.
Concat() joins several strings into one (an alternative to +). Length() returns the length. Strings in Pascal are dynamic.
Delete and Insert
var
s: string;
begin
s := 'Hello World';
Delete(s, 1, 6); // removes 6 chars
WriteLn(s); // 'World'
Insert('!', s, 6);
WriteLn(s); // 'World!'
end.Delete(s, start, n) removes n characters (modifies the string). Insert(txt, s, pos) inserts text at the given position.
Number to String
uses SysUtils;
var
s: string;
begin
s := IntToStr(42); // '42'
s := FloatToStr(3.14); // '3.14'
s := FloatToStrF(3.14159,
ffFixed, 8, 2); // '3.14'
end.IntToStr() and FloatToStr() convert numbers into strings. FloatToStrF() lets you control the format and decimal places.
String with Quotes (escape)
var s: string; begin s := 'He said ''hello'''; WriteLn(s); // He said 'hello' s := 'Line1' + #13#10 + 'Line2'; WriteLn(s); // two lines end.
To include a single quote inside a string, double it (''). #13#10 inserts a line break (CR+LF) using character codes.
Pointers, Units and Exceptions
Basic Pointers
var p: ^integer; x: integer; begin x := 42; p := @x; // address of x WriteLn(p^); // 42 (dereference) p^ := 100; // changes x WriteLn(x); // 100 end.
A pointer (^integer) stores an address. @x gets the address and p^ accesses the pointed value (dereference).
Using a Unit
program Main; uses MyUnit, SysUtils; begin WriteLn(Add(2, 3)); // from MyUnit end.
The uses clause imports units to access their functions and types. It can appear in the program or in another unit (interface or implementation).
Custom Exception
type
EInsufficientBalance = class(Exception)
constructor Create(value: real);
end;
constructor EInsufficientBalance.Create(value: real);
begin
inherited CreateFmt('Insufficient balance: %.2f',
[value]);
end;Create classes that inherit from Exception for specific errors. CreateFmt formats the message with parameters, like Format.
Bitwise Operations
var a, b: integer; begin a := 12; // 1100 b := 10; // 1010 WriteLn(a and b); // 8 (1000) WriteLn(a or b); // 14 (1110) WriteLn(a xor b); // 6 (0110) WriteLn(a shl 1); // 24 (shift) end.
The bitwise operators and, or, xor, shl and shr operate on the bits of the integer. Useful for flags and masks.
Dynamic Memory
var p: ^integer; begin New(p); // allocate memory p^ := 100; WriteLn(p^); Dispose(p); // release memory p := nil; end.
New() allocates memory for the pointed type and Dispose() releases it. Set the pointer to nil afterwards to avoid invalid accesses.
Try / Except
var
x: integer;
begin
try
x := StrToInt('abc');
except
on E: EConvertError do
WriteLn('Invalid number');
on E: Exception do
WriteLn('Error: ', E.Message);
end;
end.try..except catches exceptions. The on E: Type handles each exception type. E.Message gives the error description.
Typed Constants
const Threshold: integer = 100; // mutable (FPC) begin Threshold := 200; // allowed WriteLn(Threshold); end.
Typed constants (name: type = value) are actually initialized static variables: they keep the value between calls and can be changed.
Complete Program (example)
program Average;
uses SysUtils;
var
grades: array of integer;
i, sum: integer;
begin
SetLength(grades, 3);
sum := 0;
for i := 0 to High(grades) do
begin
grades[i] := Random(20) + 1;
sum := sum + grades[i];
end;
WriteLn('Average: ', sum / Length(grades):0:1);
end.Complete example: allocates a dynamic array, fills it with Random, sums and computes the average. It shows the typical structure of a Pascal program.
GetMem and FreeMem
var ptr: Pointer; begin GetMem(ptr, 1024); // 1024 bytes // use ptr... FreeMem(ptr); // release ptr := nil; end.
GetMem() allocates a raw block of bytes and FreeMem() releases it. More flexible than New for variable-size buffers.
Try / Finally
var
list: TStringList;
begin
list := TStringList.Create;
try
list.Add('item');
WriteLn(list.Count);
finally
list.Free; // always runs
end;
end.try..finally guarantees the execution of the finally block even on error. It is the pattern for releasing resources (memory, files, objects).
Compiler Directives
{$IFDEF DEBUG}
WriteLn('Debug mode active');
{$ENDIF}
{$MODE DELPHI} // Delphi mode (FPC)
{$RANGECHECKS ON} // checks indexes
begin
WriteLn('Hello');
end.{$...} directives control compilation. {$IFDEF} compiles conditionally, {$MODE} sets compatibility and {$RANGECHECKS} validates indexes.
Structure of a Unit
unit MyUnit; interface uses SysUtils; function Add(a, b: integer): integer; implementation function Add(a, b: integer): integer; begin Result := a + b; end; end.
A unit is a reusable module. The interface section declares what is public and implementation holds the code. It is used with uses.
Raise (throw an exception)
procedure Validate(age: integer);
begin
if age < 0 then
raise Exception.Create('Invalid age');
end;raise throws an exception manually. Exception.Create(msg) creates the exception with a message. It interrupts the flow up to the nearest except.
Type Aliases
type TName = string; TAge = integer; TMatrix = array of array of real; var name: TName; m: TMatrix; begin name := 'Anna'; end.
The type creates alternative names for existing types, improving readability. TName is just an alias for string.
Input/Output and Files
Write and WriteLn
begin
Write('No break ');
WriteLn('with break');
WriteLn('A', 'B', 'C'); // ABC
WriteLn(10, ' ', 20); // 10 20
WriteLn(3.14:6:2); // 3.14
end.Write prints without moving to a new line and WriteLn does. They accept several comma-separated arguments and :width:decimals formatting.
Append
var f: TextFile; begin AssignFile(f, 'log.txt'); Append(f); // append at the end WriteLn(f, 'New entry'); CloseFile(f); end.
Append opens an existing file to append at the end, without erasing the previous content. Ideal for log files.
Check Existence
uses SysUtils;
begin
if FileExists('data.txt') then
WriteLn('exists')
else
WriteLn('does not exist');
if DirectoryExists('C:\temp') then
WriteLn('folder exists');
end.FileExists() checks whether a file exists and DirectoryExists() whether a folder exists. They live in the SysUtils unit.
Read and ReadLn
var name: string; age: integer; begin ReadLn(name); // reads a line ReadLn(age); // reads an integer WriteLn(name, ' ', age); end.
ReadLn reads a full line from the keyboard and converts it to the variable type. Read reads without consuming the line break.
Binary File (typed)
type
TRecord = record
id: integer;
name: string[50];
end;
var
f: file of TRecord;
reg: TRecord;
begin
AssignFile(f, 'data.dat');
Rewrite(f);
reg.id := 1;
reg.name := 'Anna';
Write(f, reg);
CloseFile(f);
end.A file of TRecord stores fixed-size records in binary. Write(f, reg) and Read(f, reg) read/write complete records.
Delete and Rename
var f: TextFile; begin AssignFile(f, 'old.txt'); Erase(f); // deletes the file AssignFile(f, 'new.txt'); Rename(f, 'new2.txt'); // renames end.
Erase() deletes the associated file and Rename() changes the name. The variable must be linked with AssignFile but not open.
Write a Text File
var f: TextFile; begin AssignFile(f, 'data.txt'); Rewrite(f); // create/write WriteLn(f, 'Line 1'); WriteLn(f, 'Line 2'); CloseFile(f); end.
AssignFile links the variable to the file, Rewrite opens it for writing (creates a new one), you write with WriteLn(f, ...) and close with CloseFile.
Read a Binary File
var
f: file of TRecord;
reg: TRecord;
begin
AssignFile(f, 'data.dat');
Reset(f);
while not EOF(f) do
begin
Read(f, reg);
WriteLn(reg.id, ' ', reg.name);
end;
CloseFile(f);
end.Binary reading uses Read(f, reg) inside while not EOF(f). Each iteration loads a complete record of the structure.
TFileStream
uses Classes, SysUtils;
var
fs: TFileStream;
s: string;
begin
fs := TFileStream.Create('data.bin',
fmCreate);
try
s := 'Hello';
fs.WriteBuffer(s[1], Length(s));
finally
fs.Free;
end;
end.TFileStream gives full control over binary reading/writing. fmCreate creates the file and WriteBuffer writes raw bytes.
Read a Text File
var
f: TextFile;
line: string;
begin
AssignFile(f, 'data.txt');
Reset(f); // open for reading
while not EOF(f) do
begin
ReadLn(f, line);
WriteLn(line);
end;
CloseFile(f);
end.Reset opens the file for reading. The while not EOF(f) loop goes through to the end, reading each line with ReadLn(f, line).
Size and Position (binary)
var f: file of TRecord; begin AssignFile(f, 'data.dat'); Reset(f); WriteLn(FileSize(f)); // no. of records Seek(f, 2); // go to record 2 WriteLn(FilePos(f)); // current position CloseFile(f); end.
FileSize() returns the number of records and FilePos() the current position. Seek(f, n) moves to record n (random access).
Command Line Parameters
var
i: integer;
begin
WriteLn('No. args: ', ParamCount);
for i := 1 to ParamCount do
WriteLn(ParamStr(i));
end.ParamCount returns the number of command line arguments and ParamStr(i) each argument. ParamStr(0) is the name of the executable.
Classes e OOP
Basic Class
type
TPerson = class
Name: string;
Age: integer;
procedure Introduce;
end;
procedure TPerson.Introduce;
begin
WriteLn(Name, ', ', Age);
end;A class is declared with class and contains fields and methods. Methods are implemented outside with TPerson.Introduce. It is instantiated with Create.
Private and public
type
TAccount = class
private
FBalance: real; // hidden from outside
public
procedure Deposit(v: real);
function Balance: real;
end;private restricts access to the inside of the class (encapsulation). public makes members accessible from outside. Private fields use the F prefix.
inherited
procedure TDog.Speak;
begin
inherited Speak; // calls the superclass one
WriteLn('... and wags its tail');
end;inherited calls the version of the method in the superclass. Useful for extending behavior instead of replacing it entirely.
Polymorphism
var
shapes: array of TShape;
f: TShape;
begin
SetLength(shapes, 2);
shapes[0] := TCircle.Create;
shapes[1] := TSquare.Create;
for f in shapes do
WriteLn(f.Area); // calls the right one
end.With virtual/override methods, the same call (f.Area) runs the correct implementation according to the real type of the object at runtime.
Create and Free an Object
var
p: TPerson;
begin
p := TPerson.Create;
try
p.Name := 'Anna';
p.Age := 30;
p.Introduce;
finally
p.Free; // release memory
end;
end.Objects are created with Create and must be released with Free. The try..finally guarantees the release even if an error occurs.
Properties
type
TPerson = class
private
FName: string;
public
property Name: string read FName write FName;
property ReadOnly: string read FName;
end;A property exposes fields with read and write, controlling access. It can be linked to getter/setter methods for validation.
is and the
var
a: TAnimal;
begin
a := TDog.Create;
if a is TDog then
WriteLn('is a dog');
(a the TDog).Bark;
a.Free;
end.is checks the type at runtime and the does a safe cast (throws an exception if it fails). Essential for working with polymorphism.
for in (collections)
var
list: TList<integer>;
n: integer;
begin
list := TList<integer>.Create;
list.AddRange([1, 2, 3]);
for n in list do
WriteLn(n);
list.Free;
end.The for in iterates over collections and arrays cleanly, without indexes. It works with dynamic arrays, TList and other enumerables.
Constructor
type
TPerson = class
Name: string;
constructor Create(n: string);
end;
constructor TPerson.Create(n: string);
begin
inherited Create;
Name := n;
end;
var p: TPerson;
begin
p := TPerson.Create('Anna');
end.The constructor initializes the object on creation. inherited Create calls the base class constructor. It allows passing initial parameters.
Inheritance
type
TAnimal = class
procedure Speak; virtual;
end;
TDog = class(TAnimal)
procedure Speak; override;
end;
procedure TDog.Speak;
begin
WriteLn('Woof woof!');
end;Inheritance uses class(TAnimal). virtual marks the method the overridable and override reimplements it in the subclass (polymorphism).
Static Class and Self
type
TCounter = class
class var Total: integer;
class procedure Increment;
end;
class procedure TCounter.Increment;
begin
Total := Total + 1;
end;class members belong to the class and not the instance (shared). Self refers to the current object, like this in other languages.
Destructor
type
TResource = class
destructor Destroy; override;
end;
destructor TResource.Destroy;
begin
WriteLn('Releasing resources');
inherited Destroy;
end;The destructor Destroy (with override) runs when the object is released. It is used to clean up resources. It is called with Free, which checks for nil.
Abstract Methods
type
TShape = class
function Area: real; virtual; abstract;
end;
TCircle = class(TShape)
Radius: real;
function Area: real; override;
end;
function TCircle.Area: real;
begin
Result := 3.14159 * Radius * Radius;
end;An abstract method is declared without implementation and forces subclasses to define it. It turns the base class into a contract (abstract class).
Interfaces
type
ISavable = interface
['{GUID-HERE}']
procedure Save;
end;
TDocument = class(TInterfacedObject, ISavable)
procedure Save;
end;An interface defines a contract without implementation. The class inherits from TInterfacedObject and implements the methods. It supports reference counting.