DevTools

Cheatsheet Pascal

Linguagem estruturada clássica para ensino e desenvolvimento (Free Pascal/Delphi)

Volver a los lenguajes
Pascal
105 tarjetas encontradas
Categorías:
Versiones:

Básico e Estrutura


14 cards
Estructura del programa
program MiPrograma;

uses SysUtils;

var
  nombre: string;

begin
  WriteLn('¡Hola Mundo!');
  Write('Nombre: ');
  ReadLn(nombre);
  WriteLn('Hola, ', nombre);
end.

Un programa Pascal comienza con program, sigue con uses (bibliotecas), var (variables) y el bloque begin...end. (con punto final).

Operadores aritméticos
var
  a, b: integer;
  r: real;

begin
  a := 10; b := 3;
  WriteLn(a + b);   // 13 suma
  WriteLn(a - b);   // 7  resta
  WriteLn(a * b);   // 30 multiplicación
  WriteLn(a div b); // 3  división entera
  WriteLn(a mod b); // 1  resto
  r := a / b;       // 3.33 división real
end.

div es la división entera y mod el resto. El operador / devuelve siempre real, incluso con operandos enteros.

Operador in (conjunto)
var
  x: integer;
  c: char;

begin
  x := 5;
  if x in [1..10] then
    WriteLn('entre 1 y 10');

  c := 'a';
  if c in ['a', 'e', 'i', 'o', 'u'] then
    WriteLn('vocal');
end.

El operador in verifica pertenencia a un conjunto. [1..10] es un intervalo y [...] una lista de valores. Muy usado en validaciones.

Tipo enumerado simple
type
  TDia = (Lun, Mar, Mie, Jue, Vie, Sab, Dom);

var
  d: TDia;

begin
  d := Lun;
  if d = Lun then
    WriteLn('Inicio de la semana');
end.

Un tipo enumerado lista valores fijos entre paréntesis. Hace el código más legible y seguro que usar enteros sueltos.

Tipos de datos
var
  i: integer;    // entero (32-bit)
  b: byte;       // 0..255
  r: real;       // número real
  c: char;       // 1 carácter
  s: string;     // string dinámica
  ok: boolean;   // true/false
  d: double;     // precisión doble
  n: int64;      // entero 64-bit

Pascal es fuertemente tipado: cada variable tiene un tipo fijo. integer e int64 para enteros, real/double para decimales, boolean para lógico.

Operadores de comparación
var
  x: integer;

begin
  x := 5;
  WriteLn(x = 5);   // true  igual
  WriteLn(x <> 3);  // true  diferente
  WriteLn(x > 3);   // true  mayor
  WriteLn(x <= 5);  // true  menor o igual
end.

La igualdad es = (un solo igual) y la diferencia es <>. Los operadores >, <, >= y <= comparan orden.

Comentarios
// comentario de una línea

{ comentario entre
  llaves }

(* comentario entre
   paréntesis-asterisco *)

begin
  WriteLn('Hola'); // inline
end.

Pascal acepta tres formas de comentario: // (línea), { } y (* *) (bloque). Los de bloque pueden abarcar varias líneas.

Subintervalos (subrange)
type
  TNota = 0..20;
  TVocales = 'a'..'z';

var
  nota: TNota;

begin
  nota := 15;
  // nota := 25;  // ERROR: fuera del intervalo
end.

Un subrange restringe una variable a un intervalo de valores (ej.: 0..20). El compilador puede validar los límites asignados.

Variables y asignación
var
  x, y, z: integer;
  nombre: string;

begin
  x := 10;       // asignación con :=
  y := x * 2;    // 20
  nombre := 'Ana';
  z := x + y;
end.

La asignación usa := (dos puntos e igual), diferente de = que es comparación. Varias variables del mismo tipo se declaran en la misma línea.

Operadores lógicos
var
  a, b: boolean;

begin
  a := true; b := false;
  WriteLn(a and b);  // false (Y)
  WriteLn(a or b);   // true  (O)
  WriteLn(not a);    // false (negación)
  WriteLn(a xor b);  // true  (O exclusivo)
end.

Los operadores lógicos son con palabras: and (Y), or (O), not (negación) y xor (O exclusivo). Operan sobre boolean.

Escritura formateada
var
  n: integer;
  r: real;

begin
  n := 42;
  r := 3.14159;
  WriteLn(n:5);     // "   42" (ancho 5)
  WriteLn(r:8:2);   // "    3.14" (2 decimales)
  Write('sin ');
  WriteLn('salto'); // misma línea
