ALGORITMOS
COM PASCAL
Prof. Miguel Jonathan – Dept. Ciência da Computação –
IM/UFRJ – 2003 – versão 1.0
program ex6_1;
var L1,L2,H: real;
begin
L1:= 3.0;
L2:= 4.0;
H:= sqrt(L1*L1+L2*L2);
writeln('A hipotenusa do triangulo retangulo
de lados ', L1:3:1, ' e ',
L2:3:1, ' e'' ' ,H:3:1);
end.
No exemplo
acima, a função sqrt já vem
pré-definida na linguagem Pascal, e pode ser utilizada diretamente. Note o
seguinte:
a) a função tem
um argumento real n, ou seja, para usá-la é preciso fornecer um valor
real entre parênteses. A definição de uso é sqrt(n) onde n deve ser um
valor real.
b) esse
argumento pode ser qualquer expressão real, no exemplo foi L1*L1+L2*L2.
c) a função realiza uma tarefa, através de um
algoritmo próprio, para calcular a raiz quadrada. Essa tarefa constitui o
sub-programa, que nesse caso já está armazenado no computador em forma
compilada.
d) quando o programa for executar o
comando: H:= sqrt(L1*L1+L2*L2);
vai ocorrer o
seguinte:
-
primeiro, a
expressão do argumento será calculada, para obter o seu valor. No
caso, será calculado o valor 3.0*3.0 + 4.0*4.0
que dá 25.0.
-
em seguida o programa entrará em um estado de suspensão da
sua execução, e o controle da execução passará para o primeiro comando do
sub-programa sqrt.
-
antes de iniciar o sub-programa, o valor calculado do argumento,
no caso 25.0, será passado como valor
inicial de uma variável especial do sub-programa que representa o argumento da
função. Essa variável é chamada de parâmetro de valor e a operação é
chamada de passagem de parâmetro.
-
o sub-programa executará seus comandos, e a raiz quadrada do
argumento será calculada, obtendo o valo 5.0, nesse caso.
-
ao terminar, o sub-programa repassará o valor obtido de
volta para o programa. Isso é feito substituindo a aplicação da função, sqrt(L1*L1+L2*L2), pelo
resultado obtido.
-
nesse ponto o controle da execução voltará para o programa
no ponto em que havia interrompido, e o programa executará o comando: H:= 5.0; continuando a execução normalmente a partir
desse ponto.
program
ex6_2;
var
x:integer;
function fat(n:integer): longint;
var
i: integer;
f: longint;
begin
f:=1;
for i:= 2 to n do f:=
f*i;
fat:= f;
end; {fim da declaracao da
funcao}
begin
{inicio do programa}
writeln('Digite varios numeros para saber o
fatorial');
writeln('Termine com -1');
read(x);
while x > 0 do begin
writeln ('fatorial de ', x, ' = ', fat(x) );
read(x);
end;
end.
Ao executar o programa, o seguinte diálogo
poderá ocorrer: (dados do usuário em itálico):
Digite varios numeros para saber o
fatorial.
Termine com –1:
4
Fatorial de 4 = 24
5
Fatorial de 5 = 120
6
Fatorial de 6 = 720
-1
(aqui o programa termina)
As seguintes observações são importantes para
um bom entendimento de funções e do programa acima:
a)
A
declaração da função fica na área de declarações, junto com as declarações de
variáveis e constantes:
function fat(n:integer):
longint;
var
i: integer;
f: longint;
begin
f:=1;
for i:= 2 to n do f:= f*i;
fat:= f;
end; {fim da declaracao da funcao}
b)
O
formato da declaração da função é bastante parecido com o de um programa,
apenas no cabeçalho a palavra program é substituída pela palavra function. A declaração da função tem sua própria
área de declarações e sua área de comandos. Mas termina com end; e não com end.
c)
Além
disso, no cabeçalho da função são declarados os seus argumentos, agrupados por
tipo, seguidos do tipo do resultado que produz. A forma sintática do cabeçalho
é:
function <nome da função> (<lista de
argumentos>:<tipo>; <lista de argumentos>: tipo; etc):<tipo
do resultado>
No caso do fatorial, há apenas um
parâmetro inteiro (chamado n) e o resultado será do tipo longint, porque os
fatoriais crescem muito rapidamente:
function fat(n:integer):
longint;
d)
No corpo
da função (parte executável, começando após o primeiro begin) o nome da função deve receber
por atribuição pelo menos uma vez o valor do resultado:
fat:= f;
É dessa forma que o resultado calculado
será repassado de volta ao programa, onde irá substituir a aplicação da função.
Note que, apesar de receber um valor por atribuição, o nome da função não é uma variável. Caso o nome da função receba
mais de um valor durante a execução da função, o valor que finalmente será repassado
para o programa será o último valor atribuído ao nome da função antes dela
terminar sua execução.
e)
Outro
ponto importante a registrar é que os identificadores definidos na
função só têm significado dentro da função, e não para fora dela. Chama-se a
isso o escopo dos identificadores. No exemplo acima, as variáveis n,
i e f não são “vistas” pelo programa que usa a função, e são
chamadas variáveis locais da função. A variável n é especial,
chamada de parâmetro formal de valor. É ela que receberá o valor do
argumento a ser usado no inicio da execução da função. A partir daí, os
parâmetros de valor se comportam como qualquer outra variável local.
Voltando então para a execução do Exemplo
6-2, vemos que o laço de repetição fará com que a função fat seja chamada
várias vezes, cada vez com um argumento diferente. A cada vez, o programa será
interrompido, o controle será passado para a função, um resultado será obtido e
repassado de volta ao programa, substituindo a aplicação da função.
Tipos dos argumentos e do resultado de funções:
Em uma linguagem de programação como
Pascal, as funções podem ter argumentos de tipos diferentes. Argumentos podem
ser de tipos escalares simples, como integer, longint, real, char e
boolean, e podem ser também de tipos estruturados, como vetores,
strings, matrizes e registros (records), esse último tipo ainda por ser
estudado.
Por outro lado, o resultado da função tem
maiores limitações: o tipo do resultado de uma função só pode ser um
tipo escalar simples, com a exceção do tipo string, que também pode ser um
resultado. Portanto, vetores comuns não podem ser resultado de funções,
Veremos mais adiante que, para contornar essa limitação, podemos usar
procedimentos para obter resultados de sub-programas que sejam tipos estruturados.
Mas, para isso, teremos que usar parâmetros de referência, outro assunto
que será visto mais adiante.
Os exemplos a seguir mostram várias
funções com tipos diferentes de argumentos e de resultados.
Exemplo 6-3:
Neste exemplo, a função maiuscula(c) é usada para obter a letra maiúscula
correspondente ao caractere c, se este for uma letra minúscula, caso contrário
o valor retornado é o próprio caractere original:
program ex6_3;
var
frase:string;
i: integer;
function
maiuscula(c:char):char;
{essa funcao converte
letras minusculas em maiusculas}
begin
case c of
'a'..'z': maiuscula:= chr(ord('A') +
ord(c)-ord('a'));
else maiuscula:= c;
end;
end;
begin
writeln('Digite uma frase. Ela sera'' re-escrita em letras
maiusculas: ');
readln (frase);
for i:=1 to length(frase) do frase[i] := maiuscula(frase[i]);
writeln(frase);
end.
program ex6_4;
var
frase:string;
i: integer;
function
maiusc_str(s:string):string;
{essa funcao retorna uma
string com todas as letras maiusculas}
var i: integer;
begin
for i:= 1 to length(s) do
case s[i] of
'a'..'z': s[i]:= chr(ord('A') +
ord(s[i])-ord('a'));
end;
maiusc_str:= s;
end;
begin
writeln('Digite uma frase. Ela sera'' re-escrita em letras
maiusculas: ');
readln (frase);
writeln(maiusc_str(frase));
end.
Esse exemplo é mais complexo, e é interessante para ressaltar a importância de se separar as tarefas em sub-programas separados. Dessa forma, o programa que usa a função fica muito mais compreensível, e também a função pode ser testada e aperfeiçoada independentemente dos programas que a usarão. O programa que usa a função é bem simples, e toda a complexidade da criptografia fica encapsulada na definição da função.
Exemplo 6-5:
program
ex6_5;
var
frase: string;
i,n: integer;
function cripto(c: char; n: integer): char;
var pos,d:integer;
begin
n:= n mod 26; {reduz logo o n }
pos:= ord(c) + n; {posicao
na tabela de caracteres n casas adiante de c}
case c of
'a'..'z': begin
d:= pos
-ord('z'); {d e' quanto pos passou de
z}
if d<=0 then
cripto:= chr(pos)
else cripto:=
chr(ord('a') + d-1 )
end;
'A'..'Z': begin
d:= pos
-ord('Z'); {d e' quanto pos passou de
Z}
if d<=0 then
cripto:= chr(pos)
else cripto:=
chr(ord('A') + d-1 )
end;
'0'..'9': begin
d:= pos
-ord('9'); {d e' quanto pos passou de
9}
if d<=0 then
cripto:= chr(pos)
else cripto:=
chr(ord('0') + d-1 )
end;
else cripto:= c; {se for
outro caractere, nao altera}
end;
end;
begin
writeln('Digite uma frase: ');
readln(frase);
writeln('Escolha o valor de n para a
criptografia: ');
readln(n);
for i:=1 to length(frase) do
write(cripto(frase[i], n));
readln;
end.
program
ex6_6;
uses
crt; {necessario para usar gotoxy e
clrscr}
var linhamedia,colunamedia: integer;
m:string;
procedure msg(frase:string;
x,y: integer);
begin
gotoxy(x,y);
write(frase);
end;
begin
clrscr;
msg('esta frase na linha 1 coluna 1', 1, 1);
msg('esta frase na linha 3 coluna 2', 2, 3);
msg('esta frase na linha 5 coluna 3', 3, 5);
m:= 'meio da tela';
linhamedia:=12;
colunamedia:=40;
msg(m,colunamedia-length(m) div
2,linhamedia);
end.
program
ex6_7;
uses
crt;
var
a,b,c: integer;
nome: string;
procedure
altera_variavel(var x:integer; n:integer);
{a e' parametro de referencia, n e' parametro
de valor}
begin
x:= x+n;
end;
procedure
reduz_string (var frase:string; n:integer);
{esse procedimento elimina os n primeiros
caracteres da frase}
var i:integer;
s:string;
begin
s:=''; {s e' inicializada com uma string vazia, ou nula}
for i:= n+1 to length(frase) do s:=s+frase[i];
{operador + de concatenacao}
frase:=s; {o conteudo de frase no programa
sera’ alterado}
end;
begin {aqui inicia a execucao do programa}
clrscr;
a:=10;
b:=20;
c:=30;
writeln(a:4,b:4,c:4);
altera_variavel(a, 5); {a variavel a tera'
seu valor alterado para a+5}
altera_variavel(b, 7); {a variavel b tera'
seu valor alterado para b+7}
altera_variavel(c, 15); {a variavel c tera'
seu valor alterado para c+15}
writeln(a:4,b:4,c:4);
nome:= 'Antonio Claudio da Sliva';
writeln('nome antes : ', nome);
reduz_string(nome,8); {deve eliminar os 8
caracteres antes de Claudio}
writeln('nome depois: ', nome);
readln;
end.
O
próximo exemplo mostra um programa que usa vários procedimentos e funções.
Um processo de criptografia de frases de até 100 caracteres, com código
(chave) igual a k<=10, consiste em colocar os caracteres da frase em uma
matriz, usando apenas as primeiras k colunas. No exemplo abaixo, com k=8, são usadas as 8 primeiras colunas
de uma matriz 10x10 para criptografar a frase:
UNIVERSIDADE FEDERAL DO RIO
DE JANEIRO
O número de linhas necessárias para conter todos os caracteres da frase
é dado pela expressão:
no. de linhas = menor inteiro
maior ou igual a tamanho da frase/k
Para k=8, e como a frase acima tem 37 caracteres, o número necessário
de linhas é: 37/8= 4,6 => 5.
Inicialmente, os caracteres da string são colocados na matriz linha a
linha, ocupando as k primeiras colunas apenas:
1 2
3 4 5 6 7
8 9 10
|
U |
N |
I |
V |
E |
R |
S |
I |
|
|
|
D |
A |
D |
E |
|
F |
E |
D |
|
|
|
E |
R |
A |
L |
|
D |
O |
|
|
|
|
R |
I |
O |
|
D |
E |
|
J |
|
|
|
A |
N |
E |
I |
R |
O |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1
2
3
4
5
6
7
8
9
10
A codificação é completada reescrevendo a matriz em forma de string, desta vez escrevendo os caracteres segundo as colunas, a partir da coluna 1, apenas para as linhas usadas.
Completando o exemplo acima, a frase codificada fica da forma seguinte:
O interessante é que o mesmo processo pode ser usado tanto para
codificar como para decodificar. Para decodificar, toma-se a frase codificada,
desta vez com chave (no. de colunas) igual ao número de linhas usado na
codificação original, obtendo a matriz transversa abaixo:
1 2
3 4 5 6 7
8 9 10
|
U |
D |
E |
R |
A |
|
|
|
|
|
|
N |
A |
R |
I |
N |
|
|
|
|
|
|
I |
D |
A |
O |
E |
|
|
|
|
|
|
V |
E |
L |
|
I |
|
|
|
|
|
|
E |
|
|
D |
R |
|
|
|
|
|
|
R |
F |
D |
E |
O |
|
|
|
|
|
|
S |
E |
O |
|
|
|
|
|
|
|
|
I |
D |
|
J |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1
2
3
4
5
6
7
8
9
10
Basta usar o processo de codificação para obter a frase original, lendo
coluna a coluna.
O número mínimo de linhas necessárias para codificar uma frase com ncar
caracteres, e chave k, é dada pela expressão:
round(ncar/k + 0.4)
A solução abaixo usa 2 procedimentos e 2 funções.
Os procedimentos le_frase e le_chave são usados para solicitar do
usuário a frase a ser codificada, e a chave a ser usada. Ambos usam parâmetros
de referência var para passar os valores lidos para o programa.
A função linhas_necessarias(f, k) calcula e retorna o menor número de
linhas necessárias para codificar a frase f com a chave k.
A função codifica(frase,k) é que faz o trabalho de codificar a string
frase com a chave k, e retorna a string codificada. A função utiliza o
procedimento limpa_matriz, para
inicializar os elementos da matriz com espaços em branco. Note que o procedimento é interno à função, e que a
matriz é acessada como variável global ao procedimento, não sendo necessário
passar parâmetro.
A função usa uma matriz 10x10, podendo acomodar frases de até 100
caracteres.
O programa propriamente dito consiste apenas de chamadas dos
procedimentos. Todo o trabalho real é feito nos sub-programas, o programa
apenas coordena a chamada dos mesmos para realizar uma tarefa completa.
program
codifica_matr;
{Este
programa codifica textos usando o metodo da matriz transposta}
var
frase: string;
chave:integer;
procedure
le_frase (var frase:string);
begin
writeln('Digite a frase a ser codificada
ate'' 100 caracteres:' );
readln(frase);
end;
procedure
le_chave(var chave:integer);
var i: integer;
begin
writeln('Digite a chave de codificacao <
10: '); readln(chave);
end;
function
linhas_necessarias(f:string; k: integer):integer;
{retorna
o menor numero de linhas necessarias para codificar a string f
com a chave k}
begin
linhas_necessarias:= round(length(f)/k +0.4);
end;
function
codifica (frase:string; k: integer):string;
var
m: array[1..10,1..10] of char;
i,j,n,lin,col,linhas, colunas:integer;
s: string;
procedure limpa_matriz;
var i,j:integer;
begin
for i:= 1 to 10 do
for j:= 1 to 10 do m[i,j]:= ' ';
end; {limpa_matriz}
begin
limpa_matriz;
colunas:= k;
linhas:= linhas_necessarias(frase,k);
for i:= 1 to length(frase) do begin
lin:= (i- 1) div colunas+1;
col:= i mod colunas; if col=0 then col:=colunas;
m[lin,col]:= frase[i];
end;
s:='';
for j:=1 to colunas do
for i:= 1 to linhas do s:=s+m[i,j];
codifica:=s;
end;
{codifica}
begin
le_frase(frase);
le_chave(chave);
frase:=codifica(frase,chave);
writeln('Frase codificada com a chave ',
chave,': ', frase);
chave := linhas_necessarias(frase, chave);
frase:= codifica(frase,chave);
writeln('Decodificando com a chave ', chave,
': ', frase);
readln;
end.