Procedimentos e Funções encadeados
Após ver a existência de pessoal que estava a converter código minimamente bom num código esparguete cheio de Gotos, decidi mostrar uma das maravilhas do Pascal.
Os procedimentos e funções podem-se chamar uns aos outros, mas muitas vezes damos por nós a criar procedimentos ou funções que só são necessários para um(a) outro/a. Para este caso, podemos criar o procedimento, ou a função, dentro do próprio procedimento/função que o necessitar! Este não será acessível ao resto do programa e outros procedimentos e funções que não sejam aquele que o contém.
Bem, isto já parece algo confuso. Um exemplo prático irá esclarecer bem o assunto.
Imaginemos que queremos um procedimento que escreve um texto convertido. A conversão consiste em transformar cada caracter no seu terceiro sucessor. Isto é, A será D, e X será A. Ou seja, quando o caracter é Z, o seu sucessor directo é A (X > Y (1º) > Z (2º) > A (3º)).
Criemos então um procedimento, Escrever
, que recebe como argumento o texto a converter, obtido por leitura do utilizador. Este procedimento vai depender um conversor, uma função que recebe o texto a converter e o converte. O seu nome será original, Conversor
. :-D Mas o conversor irá depender de uma outra função que lhe irá dar directamente o terceiro sucessor de um caracter. Sendo Succ
a função padrão que dá o sucessor directo, o nome da função que devolve o terceiro sucessor será Succ3
.
Numa árvore, temos o seguinte:
- Programa Principal
- Escrever
- Conversor
- Succ3
- Conversor
- Escrever
Aqui vê-se que o programa principal pode aceder a Escrever
, mas não pode aceder a Conversor
nem a Succ3
. Escrever
pode aceder a Conversor
, mas não a Succ3
. Conversor
pode aceder a Succ3
.
Vemos, então, que cada procedimento/função só pode aceder a outros procedimentos/funções que estejam directamente na sua linha de hierarquia ou na seguinte. As superiores são-lhes inacessíveis.
Basta pensar em cada procedimento e função como um pequeno programa com os seus procedimentos e funções. Outro programa externo não pode aceder directamente a esses procedimentos e funções — são seus e não de outrém.
Assim sendo, e dando por terminada a teoria, segue-se a implementação prática.
Em comentário entre {}
está o nome do procedimento ou da função a que cada Begin
/End
se refere para evitar confusões.
{$MODE Delphi}
PROGRAM ProcFuncEx;
VAR Txt : string[80];
PROCEDURE Escrever(const Texto : string[80]);
(* Escreve "Texto" com os seus caracteres convertidos nos seus terceiros sucessores *)
function Conversor(const Linha : string[80]) : string;
(* Debita "Linha" convertida, cujos caracteres são os seus terceiros sucessores *)
var i : byte;
Resultado : string[80];
function Succ3(const Caracter : char) : char;
(* Função que calcula o terceiro sucessor *)
var Res : char;
j : 1..3;
begin {Succ3}
Res := Caracter;
for j:=1 to 3 do begin // Terceiro sucessor
Res := Succ(Res);
if (ord(Res) > Ord('Z')) then Res := 'A'; // Evita caracteres não alfanuméricos
end;
Result := Res; // Output da função
end; {Succ3}
begin {Conversor}
Resultado := ''; // Inicia a String
// Converte caracter a caracter
for i:=1 to length(Linha) do Resultado := Resultado + Succ3(Linha[i]);
Result := Resultado; // Output da função
end; {Conversor}
begin {Escrever}
// Debita o texto, em maiúsculas, convertido, recorrendo ao Conversor
writeln(Conversor(UpCase(Texto)));
end; {Escrever}
BEGIN (* Bloco Principal *)
repeat
Write('Txt? '); ReadLn(Txt);
Escrever(Txt); // debita texto convertido
WriteLn; // parágrafo em branco
until (UpCase(Txt) = 'SAIR');
END.