end.

WriteLn escribe con salto de línea y Write sin salto. La sintaxis valor:ancho:decimales formatea la salida alineada.

Constantes
const
  PI = 3.14159;
  MAX = 100;
  NOMBRE = 'Pascal';
  ACTIVO = true;

begin
  WriteLn(PI * 2);
  // PI := 3;  // ERROR: constante
end.

Las constantes se declaran con const y no pueden ser alteradas. El tipo se infiere del valor. Útiles para valores fijos como PI o límites.

Concatenación de strings
var
  nombre, saludo: string;

begin
  nombre := 'Ana';
  saludo := 'Hola, ' + nombre + '!';
  WriteLn(saludo);  // Hola, Ana!
end.

El operador + concatena strings. Para juntar texto con números, convierte primero con IntToStr() o usa WriteLn con comas.

Lectura de datos
var
  nombre: string;
  edad: integer;

begin
  Write('Nombre: ');
  ReadLn(nombre);

  Write('Edad: ');
  ReadLn(edad);

  WriteLn('Hola ', nombre, ', ', edad);
end.

ReadLn lee una línea del teclado hacia la variable. Write muestra el prompt sin salto de línea antes de la lectura.

Controlo de Fluxo


12 cards
If / Else
if edad >= 18 then
  WriteLn('Adulto')
else if edad >= 12 then
  WriteLn('Adolescente')
else
  WriteLn('Niño');

El if/else evalúa condiciones en orden. No hay paréntesis obligatorios y no se usa punto y coma antes del else.

For (creciente)
var
  i: integer;

begin
  for i := 1 to 10 do
    WriteLn(i);
end.

El for con to cuenta de forma creciente. La variable de control debe ser un tipo ordinal (entero, char, enum). No la modifiques dentro del bucle.

Break
var
  i: integer;

begin
  for i := 1 to 100 do
  begin
    if i = 50 then
      Break;  // sale del bucle
    WriteLn(i);
  end;
end.

El Break termina inmediatamente el bucle (for, while o repeat) y continúa después de él. Útil para salir al encontrar un resultado.

If con bloque begin/end
if x > 0 then
begin
  y := x * 2;
  WriteLn('positivo: ', y);
end
else
begin
  y := 0;
  WriteLn('no positivo');
end;

Para ejecutar varias instrucciones en una rama, agrúpalas con begin...end. Sin el bloque, solo la primera instrucción pertenece al if.

For (decreciente)
var
  i: integer;

begin
  for i := 10 downto 1 do
    WriteLn(i);
  // 10, 9, 8, ... 1
end.

El for con downto cuenta de forma decreciente. Útil para cuentas regresivas o recorrer arrays del final al inicio.

Continue
var
  i: integer;

begin
  for i := 1 to 10 do
  begin
    if i mod 2 = 0 then
      Continue;  // salta los pares
    WriteLn(i);  // solo impares
  end;
end.

El Continue salta a la siguiente iteración del bucle, ignorando el resto del bloque actual. Aquí imprime solo los números impares.

Case
case dia of
  1: WriteLn('Lunes');
  2: WriteLn('Martes');
  3..5: WriteLn('Mitad de semana');
  6, 7: WriteLn('Fin de semana');
else
  WriteLn('Inválido');
end;

El case selecciona por valor. Acepta valores únicos, intervalos (3..5) y listas (6, 7). El else trata los demás casos.

While
var
  x: integer;

begin
  x := 5;
  while x > 0 do
  begin
    WriteLn(x);
    x := x - 1;
  end;
end.

El while repite mientras la condición sea verdadera. Verifica la condición antes de cada iteración, pudiendo no ejecutar nunca el bloque.

Exit
function Dividir(a, b: integer): integer;
begin
  if b = 0 then
  begin
    WriteLn('División por cero');
    Exit;  // sale de la función
  end;
  Result := a div b;
end;

El Exit termina inmediatamente la función o procedure actual. En funciones, puede devolver un valor con Exit(valor) (Delphi/FPC moderno).

Case con string
case comando of
  'salir':  Close;
  'ayuda':  ShowHelp;
  'guardar': Save;
else
  WriteLn('Comando desconocido');
end;

En Free Pascal y Delphi el case también acepta strings. Cada rama compara con una constante string. Más limpio que varios if.

Repeat / Until
var
  x: integer;

begin
  x := 0;
  repeat
    x := x + 1;
    WriteLn(x);
  until x >= 5;
end.

