Cheatsheet Pascal
Linguagem estruturada clássica para ensino e desenvolvimento (Free Pascal/Delphi)
Pascal
Básico e Estrutura
Estrutura do programa
program MeuPrograma;
uses SysUtils;
var
nome: string;
begin
WriteLn('Olá Mundo!');
Write('Nome: ');
ReadLn(nome);
WriteLn('Olá, ', nome);
end.Um programa Pascal começa com program, segue com uses (bibliotecas), var (variáveis) e o bloco begin...end. (com ponto final).
Operadores aritméticos
var a, b: integer; r: real; begin a := 10; b := 3; WriteLn(a + b); // 13 soma WriteLn(a - b); // 7 subtração WriteLn(a * b); // 30 multiplicação WriteLn(a div b); // 3 divisão inteira WriteLn(a mod b); // 1 resto r := a / b; // 3.33 divisão real end.
div é a divisão inteira e mod o resto. O operador / devolve sempre real, mesmo com operandos inteiros.
Operador in (conjunto)
var
x: integer;
c: char;
begin
x := 5;
if x in [1..10] then
WriteLn('entre 1 e 10');
c := 'a';
if c in ['a', 'e', 'i', 'o', 'u'] then
WriteLn('vogal');
end.O operador in verifica pertença a um conjunto. [1..10] é um intervalo e [...] uma lista de valores. Muito usado em validações.
Tipo enumerado simples
type
TDia = (Seg, Ter, Qua, Qui, Sex, Sab, Dom);
var
d: TDia;
begin
d := Seg;
if d = Seg then
WriteLn('Início da semana');
end.Um tipo enumerado lista valores fixos entre parênteses. Torna o código mais legível e seguro do que usar inteiros soltos.
Tipos de dados
var i: integer; // inteiro (32-bit) b: byte; // 0..255 r: real; // número real c: char; // 1 caractere s: string; // string dinâmica ok: boolean; // true/false d: double; // precisão dupla n: int64; // inteiro 64-bit
O Pascal é fortemente tipado: cada variável tem um tipo fixo. integer e int64 para inteiros, real/double para decimais, boolean para lógico.
Operadores de comparação
var x: integer; begin x := 5; WriteLn(x = 5); // true igual WriteLn(x <> 3); // true diferente WriteLn(x > 3); // true maior WriteLn(x <= 5); // true menor ou igual end.
A igualdade é = (um só igual) e a diferença é <>. Os operadores >, <, >= e <= comparam ordem.
Comentários
// comentário de uma linha
{ comentário entre
chavetas }
(* comentário entre
parênteses-asterisco *)
begin
WriteLn('Olá'); // inline
end.O Pascal aceita três formas de comentário: // (linha), { } e (* *) (bloco). Os de bloco podem span várias linhas.
Subintervalos (subrange)
type TNota = 0..20; TVogais = 'a'..'z'; var nota: TNota; begin nota := 15; // nota := 25; // ERRO: fora do intervalo end.
Um subrange restringe uma variável a um intervalo de valores (ex.: 0..20). O compilador pode validar os limites atribuídos.
Variáveis e atribuição
var x, y, z: integer; nome: string; begin x := 10; // atribuição com := y := x * 2; // 20 nome := 'Ana'; z := x + y; end.
A atribuição usa := (dois pontos e igual), diferente de = que é comparação. Várias variáveis do mesmo tipo declaram-se na mesma linha.
Operadores lógicos
var a, b: boolean; begin a := true; b := false; WriteLn(a and b); // false (E) WriteLn(a or b); // true (OU) WriteLn(not a); // false (negação) WriteLn(a xor b); // true (OU exclusivo) end.
Os operadores lógicos são por extenso: and (E), or (OU), not (negação) e xor (OU exclusivo). Operam sobre boolean.
Escrita formatada
var
n: integer;
r: real;
begin
n := 42;
r := 3.14159;
WriteLn(n:5); // " 42" (largura 5)
WriteLn(r:8:2); // " 3.14" (2 casas)
Write('sem ');
WriteLn('quebra'); // mesma linha
end.WriteLn escreve com quebra de linha e Write sem quebra. A sintaxe valor:largura:casas formata a saída alinhada.
Constantes
const PI = 3.14159; MAX = 100; NOME = 'Pascal'; ATIVO = true; begin WriteLn(PI * 2); // PI := 3; // ERRO: constante end.
Constantes declaram-se com const e não podem ser alteradas. O tipo é inferido do valor. Úteis para valores fixos como PI ou limites.
Concatenação de strings
var nome, saudacao: string; begin nome := 'Ana'; saudacao := 'Olá, ' + nome + '!'; WriteLn(saudacao); // Olá, Ana! end.
O operador + concatena strings. Para juntar texto com números, converte primeiro com IntToStr() ou usa WriteLn com vírgulas.
Leitura de dados
var
nome: string;
idade: integer;
begin
Write('Nome: ');
ReadLn(nome);
Write('Idade: ');
ReadLn(idade);
WriteLn('Olá ', nome, ', ', idade);
end.ReadLn lê uma linha do teclado para a variável. Write mostra o prompt sem quebra de linha antes da leitura.
Controlo de Fluxo
If / Else
if idade >= 18 then
WriteLn('Adulto')
else if idade >= 12 then
WriteLn('Adolescente')
else
WriteLn('Criança');O if/else avalia condições em ordem. Não há parênteses obrigatórios e não se usa ponto e vírgula antes do else.
For (crescente)
var
i: integer;
begin
for i := 1 to 10 do
WriteLn(i);
end.O for com to conta de forma crescente. A variável de controlo deve ser um tipo ordinal (inteiro, char, enum). Não a modifiques dentro do ciclo.
Break
var
i: integer;
begin
for i := 1 to 100 do
begin
if i = 50 then
Break; // sai do ciclo
WriteLn(i);
end;
end.O Break termina imediatamente o ciclo (for, while ou repeat) e continua após ele. Útil para sair ao encontrar um resultado.
If com bloco begin/end
if x > 0 then
begin
y := x * 2;
WriteLn('positivo: ', y);
end
else
begin
y := 0;
WriteLn('não positivo');
end;Para executar várias instruções num ramo, agrupa-as com begin...end. Sem o bloco, só a primeira instrução pertence ao if.
For (decrescente)
var
i: integer;
begin
for i := 10 downto 1 do
WriteLn(i);
// 10, 9, 8, ... 1
end.O for com downto conta de forma decrescente. Útil para contagens regressivas ou percorrer arrays do fim para o início.
Continue
var
i: integer;
begin
for i := 1 to 10 do
begin
if i mod 2 = 0 then
Continue; // salta os pares
WriteLn(i); // só ímpares
end;
end.O Continue salta para a próxima iteração do ciclo, ignorando o resto do bloco atual. Aqui imprime apenas os números ímpares.
Case
case dia of
1: WriteLn('Segunda');
2: WriteLn('Terça');
3..5: WriteLn('Meio da semana');
6, 7: WriteLn('Fim de semana');
else
WriteLn('Inválido');
end;O case seleciona por valor. Aceita valores únicos, intervalos (3..5) e listas (6, 7). O else trata os restantes casos.
While
var
x: integer;
begin
x := 5;
while x > 0 do
begin
WriteLn(x);
x := x - 1;
end;
end.O while repete enquanto a condição for verdadeira. Verifica a condição antes de cada iteração, podendo nunca executar o bloco.
Exit
function Dividir(a, b: integer): integer;
begin
if b = 0 then
begin
WriteLn('Divisão por zero');
Exit; // sai da função
end;
Result := a div b;
end;O Exit termina imediatamente a função ou procedure atual. Em funções, pode devolver um valor com Exit(valor) (Delphi/FPC moderno).
Case com string
case comando of
'sair': Close;
'ajuda': ShowHelp;
'gravar': Save;
else
WriteLn('Comando desconhecido');
end;No Free Pascal e Delphi o case também aceita strings. Cada ramo compara com uma constante string. Mais limpo do que vários if.
Repeat / Until
var
x: integer;
begin
x := 0;
repeat
x := x + 1;
WriteLn(x);
until x >= 5;
end.O repeat/until executa o bloco antes de verificar a condição, garantindo pelo menos uma execução. Repete até a condição ser verdadeira.
Ciclos aninhados
var
i, j: integer;
begin
for i := 1 to 3 do
for j := 1 to 3 do
WriteLn('i=', i, ' j=', j);
end.Podes aninhar ciclos para percorrer matrizes ou gerar combinações. Cada nível usa a sua própria variável de controlo (i, j).
Funções e Procedures
Procedure simples
procedure Saudar(nome: string);
begin
WriteLn('Olá, ', nome, '!');
end;
begin
Saudar('Ana');
Saudar('Rui');
end.Uma procedure é um subprograma que executa ações sem devolver valor. Declara-se antes do begin principal e chama-se pelo nome.
Parâmetro const
procedure Imprimir(const s: string); begin WriteLn(s); // s := 'x'; // ERRO: não pode modificar end;
O const passa por referência mas impede modificação. Evita a cópia de tipos grandes (strings, records) mantendo a segurança de leitura.
Parâmetros por defeito
procedure Log(msg: string; nivel: integer = 1);
begin
WriteLn('[', nivel, '] ', msg);
end;
begin
Log('erro', 3); // [3] erro
Log('info'); // [1] info
end.Parâmetros com valor por defeito (ex.: nivel: integer = 1) podem ser omitidos na chamada. Devem vir no fim da lista de parâmetros.
Scope de variáveis
var global: integer; // visível em todo o programa procedure Teste; var local: integer; // só visível aqui begin local := 5; global := local; end;
Variáveis declaradas no topo são globais; dentro de uma rotina são locais. Variáveis locais deixam de existir quando a rotina termina.
Function com retorno
function Somar(a, b: integer): integer; begin Somar := a + b; // retorno pelo nome end; begin WriteLn(Somar(2, 3)); // 5 end.
Uma function devolve um valor, atribuído ao próprio nome da função (aqui Somar := ...). O tipo de retorno vem após :.
Array aberto (open array)
function Soma(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(Soma([1, 2, 3, 4])); // 10
end.Um array of como parâmetro aceita arrays de qualquer tamanho. Low() e High() dão os limites e podes passar literais [...].
Declaração forward
procedure B; forward;
procedure A;
begin
B; // chama B declarada à frente
end;
procedure B;
begin
WriteLn('B');
end;A diretiva forward declara uma rotina antes da sua implementação, permitindo referência mútua entre procedures (ex.: A chama B e B chama A).
Result (forma moderna)
function Quadrado(x: integer): integer; begin Result := x * x; end; function EPar(n: integer): boolean; begin Result := (n mod 2 = 0); end;
A variável especial Result guarda o valor de retorno de forma mais legível. É a forma preferida no Delphi e Free Pascal moderno.
Recursão
function Fatorial(n: integer): int64;
begin
if n <= 1 then
Result := 1
else
Result := n * Fatorial(n - 1);
end;
begin
WriteLn(Fatorial(5)); // 120
end.Uma função recursiva chama-se a si própria. Precisa de um caso base (n <= 1) para terminar. Aqui calcula o fatorial de n.
Funções anónimas (Delphi/FPC)
type
TIntFunc = reference to function(x: integer): integer;
var
dobro: TIntFunc;
begin
dobro := function(x: integer): integer
begin
Result := x * 2;
end;
WriteLn(dobro(5)); // 10
end.Funções anónimas (lambdas) usam reference to function. Podem ser atribuídas a variáveis e passadas como argumentos, como noutras linguagens modernas.
Parâmetro por referência (var)
procedure Incrementar(var x: integer); begin x := x + 1; // altera a variável original end; var n: integer; begin n := 10; Incrementar(n); WriteLn(n); // 11 end.
O var passa o parâmetro por referência: a função altera a variável original. Sem var, recebe apenas uma cópia (por valor).
Overload de funções
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;
O overload permite várias funções com o mesmo nome mas parâmetros diferentes. O compilador escolhe a versão certa pelo tipo dos argumentos.
Funções de ordem superior
type TOperacao = function(a, b: integer): integer; function Aplicar(x, y: integer; op: TOperacao): integer; begin Result := op(x, y); end; function Somar(a, b: integer): integer; begin Result := a + b; end;
Podes passar funções como parâmetros usando um tipo função (function(a,b): integer). Isto permite funções de ordem superior reutilizáveis.
Estruturas de Dados
Array estático
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.Um array estático tem tamanho fixo definido em compilação (array[1..5]). O índice inicial pode ser qualquer valor ordinal, aqui começa em 1.
Record com métodos
type
TPonto = record
x, y: integer;
procedure Mover(dx, dy: integer);
end;
procedure TPonto.Mover(dx, dy: integer);
begin
x := x + dx;
y := y + dy;
end;Records modernos (Delphi/FPC) podem ter métodos e propriedades. A sintaxe TPonto.Mover implementa o método declarado no record.
Sets (conjuntos)
type
TVogais = set of char;
var
v: TVogais;
begin
v := ['a', 'e', 'i', 'o', 'u'];
if 'a' in v then
WriteLn('é vogal');
end.Um set guarda valores únicos de um tipo ordinal. O operador in verifica pertença. Útil para flags e coleções pequenas.
TDictionary
uses Generics.Collections;
var
dict: TDictionary<string, integer>;
begin
dict := TDictionary<string, integer>.Create;
try
dict.Add('Ana', 30);
dict.Add('Rui', 25);
WriteLn(dict['Ana']); // 30
finally
dict.Free;
end;
end.TDictionary<K,V> guarda pares chave-valor. Acede ao valor pela chave (ex.: dict["Ana"]). Equivalente a um mapa/hashtable.
Array dinâmico
var dyn: array of integer; begin SetLength(dyn, 5); // aloca 5 elementos dyn[0] := 10; // começa em 0 dyn[4] := 50; WriteLn(Length(dyn)); // 5 WriteLn(Low(dyn)); // 0 WriteLn(High(dyn)); // 4 end.
Um array dinâmico (array of) é redimensionável com SetLength. Começa sempre no índice 0. Length, Low e High dão os limites.
Variant record
type
TForma = record
case tipo: char of
'c': (raio: real);
'r': (larg, alt: real);
end;
var
f: TForma;
begin
f.tipo := 'c';
f.raio := 5.0;
end.Um variant record tem campos que partilham memória conforme um campo discriminante (case). Semelhante a uma union em C.
Operações de sets
var A, B, C: set of integer; begin A := [1, 2, 3]; B := [2, 3, 4]; C := A + B; // união [1,2,3,4] C := A - B; // diferença [1] C := A * B; // interseção [2,3] end.
Os sets suportam operações matemáticas: + (união), - (diferença) e * (interseção). Ideais para lógica de conjuntos.
Constantes array e record
const
Dias: array[1..7] of string =
('Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab', 'Dom');
Origem: TPonto = (x: 0; y: 0);
begin
WriteLn(Dias[1]); // Seg
end.Podes criar arrays e records constantes com valores iniciais fixos. Arrays usam (...) e records usam (campo: valor; ...).
Array multidimensional
var
matriz: array[1..3, 1..3] of integer;
i, j: integer;
begin
for i := 1 to 3 do
for j := 1 to 3 do
matriz[i, j] := i * j;
WriteLn(matriz[2, 3]); // 6
end.Um array multidimensional usa vários índices separados por vírgula (array[1..3, 1..3]). Ideal para matrizes e grelhas bidimensionais.
With (atalho de record)
var
p: TPessoa;
begin
with p do
begin
nome := 'Ana';
idade := 30;
ativo := true;
end;
end.O with evita repetir o nome do record ao aceder a vários campos. Dentro do bloco, nome refere-se a p.nome. Usar com moderação.
TStringList
uses Classes;
var
lista: TStringList;
begin
lista := TStringList.Create;
try
lista.Add('item1');
lista.Add('item2');
WriteLn(lista.Count); // 2
WriteLn(lista.IndexOf('item1')); // 0
finally
lista.Free;
end;
end.TStringList é uma lista dinâmica de strings da RTL. Oferece Add, IndexOf, Sort e Count. Cria com Create e liberta com Free.
Record simples
type
TPessoa = record
nome: string;
idade: integer;
ativo: boolean;
end;
var
p: TPessoa;
begin
p.nome := 'Ana';
p.idade := 30;
p.ativo := true;
end.Um record agrupa campos de tipos diferentes numa estrutura. Acede-se aos campos com ponto (p.nome). É o equivalente a uma struct.
Enumerados (enum)
type
TCor = (Vermelho, Verde, Azul);
var
c: TCor;
begin
c := Verde;
if c = Verde then
WriteLn('Verde');
WriteLn(Ord(c)); // 1 (posição)
end.Um enumerado define um conjunto ordenado de valores nomeados. Ord() devolve a posição (começa em 0). Mais legível do que inteiros.
Genéricos (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.Genéricos (TList<integer>) criam coleções tipadas seguras. Generics.Collections traz TList, TDictionary e outras listas dinâmicas.
Strings e Conversões
Length e Copy
var s: string; begin s := 'Olá Mundo'; WriteLn(Length(s)); // 9 WriteLn(Copy(s, 1, 3)); // 'Olá' WriteLn(Copy(s, 5, 5)); // 'Mundo' end.
Length() devolve o número de caracteres. Copy(s, inicio, n) extrai uma substring a partir de inicio com n caracteres.
StringReplace
uses SysUtils;
var
s: string;
begin
s := 'ola mundo ola';
s := StringReplace(s, 'ola', 'olá',
[rfReplaceAll, rfIgnoreCase]);
WriteLn(s); // 'olá mundo olá'
end.StringReplace() substitui texto. rfReplaceAll troca todas as ocorrências e rfIgnoreCase ignora maiúsculas/minúsculas.
Format
uses SysUtils;
begin
WriteLn(Format('%d anos', [30]));
WriteLn(Format('%.2f', [3.14159])); // 3.14
WriteLn(Format('%s tem %d', ['Ana', 30]));
WriteLn(Format('%8d', [42])); // alinhado
end.Format() constrói strings com marcadores: %d (inteiro), %f (real), %s (string). O .2 define casas decimais.
Maiúsculas e minúsculas
uses SysUtils; var s: string; begin s := 'Olá Mundo'; WriteLn(UpperCase(s)); // 'OLÁ MUNDO' WriteLn(LowerCase(s)); // 'olá mundo' end.
UpperCase() converte para maiúsculas e LowerCase() para minúsculas. Estão na unit SysUtils.
Trim
uses SysUtils; var s: string; begin s := ' texto '; WriteLn(Trim(s)); // 'texto' WriteLn(TrimLeft(s)); // 'texto ' WriteLn(TrimRight(s)); // ' texto' end.
Trim() remove espaços no início e no fim. TrimLeft() só à esquerda e TrimRight() só à direita. Essencial para limpar input.
Char: Ord e Chr
var
c: char;
n: integer;
begin
n := Ord('A'); // 65 (código ASCII)
c := Chr(65); // 'A'
c := Chr(Ord('a') - 32); // 'A'
WriteLn(Succ('A')); // 'B'
WriteLn(Pred('B')); // 'A'
end.Ord() devolve o código numérico do caractere e Chr() faz o inverso. Succ() e Pred() dão o seguinte/anterior.
Pos (procurar)
var
s: string;
p: integer;
begin
s := 'Olá Mundo';
p := Pos('Mundo', s);
WriteLn(p); // 5 (posição)
if Pos('xyz', s) = 0 then
WriteLn('não encontrado');
end.Pos(sub, s) devolve a posição da primeira ocorrência (começa em 1) ou 0 se não encontrar. Útil para verificar presença.
String para número
uses SysUtils;
var
n: integer;
r: real;
begin
n := StrToInt('42'); // 42
r := StrToFloat('3.14'); // 3.14
n := StrToIntDef('abc', 0); // 0 (seguro)
end.StrToInt() e StrToFloat() convertem strings em números e lançam exceção se inválidas. StrToIntDef() devolve um valor por defeito em vez de falhar.
Concat e Length
var a, b, c: string; begin a := 'Olá'; b := 'Mundo'; c := Concat(a, ' ', b); WriteLn(c); // 'Olá Mundo' WriteLn(Length(c)); // 9 end.
Concat() junta várias strings numa só (alternativa ao +). Length() devolve o comprimento. Strings em Pascal são dinâmicas.
Delete e Insert
var
s: string;
begin
s := 'Olá Mundo';
Delete(s, 1, 4); // remove 4 chars
WriteLn(s); // 'Mundo'
Insert('!', s, 6);
WriteLn(s); // 'Mundo!'
end.Delete(s, inicio, n) remove n caracteres (modifica a string). Insert(txt, s, pos) insere texto na posição indicada.
Número para 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() e FloatToStr() convertem números em strings. FloatToStrF() permite controlar o formato e as casas decimais.
String com aspas (escape)
var s: string; begin s := 'Ele disse ''olá'''; WriteLn(s); // Ele disse 'olá' s := 'Linha1' + #13#10 + 'Linha2'; WriteLn(s); // duas linhas end.
Para incluir uma aspa simples numa string, duplica-a (''). #13#10 insere quebra de linha (CR+LF) usando códigos de caractere.
Ponteiros, Units e Exceções
Ponteiros básicos
var p: ^integer; x: integer; begin x := 42; p := @x; // endereço de x WriteLn(p^); // 42 (dereference) p^ := 100; // altera x WriteLn(x); // 100 end.
Um ponteiro (^integer) guarda um endereço. @x obtém o endereço e p^ acede ao valor apontado (dereference).
Usar uma Unit
program Principal; uses MinhaUnit, SysUtils; begin WriteLn(Somar(2, 3)); // da MinhaUnit end.
A cláusula uses importa units para aceder às suas funções e tipos. Pode aparecer no programa ou noutra unit (interface ou implementation).
Exceção personalizada
type
ESaldoInsuficiente = class(Exception)
constructor Create(valor: real);
end;
constructor ESaldoInsuficiente.Create(valor: real);
begin
inherited CreateFmt('Saldo insuficiente: %.2f',
[valor]);
end;Cria classes que herdam de Exception para erros específicos. CreateFmt formata a mensagem com parâmetros, como o Format.
Operações bitwise
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 (deslocar) end.
Os operadores bit a bit and, or, xor, shl e shr operam sobre os bits do inteiro. Úteis para flags e máscaras.
Memória dinâmica
var p: ^integer; begin New(p); // alocar memória p^ := 100; WriteLn(p^); Dispose(p); // libertar memória p := nil; end.
New() aloca memória para o tipo apontado e Dispose() liberta-a. Define o ponteiro como nil depois para evitar acessos inválidos.
Try / Except
var
x: integer;
begin
try
x := StrToInt('abc');
except
on E: EConvertError do
WriteLn('Número inválido');
on E: Exception do
WriteLn('Erro: ', E.Message);
end;
end.try..except captura exceções. O on E: Tipo trata cada tipo de exceção. E.Message dá a descrição do erro.
Constantes tipadas
const Limiar: integer = 100; // mutável (FPC) begin Limiar := 200; // permitido WriteLn(Limiar); end.
Constantes tipadas (nome: tipo = valor) são na verdade variáveis estáticas inicializadas: mantêm o valor entre chamadas e podem ser alteradas.
Programa completo (exemplo)
program Media;
uses SysUtils;
var
notas: array of integer;
i, soma: integer;
begin
SetLength(notas, 3);
soma := 0;
for i := 0 to High(notas) do
begin
notas[i] := Random(20) + 1;
soma := soma + notas[i];
end;
WriteLn('Média: ', soma / Length(notas):0:1);
end.Exemplo completo: aloca um array dinâmico, preenche com Random, soma e calcula a média. Mostra a estrutura típica de um programa Pascal.
GetMem e FreeMem
var ptr: Pointer; begin GetMem(ptr, 1024); // 1024 bytes // usar ptr... FreeMem(ptr); // libertar ptr := nil; end.
GetMem() aloca um bloco de bytes em bruto e FreeMem() liberta. Mais flexível do que New para buffers de tamanho variável.
Try / Finally
var
lista: TStringList;
begin
lista := TStringList.Create;
try
lista.Add('item');
WriteLn(lista.Count);
finally
lista.Free; // executa sempre
end;
end.try..finally garante a execução do bloco finally mesmo com erro. É o padrão para libertar recursos (memória, ficheiros, objetos).
Diretivas de compilação
{$IFDEF DEBUG}
WriteLn('Modo debug ativo');
{$ENDIF}
{$MODE DELPHI} // modo Delphi (FPC)
{$RANGECHECKS ON} // verifica índices
begin
WriteLn('Olá');
end.Diretivas {$...} controlam a compilação. {$IFDEF} compila condicionalmente, {$MODE} define compatibilidade e {$RANGECHECKS} valida índices.
Estrutura de uma Unit
unit MinhaUnit; interface uses SysUtils; function Somar(a, b: integer): integer; implementation function Somar(a, b: integer): integer; begin Result := a + b; end; end.
Uma unit é um módulo reutilizável. A secção interface declara o que é público e implementation contém o código. Usa-se com uses.
Raise (lançar exceção)
procedure Validar(idade: integer);
begin
if idade < 0 then
raise Exception.Create('Idade inválida');
end;raise lança uma exceção manualmente. Exception.Create(msg) cria a exceção com uma mensagem. Interrompe o fluxo até ao except mais próximo.
Type aliases
type TNome = string; TIdade = integer; TMatriz = array of array of real; var nome: TNome; m: TMatriz; begin nome := 'Ana'; end.
O type cria nomes alternativos para tipos existentes, melhorando a legibilidade. TNome é apenas um alias para string.
Entrada/Saída e Ficheiros
Write e WriteLn
begin
Write('Sem quebra ');
WriteLn('com quebra');
WriteLn('A', 'B', 'C'); // ABC
WriteLn(10, ' ', 20); // 10 20
WriteLn(3.14:6:2); // 3.14
end.Write imprime sem mudar de linha e WriteLn muda. Aceitam vários argumentos separados por vírgulas e formatação :largura:casas.
Append (acrescentar)
var f: TextFile; begin AssignFile(f, 'log.txt'); Append(f); // acrescentar no fim WriteLn(f, 'Nova entrada'); CloseFile(f); end.
Append abre um ficheiro existente para acrescentar no fim, sem apagar o conteúdo anterior. Ideal para ficheiros de log.
Verificar existência
uses SysUtils;
begin
if FileExists('dados.txt') then
WriteLn('existe')
else
WriteLn('não existe');
if DirectoryExists('C:\temp') then
WriteLn('pasta existe');
end.FileExists() verifica se um ficheiro existe e DirectoryExists() se uma pasta existe. Estão na unit SysUtils.
Read e ReadLn
var nome: string; idade: integer; begin ReadLn(nome); // lê uma linha ReadLn(idade); // lê um inteiro WriteLn(nome, ' ', idade); end.
ReadLn lê uma linha completa do teclado e converte para o tipo da variável. Read lê sem consumir a quebra de linha.
Ficheiro binário (tipado)
type
TRegisto = record
id: integer;
nome: string[50];
end;
var
f: file of TRegisto;
reg: TRegisto;
begin
AssignFile(f, 'dados.dat');
Rewrite(f);
reg.id := 1;
reg.nome := 'Ana';
Write(f, reg);
CloseFile(f);
end.Um file of TRegisto guarda registos de tamanho fixo em binário. Write(f, reg) e Read(f, reg) leem/escrevem registos completos.
Apagar e renomear
var f: TextFile; begin AssignFile(f, 'antigo.txt'); Erase(f); // apaga o ficheiro AssignFile(f, 'novo.txt'); Rename(f, 'novo2.txt'); // renomeia end.
Erase() apaga o ficheiro associado e Rename() muda o nome. A variável deve estar associada com AssignFile mas não aberta.
Escrever ficheiro de texto
var f: TextFile; begin AssignFile(f, 'dados.txt'); Rewrite(f); // criar/escrever WriteLn(f, 'Linha 1'); WriteLn(f, 'Linha 2'); CloseFile(f); end.
AssignFile associa a variável ao ficheiro, Rewrite abre para escrita (cria novo), escreve com WriteLn(f, ...) e fecha com CloseFile.
Ler ficheiro binário
var
f: file of TRegisto;
reg: TRegisto;
begin
AssignFile(f, 'dados.dat');
Reset(f);
while not EOF(f) do
begin
Read(f, reg);
WriteLn(reg.id, ' ', reg.nome);
end;
CloseFile(f);
end.A leitura binária usa Read(f, reg) dentro de while not EOF(f). Cada iteração carrega um registo completo da estrutura.
TFileStream
uses Classes, SysUtils;
var
fs: TFileStream;
s: string;
begin
fs := TFileStream.Create('dados.bin',
fmCreate);
try
s := 'Olá';
fs.WriteBuffer(s[1], Length(s));
finally
fs.Free;
end;
end.TFileStream dá controlo total sobre leitura/escrita binária. fmCreate cria o ficheiro e WriteBuffer escreve bytes em bruto.
Ler ficheiro de texto
var
f: TextFile;
linha: string;
begin
AssignFile(f, 'dados.txt');
Reset(f); // abrir para leitura
while not EOF(f) do
begin
ReadLn(f, linha);
WriteLn(linha);
end;
CloseFile(f);
end.Reset abre o ficheiro para leitura. O ciclo while not EOF(f) percorre até ao fim, lendo cada linha com ReadLn(f, linha).
Tamanho e posição (binário)
var f: file of TRegisto; begin AssignFile(f, 'dados.dat'); Reset(f); WriteLn(FileSize(f)); // nº de registos Seek(f, 2); // ir ao registo 2 WriteLn(FilePos(f)); // posição atual CloseFile(f); end.
FileSize() devolve o número de registos e FilePos() a posição atual. Seek(f, n) move para o registo n (acesso aleatório).
Parâmetros de linha de comandos
var
i: integer;
begin
WriteLn('Nº args: ', ParamCount);
for i := 1 to ParamCount do
WriteLn(ParamStr(i));
end.ParamCount devolve o número de argumentos da linha de comandos e ParamStr(i) cada argumento. ParamStr(0) é o nome do executável.
Classes e OOP
Classe básica
type
TPessoa = class
Nome: string;
Idade: integer;
procedure Apresentar;
end;
procedure TPessoa.Apresentar;
begin
WriteLn(Nome, ', ', Idade);
end;Uma classe declara-se com class e contém campos e métodos. Os métodos implementam-se fora com TPessoa.Apresentar. Instancia-se com Create.
Private e public
type
TConta = class
private
FSaldo: real; // oculto do exterior
public
procedure Depositar(v: real);
function Saldo: real;
end;private restringe o acesso ao interior da classe (encapsulamento). public torna os membros acessíveis de fora. Campos privados usam prefixo F.
inherited
procedure TCao.Falar;
begin
inherited Falar; // chama o da superclasse
WriteLn('... e abana a cauda');
end;inherited chama a versão do método na superclasse. Útil para estender comportamento em vez de o substituir por completo.
Polimorfismo
var
formas: array of TForma;
f: TForma;
begin
SetLength(formas, 2);
formas[0] := TCirculo.Create;
formas[1] := TQuadrado.Create;
for f in formas do
WriteLn(f.Area); // chama o certo
end.Com métodos virtual/override, a mesma chamada (f.Area) executa a implementação correta conforme o tipo real do objeto em runtime.
Criar e libertar objeto
var
p: TPessoa;
begin
p := TPessoa.Create;
try
p.Nome := 'Ana';
p.Idade := 30;
p.Apresentar;
finally
p.Free; // libertar memória
end;
end.Objetos criam-se com Create e devem ser libertados com Free. O try..finally garante a libertação mesmo se houver erro.
Properties
type
TPessoa = class
private
FNome: string;
public
property Nome: string read FNome write FNome;
property SoLeitura: string read FNome;
end;Uma property expõe campos com read e write, controlando o acesso. Pode ligar-se a métodos getter/setter para validação.
is e as
var
a: TAnimal;
begin
a := TCao.Create;
if a is TCao then
WriteLn('é um cão');
(a as TCao).Latir;
a.Free;
end.is verifica o tipo em runtime e as faz cast seguro (lança exceção se falhar). Essenciais para trabalhar com polimorfismo.
for in (coleções)
var
lista: TList<integer>;
n: integer;
begin
lista := TList<integer>.Create;
lista.AddRange([1, 2, 3]);
for n in lista do
WriteLn(n);
lista.Free;
end.O for in percorre coleções e arrays de forma limpa, sem índices. Funciona com arrays dinâmicos, TList e outros enumeráveis.
Constructor
type
TPessoa = class
Nome: string;
constructor Create(n: string);
end;
constructor TPessoa.Create(n: string);
begin
inherited Create;
Nome := n;
end;
var p: TPessoa;
begin
p := TPessoa.Create('Ana');
end.O constructor inicializa o objeto na criação. inherited Create chama o construtor da classe base. Permite passar parâmetros iniciais.
Herança
type
TAnimal = class
procedure Falar; virtual;
end;
TCao = class(TAnimal)
procedure Falar; override;
end;
procedure TCao.Falar;
begin
WriteLn('Au au!');
end;A herança usa class(TAnimal). virtual marca o método como redefinível e override reimplementa-o na subclasse (polimorfismo).
Classe estática e Self
type
TContador = class
class var Total: integer;
class procedure Incrementar;
end;
class procedure TContador.Incrementar;
begin
Total := Total + 1;
end;Membros class pertencem à classe e não à instância (partilhados). Self refere o objeto atual, como this noutras linguagens.
Destructor
type
TRecurso = class
destructor Destroy; override;
end;
destructor TRecurso.Destroy;
begin
WriteLn('A libertar recursos');
inherited Destroy;
end;O destructor Destroy (com override) executa ao libertar o objeto. Usa-se para limpar recursos. Chama-se com Free, que verifica nil.
Métodos abstract
type
TForma = class
function Area: real; virtual; abstract;
end;
TCirculo = class(TForma)
Raio: real;
function Area: real; override;
end;
function TCirculo.Area: real;
begin
Result := 3.14159 * Raio * Raio;
end;Um método abstract declara-se sem implementação e obriga as subclasses a defini-lo. Torna a classe base num contrato (classe abstrata).
Interfaces
type
IGravavel = interface
['{GUID-AQUI}']
procedure Gravar;
end;
TDocumento = class(TInterfacedObject, IGravavel)
procedure Gravar;
end;Uma interface define um contrato sem implementação. A classe herda de TInterfacedObject e implementa os métodos. Suporta contagem de referências.