El repeat/until ejecuta el bloque antes de verificar la condición, garantizando al menos una ejecución. Repite hasta que la condición sea verdadera.

Bucles anidados
var
  i, j: integer;

begin
  for i := 1 to 3 do
    for j := 1 to 3 do
      WriteLn('i=', i, ' j=', j);
end.

Puedes anidar bucles para recorrer matrices o generar combinaciones. Cada nivel usa su propia variable de control (i, j).

Funções e Procedures


13 cards
Procedure simple
procedure Saludar(nombre: string);
begin
  WriteLn('Hola, ', nombre, '!');
end;

begin
  Saludar('Ana');
  Saludar('Ray');
end.

Una procedure es un subprograma que ejecuta acciones sin devolver valor. Se declara antes del begin principal y se llama por el nombre.

Parámetro const
procedure Imprimir(const s: string);
begin
  WriteLn(s);
  // s := 'x';  // ERROR: no puede modificar
end;

El const pasa por referencia pero impide la modificación. Evita la copia de tipos grandes (strings, records) manteniendo la seguridad de lectura.

Parámetros por defecto
procedure Log(msg: string; nivel: integer = 1);
begin
  WriteLn('[', nivel, '] ', msg);
end;

begin
  Log('error', 3);  // [3] error
  Log('info');      // [1] info
end.

Los parámetros con valor por defecto (ej.: nivel: integer = 1) pueden omitirse en la llamada. Deben ir al final de la lista de parámetros.

Scope de variables
var
  global: integer;  // visible en todo el programa

procedure Prueba;
var
  local: integer;  // solo visible aquí
begin
  local := 5;
  global := local;
end;

Las variables declaradas arriba son globales; dentro de una rutina son locales. Las variables locales dejan de existir cuando la rutina termina.

Function con retorno
function Sumar(a, b: integer): integer;
begin
  Sumar := a + b;  // retorno por el nombre
end;

begin
  WriteLn(Sumar(2, 3));  // 5
end.

Una function devuelve un valor, asignado al propio nombre de la función (aquí Sumar := ...). El tipo de retorno va después de :.

Array abierto (open array)
function Suma(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(Suma([1, 2, 3, 4]));  // 10
end.

Un array of como parámetro acepta arrays de cualquier tamaño. Low() y High() dan los límites y puedes pasar literales [...].

Declaración forward
procedure B; forward;

procedure A;
begin
  B;  // llama a B declarada más adelante
end;

procedure B;
begin
  WriteLn('B');
end;

La directiva forward declara una rutina antes de su implementación, permitiendo referencia mutua entre procedures (ej.: A llama a B y B llama a A).

Result (forma moderna)
function Cuadrado(x: integer): integer;
begin
  Result := x * x;
end;

function EsPar(n: integer): boolean;
begin
  Result := (n mod 2 = 0);
end;

La variable especial Result guarda el valor de retorno de forma más legible. Es la forma preferida en Delphi y Free Pascal moderno.

Recursión
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.

Una función recursiva se llama a sí misma. Necesita un caso base (n <= 1) para terminar. Aquí calcula el factorial de n.

Funciones anónimas (Delphi/FPC)
type
  TIntFunc = reference to function(x: integer): integer;

var
  doble: TIntFunc;

begin
  doble := function(x: integer): integer
  begin
    Result := x * 2;
  end;

  WriteLn(doble(5));  // 10
end.

Las funciones anónimas (lambdas) usan reference to function. Pueden asignarse a variables y pasarse como argumentos, como en otros lenguajes modernos.

Parámetro por referencia (var)
procedure Incrementar(var x: integer);
begin
  x := x + 1;  // altera la variable original
end;

var
  n: integer;
begin
  n := 10;
  Incrementar(n);
  WriteLn(n);  // 11
end.

El var pasa el parámetro por referencia: la función altera la variable original. Sin var, recibe solo una copia (por valor).

Overload de funciones
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;

El overload permite varias funciones con el mismo nombre pero parámetros diferentes. El compilador elige la versión correcta por el tipo de los argumentos.

Funciones de orden superior
type
  TOperacion = function(a, b: integer): integer;

function Aplicar(x, y: integer; op: TOperacion): integer;
begin
  Result := op(x, y);
end;

function Sumar(a, b: integer): integer;
begin
  Result := a + b;
end;

Puedes pasar funciones como parámetros usando un tipo función (function(a,b): integer). Esto permite funciones de orden superior reutilizables.

Estruturas de Dados


14 cards
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.

Un array estático tiene tamaño fijo definido en compilación (array[1..5]). El índice inicial puede ser cualquier valor ordinal, aquí empieza en 1.

Record con métodos
type
  TPunto = record
    x, y: integer;
    procedure Mover(dx, dy: integer);
  end;

procedure TPunto.Mover(dx, dy: integer);
begin
  x := x + dx;
  y := y + dy;
end;

Los records modernos (Delphi/FPC) pueden tener métodos y propiedades. La sintaxis TPunto.Mover implementa el método declarado en el record.

Sets (conjuntos)
type
  TVocales = set of char;

var
  v: TVocales;

begin
  v := ['a', 'e', 'i', 'o', 'u'];
  if 'a' in v then
    WriteLn('es vocal');
end.

Un set guarda valores únicos de un tipo ordinal. El operador in verifica pertenencia. Útil para flags y colecciones pequeñas.

TDictionary
uses Generics.Collections;

var
  dict: TDictionary<string, integer>;
begin
  dict := TDictionary<string, integer>.Create;
  try
    dict.Add('Ana', 30);
    dict.Add('Ray', 25);
    WriteLn(dict['Ana']);  // 30
  finally
    dict.Free;
  end;
end.

TDictionary<K,V> guarda pares clave-valor. Accede al valor por la clave (ej.: dict["Ana"]). Equivalente a un mapa/hashtable.

Array dinámico
var
  dyn: array of integer;

begin
  SetLength(dyn, 5);  // asigna 5 elementos
  dyn[0] := 10;       // empieza en 0
  dyn[4] := 50;

  WriteLn(Length(dyn));  // 5
  WriteLn(Low(dyn));     // 0
  WriteLn(High(dyn));    // 4
end.

Un array dinámico (array of) es redimensionable con SetLength. Empieza siempre en el índice 0. Length, Low y High dan los límites.

Variant record
type
  TForma = record
    case tipo: char of
      'c': (radio: real);
      'r': (ancho, alto: real);
  end;

var
  f: TForma;
begin
  f.tipo := 'c';
  f.radio := 5.0;
end.

Un variant record tiene campos que comparten memoria según un campo discriminante (case). Similar a una union en C.

Operaciones de sets
var
  A, B, C: set of integer;

begin
  A := [1, 2, 3];
  B := [2, 3, 4];
  C := A + B;  // unión [1,2,3,4]
  C := A - B;  // diferencia [1]
  C := A * B;  // intersección [2,3]
end.

Los sets soportan operaciones matemáticas: + (unión), - (diferencia) y * (intersección). Ideales para lógica de conjuntos.

Constantes array y record
const
  Días: array[1..7] of string =
    ('Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab', 'Dom');

  Origen: TPunto = (x: 0; y: 0);

begin
  WriteLn(Días[1]);  // Lun
end.

Puedes crear arrays y records constantes con valores iniciales fijos. Los arrays usan (...) y los records usan (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.

Un array multidimensional usa varios índices separados por coma (array[1..3, 1..3]). Ideal para matrices y cuadrículas bidimensionales.

With (atajo de record)
var
  p: TPersona;

begin
  with p do
  begin
    nombre := 'Ana';
    edad := 30;
    activo := true;
  end;
end.

El with evita repetir el nombre del record al acceder a varios campos. Dentro del bloque, nombre se refiere a p.nombre. Usar con moderación.

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 es una lista dinámica de strings de la RTL. Ofrece Add, IndexOf, Sort y Count. Crea con Create y libera con Free.

Record simple
type
  TPersona = record
    nombre: string;
    edad: integer;
    activo: boolean;
  end;

var
  p: TPersona;
begin
  p.nombre := 'Ana';
  p.edad := 30;
  p.activo := true;
end.

Un record agrupa campos de tipos diferentes en una estructura. Se accede a los campos con punto (p.nombre). Es el equivalente a una struct.

Enumerados (enum)
type
  TColor = (Rojo, Verde, Azul);

var
  c: TColor;

begin
  c := Verde;
  if c = Verde then
    WriteLn('Verde');
  WriteLn(Ord(c));  // 1 (posición)
end.

Un enumerado define un conjunto ordenado de valores con nombre. Ord() devuelve la posición (empieza en 0). Más legible que enteros.

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.

Los genéricos (TList<integer>) crean colecciones tipadas seguras. Generics.Collections trae TList, TDictionary y otras listas dinámicas.

Strings e Conversões


12 cards
Length y Copy
var
  s: string;

begin
  s := 'Hola Mundo';
  WriteLn(Length(s));      // 10
  WriteLn(Copy(s, 1, 4));  // 'Hola'
  WriteLn(Copy(s, 6, 5));  // 'Mundo'
end.

Length() devuelve el número de caracteres. Copy(s, inicio, n) extrae una substring a partir de inicio con n caracteres.

StringReplace
uses SysUtils;

var
  s: string;
begin
  s := 'ola mundo ola';
  s := StringReplace(s, 'ola', 'hola',
       [rfReplaceAll, rfIgnoreCase]);
  WriteLn(s);  // 'hola mundo hola'
end.

StringReplace() sustituye texto. rfReplaceAll cambia todas las ocurrencias y rfIgnoreCase ignora mayúsculas/minúsculas.

Format
uses SysUtils;

begin
  WriteLn(Format('%d años', [30]));
  WriteLn(Format('%.2f', [3.14159]));  // 3.14
  WriteLn(Format('%s tiene %d', ['Ana', 30]));
  WriteLn(Format('%8d', [42]));  // alineado
end.

Format() construye strings con marcadores: %d (entero), %f (real), %s (string). El .2 define los decimales.

Mayúsculas y minúsculas
uses SysUtils;

var
  s: string;
begin
  s := 'Hola Mundo';
  WriteLn(UpperCase(s));  // 'HOLA MUNDO'
  WriteLn(LowerCase(s));  // 'hola mundo'
end.

UpperCase() convierte a mayúsculas y LowerCase() a minúsculas. Están en la 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() elimina espacios al inicio y al final. TrimLeft() solo a la izquierda y TrimRight() solo a la derecha. Esencial para limpiar input.

Char: Ord y 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() devuelve el código numérico del carácter y Chr() hace lo inverso. Succ() y Pred() dan el siguiente/anterior.

Pos (buscar)
var
  s: string;
  p: integer;

begin
  s := 'Hola Mundo';
  p := Pos('Mundo', s);
  WriteLn(p);  // 6 (posición)

  if Pos('xyz', s) = 0 then
    WriteLn('no encontrado');
end.

Pos(sub, s) devuelve la posición de la primera ocurrencia (empieza en 1) o 0 si no encuentra. Útil para verificar presencia.

String a 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() y StrToFloat() convierten strings en números y lanzan excepción si son inválidas. StrToIntDef() devuelve un valor por defecto en vez de fallar.

Concat y Length
var
  a, b, c: string;

begin
  a := 'Hola';
  b := 'Mundo';
  c := Concat(a, ' ', b);
  WriteLn(c);          // 'Hola Mundo'
  WriteLn(Length(c));  // 10
end.

Concat() une varias strings en una sola (alternativa a +). Length() devuelve la longitud. Las strings en Pascal son dinámicas.

Delete e Insert
var
  s: string;

begin
  s := 'Hola Mundo';
  Delete(s, 1, 5);   // elimina 5 chars
  WriteLn(s);        // 'Mundo'

  Insert('!', s, 6);
  WriteLn(s);        // 'Mundo!'
end.

Delete(s, inicio, n) elimina n caracteres (modifica la string). Insert(txt, s, pos) inserta texto en la posición indicada.

Número a 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() y FloatToStr() convierten números en strings. FloatToStrF() permite controlar el formato y los decimales.

String con comillas (escape)
var
  s: string;

begin
  s := 'Él dijo ''hola''';
  WriteLn(s);  // Él dijo 'hola'

  s := 'Linea1' + #13#10 + 'Linea2';
  WriteLn(s);  // dos líneas
end.

Para incluir una comilla simple dentro de una string, duplícala (''). #13#10 inserta un salto de línea (CR+LF) usando códigos de carácter.

Ponteiros, Units e Exceções


14 cards
Punteros básicos
var
  p: ^integer;
  x: integer;
begin
  x := 42;
  p := @x;       // dirección de x
  WriteLn(p^);   // 42 (dereference)
  p^ := 100;     // cambia x
  WriteLn(x);    // 100
end.

Un puntero (^integer) guarda una dirección. @x obtiene la dirección y p^ accede al valor apuntado (dereference).

Usar una Unit
program Principal;

uses MiUnit, SysUtils;

begin
  WriteLn(Sumar(2, 3));  // de MiUnit
end.

La cláusula uses importa units para acceder a sus funciones y tipos. Puede aparecer en el programa o en otra unit (interface o implementation).

Excepción personalizada
type
  ESaldoInsuficiente = class(Exception)
    constructor Create(valor: real);
  end;

constructor ESaldoInsuficiente.Create(valor: real);
begin
  inherited CreateFmt('Saldo insuficiente: %.2f',
    [valor]);
end;

Crea clases que heredan de Exception para errores específicos. CreateFmt formatea el mensaje con parámetros, como Format.

Operaciones 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 (desplazar)
end.

Los operadores bit a bit and, or, xor, shl y shr operan sobre los bits del entero. Útiles para flags y máscaras.

Memoria dinámica
var
  p: ^integer;
begin
  New(p);      // asignar memoria
  p^ := 100;
  WriteLn(p^);
  Dispose(p);  // liberar memoria
  p := nil;
end.

New() asigna memoria para el tipo apuntado y Dispose() la libera. Define el puntero como nil después para evitar accesos 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('Error: ', E.Message);
  end;
end.

try..except captura excepciones. El on E: Tipo trata cada tipo de excepción. E.Message da la descripción del error.

Constantes tipadas
const
  Umbral: integer = 100;  // mutable (FPC)

begin
  Umbral := 200;  // permitido
  WriteLn(Umbral);
end.

Las constantes tipadas (nombre: tipo = valor) son en realidad variables estáticas inicializadas: mantienen el valor entre llamadas y pueden cambiarse.

Programa completo (ejemplo)
program Media;

uses SysUtils;

var
  notas: array of integer;
  i, suma: integer;

begin
  SetLength(notas, 3);
  suma := 0;
  for i := 0 to High(notas) do
  begin
    notas[i] := Random(20) + 1;
    suma := suma + notas[i];
  end;
  WriteLn('Media: ', suma / Length(notas):0:1);
end.

Ejemplo completo: asigna un array dinámico, lo llena con Random, suma y calcula la media. Muestra la estructura típica de un programa Pascal.

GetMem y FreeMem
var
  ptr: Pointer;
begin
  GetMem(ptr, 1024);  // 1024 bytes
  // usar ptr...
  FreeMem(ptr);       // liberar
  ptr := nil;
end.

GetMem() asigna un bloque de bytes en bruto y FreeMem() lo libera. Más flexible que New para buffers de tamaño variable.

Try / Finally
var
  lista: TStringList;
begin
  lista := TStringList.Create;
  try
    lista.Add('item');
    WriteLn(lista.Count);
  finally
    lista.Free;  // se ejecuta siempre
  end;
end.

try..finally garantiza la ejecución del bloque finally incluso con error. Es el patrón para liberar recursos (memoria, ficheros, objetos).

Directivas de compilación
{$IFDEF DEBUG}
  WriteLn('Modo debug activo');
{$ENDIF}

{$MODE DELPHI}   // modo Delphi (FPC)
{$RANGECHECKS ON} // verifica índices

begin
  WriteLn('Hola');
end.

Las directivas {$...} controlan la compilación. {$IFDEF} compila condicionalmente, {$MODE} define compatibilidad y {$RANGECHECKS} valida índices.

Estructura de una Unit
unit MiUnit;

interface

uses SysUtils;

function Sumar(a, b: integer): integer;

implementation

function Sumar(a, b: integer): integer;
begin
  Result := a + b;
end;

end.

Una unit es un módulo reutilizable. La sección interface declara lo que es público e implementation contiene el código. Se usa con uses.

Raise (lanzar excepción)
procedure Validar(edad: integer);
begin
  if edad < 0 then
    raise Exception.Create('Edad inválida');
end;

raise lanza una excepción manualmente. Exception.Create(msg) crea la excepción con un mensaje. Interrumpe el flujo hasta el except más cercano.

Type aliases
type
  TNombre = string;
  TEdad = integer;
  TMatriz = array of array of real;

var
  nombre: TNombre;
  m: TMatriz;
begin
  nombre := 'Ana';
end.

El type crea nombres alternativos para tipos existentes, mejorando la legibilidad. TNombre es solo un alias para string.

Entrada/Saída e Ficheiros


12 cards
Write y WriteLn
begin
  Write('Sin salto ');
  WriteLn('con salto');
  WriteLn('A', 'B', 'C');   // ABC
  WriteLn(10, ' ', 20);     // 10 20
  WriteLn(3.14:6:2);        //   3.14
end.

Write imprime sin cambiar de línea y WriteLn sí. Aceptan varios argumentos separados por comas y formato :ancho:decimales.

Append (añadir)
var
  f: TextFile;

begin
  AssignFile(f, 'log.txt');
  Append(f);             // añadir al final
  WriteLn(f, 'Nueva entrada');
  CloseFile(f);
end.

Append abre un fichero existente para añadir al final, sin borrar el contenido anterior. Ideal para ficheros de log.

Verificar existencia
uses SysUtils;

begin
  if FileExists('datos.txt') then
    WriteLn('existe')
  else
    WriteLn('no existe');

  if DirectoryExists('C:\temp') then
    WriteLn('la carpeta existe');
end.

FileExists() verifica si un fichero existe y DirectoryExists() si una carpeta existe. Están en la unit SysUtils.

Read y ReadLn
var
  nombre: string;
  edad: integer;

begin
  ReadLn(nombre);     // lee una línea
  ReadLn(edad);       // lee un entero
  WriteLn(nombre, ' ', edad);
end.

ReadLn lee una línea completa del teclado y la convierte al tipo de la variable. Read lee sin consumir el salto de línea.

Fichero binario (tipado)
type
  TRegistro = record
    id: integer;
    nombre: string[50];
  end;

var
  f: file of TRegistro;
  reg: TRegistro;
begin
  AssignFile(f, 'datos.dat');
  Rewrite(f);
  reg.id := 1;
  reg.nombre := 'Ana';
  Write(f, reg);
  CloseFile(f);
end.

Un file of TRegistro guarda registros de tamaño fijo en binario. Write(f, reg) y Read(f, reg) leen/escriben registros completos.

Borrar y renombrar
var
  f: TextFile;

begin
  AssignFile(f, 'antiguo.txt');
  Erase(f);          // borra el fichero

  AssignFile(f, 'nuevo.txt');
  Rename(f, 'nuevo2.txt');  // renombra
end.

Erase() borra el fichero asociado y Rename() cambia el nombre. La variable debe estar asociada con AssignFile pero no abierta.

Escribir fichero de texto
var
  f: TextFile;

begin
  AssignFile(f, 'datos.txt');
  Rewrite(f);            // crear/escribir
  WriteLn(f, 'Linea 1');
  WriteLn(f, 'Linea 2');
  CloseFile(f);
end.

AssignFile asocia la variable al fichero, Rewrite lo abre para escritura (crea uno nuevo), escribes con WriteLn(f, ...) y cierras con CloseFile.

Leer fichero binario
var
  f: file of TRegistro;
  reg: TRegistro;

begin
  AssignFile(f, 'datos.dat');
  Reset(f);
  while not EOF(f) do
  begin
    Read(f, reg);
    WriteLn(reg.id, ' ', reg.nombre);
  end;
  CloseFile(f);
end.

La lectura binaria usa Read(f, reg) dentro de while not EOF(f). Cada iteración carga un registro completo de la estructura.

TFileStream
uses Classes, SysUtils;

var
  fs: TFileStream;
  s: string;
begin
  fs := TFileStream.Create('datos.bin',
        fmCreate);
  try
    s := 'Hola';
    fs.WriteBuffer(s[1], Length(s));
  finally
    fs.Free;
  end;
end.

TFileStream da control total sobre la lectura/escritura binaria. fmCreate crea el fichero y WriteBuffer escribe bytes en bruto.

Leer fichero de texto
var
  f: TextFile;
  linea: string;

begin
  AssignFile(f, 'datos.txt');
  Reset(f);              // abrir para lectura
  while not EOF(f) do
  begin
    ReadLn(f, linea);
    WriteLn(linea);
  end;
  CloseFile(f);
end.

Reset abre el fichero para lectura. El bucle while not EOF(f) recorre hasta el final, leyendo cada línea con ReadLn(f, linea).

Tamaño y posición (binario)
var
  f: file of TRegistro;

begin
  AssignFile(f, 'datos.dat');
  Reset(f);
  WriteLn(FileSize(f));     // nº de registros
  Seek(f, 2);               // ir al registro 2
  WriteLn(FilePos(f));      // posición actual
  CloseFile(f);
end.

FileSize() devuelve el número de registros y FilePos() la posición actual. Seek(f, n) mueve al registro n (acceso aleatorio).

Parámetros de línea de comandos
var
  i: integer;

begin
  WriteLn('Nº args: ', ParamCount);
  for i := 1 to ParamCount do
    WriteLn(ParamStr(i));
end.

ParamCount devuelve el número de argumentos de la línea de comandos y ParamStr(i) cada argumento. ParamStr(0) es el nombre del ejecutable.

Classes e OOP


14 cards
Clase básica
type
  TPersona = class
    Nombre: string;
    Edad: integer;
    procedure Presentar;
  end;

procedure TPersona.Presentar;
begin
  WriteLn(Nombre, ', ', Edad);
end;

Una clase se declara con class y contiene campos y métodos. Los métodos se implementan fuera con TPersona.Presentar. Se instancia con Create.

Private y public
type
  TCuenta = class
  private
    FSaldo: real;  // oculto del exterior
  public
    procedure Depositar(v: real);
    function Saldo: real;
  end;

private restringe el acceso al interior de la clase (encapsulamiento). public hace los miembros accesibles desde fuera. Los campos privados usan el prefijo F.

inherited
procedure TPerro.Hablar;
begin
  inherited Hablar;  // llama al de la superclase
  WriteLn('... y mueve la cola');
end;

inherited llama a la versión del método en la superclase. Útil para extender el comportamiento en vez de sustituirlo por completo.

Polimorfismo
var
  formas: array of TForma;
  f: TForma;
begin
  SetLength(formas, 2);
  formas[0] := TCirculo.Create;
  formas[1] := TCuadrado.Create;
  for f in formas do
    WriteLn(f.Area);  // llama al correcto
end.

Con métodos virtual/override, la misma llamada (f.Area) ejecuta la implementación correcta según el tipo real del objeto en runtime.

Crear y liberar objeto
var
  p: TPersona;
begin
  p := TPersona.Create;
  try
    p.Nombre := 'Ana';
    p.Edad := 30;
    p.Presentar;
  finally
    p.Free;  // liberar memoria
  end;
end.

Los objetos se crean con Create y deben liberarse con Free. El try..finally garantiza la liberación incluso si ocurre un error.

Properties
type
  TPersona = class
  private
    FNombre: string;
  public
    property Nombre: string read FNombre write FNombre;
    property SoloLectura: string read FNombre;
  end;

Una property expone campos con read y write, controlando el acceso. Puede enlazarse a métodos getter/setter para validación.

is y as
var
  a: TAnimal;
begin
  a := TPerro.Create;
  if a is TPerro then
    WriteLn('es un perro');

  (a as TPerro).Ladrar;
  a.Free;
end.

is verifica el tipo en runtime y as hace un cast seguro (lanza una excepción si falla). Esenciales para trabajar con polimorfismo.

for in (colecciones)
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.

El for in recorre colecciones y arrays de forma limpia, sin índices. Funciona con arrays dinámicos, TList y otros enumerables.

Constructor
type
  TPersona = class
    Nombre: string;
    constructor Create(n: string);
  end;

constructor TPersona.Create(n: string);
begin
  inherited Create;
  Nombre := n;
end;

var p: TPersona;
begin
  p := TPersona.Create('Ana');
end.

El constructor inicializa el objeto en la creación. inherited Create llama al constructor de la clase base. Permite pasar parámetros iniciales.

Herencia
type
  TAnimal = class
    procedure Hablar; virtual;
  end;

  TPerro = class(TAnimal)
    procedure Hablar; override;
  end;

procedure TPerro.Hablar;
begin
  WriteLn('¡Guau guau!');
end;

La herencia usa class(TAnimal). virtual marca el método como redefinible y override lo reimplementa en la subclase (polimorfismo).

Clase estática y Self
type
  TContador = class
    class var Total: integer;
    class procedure Incrementar;
  end;

class procedure TContador.Incrementar;
begin
  Total := Total + 1;
end;

Los miembros class pertenecen a la clase y no a la instancia (compartidos). Self se refiere al objeto actual, como this en otros lenguajes.

Destructor
type
  TRecurso = class
    destructor Destroy; override;
  end;

destructor TRecurso.Destroy;
begin
  WriteLn('Liberando recursos');
  inherited Destroy;
end;

El destructor Destroy (con override) se ejecuta al liberar el objeto. Se usa para limpiar recursos. Se llama con Free, que verifica nil.

Métodos abstract
type
  TForma = class
    function Area: real; virtual; abstract;
  end;

  TCirculo = class(TForma)
    Radio: real;
    function Area: real; override;
  end;

function TCirculo.Area: real;
begin
  Result := 3.14159 * Radio * Radio;
end;

Un método abstract se declara sin implementación y obliga a las subclases a definirlo. Convierte la clase base en un contrato (clase abstracta).

Interfaces
type
  IGuardable = interface
    ['{GUID-AQUI}']
    procedure Guardar;
  end;

  TDocumento = class(TInterfacedObject, IGuardable)
    procedure Guardar;
  end;

Una interface define un contrato sin implementación. La clase hereda de TInterfacedObject e implementa los métodos. Soporta conteo de referencias.