apostila
259 pág.

apostila

Disciplina:Algoritmos e Estrutura de Dados I542 materiais7.956 seguidores
Pré-visualização50 páginas
sinta´tica e´ caracterizada pela palavra var antes do nome do identifica-
dor do paraˆmetro.2 Pode parecer sutil, mas com uma semaˆntica totalmente diferente
daquela da passagem de paraˆmetros por valor.

O que antes era uma co´pia, agora e´ uma refereˆncia ao enderec¸o da varia´vel do
programa principal. Isto e´, no momento da ativac¸a˜o da func¸a˜o, o identificador n
da func¸a˜o e´ associado com o mesmo enderec¸o da varia´vel a no programa principal.
Consequentemente, qualquer alterac¸a˜o associada a n na func¸a˜o provocara´ alterac¸a˜o
do valor da varia´vel a no programa principal.

Vejamos na figura 9.4 como fica a modificac¸a˜o no programa em estudo do ponto de
vista meramente sinta´tico. Deixamos o ponto de vista semaˆntico para ser explicado
no pro´ximo exemplo.

2Com todo o respeito ao Niklaus Wirth, usar a palavra var para este fim na˜o foi uma boa escolha,
pois para um principiante e´ fa´cil confundir com uma passagem de paraˆmetros por refereˆncia com
uma declarac¸a˜o de uma varia´vel, o que na˜o e´ definitivamente o caso aqui.

114 CAPI´TULO 9. FUNC¸O˜ES E PROCEDIMENTOS

program imprime pares ;
var a: integer ;

(∗ funcao que calcula se a variavel global a eh par ∗)
function eh par (var n: integer) : boolean;
begin

if n mod 2 = 0 then
eh par:= true

else
eh par:= false ;

end;

begin (∗ programa principal ∗)
read (a) ;
while a <> 0 do
begin

if eh par (a) then
writeln (a) ;

read (a) ;
end;

end.

Figura 9.4: Versa˜o com paraˆmetros por refereˆncia.

9.2.7 Procedimentos

Um procedimento difere de uma func¸a˜o basicamente pois na˜o tem um valor de retorno
associado. Isto faz com que ele se comporte como um comando extra da linguagem ao
passo que a func¸a˜o tem um comportamento mais parecido com o de uma expressa˜o
aritme´tica ou booleana. Um proto´tipo para um procedimento e´ definido enta˜o com
base em apenas duas informac¸o˜es:

1. o identificador do procedimento (nome);

2. a lista de paraˆmetros (que podem ser por valor ou refereˆncia).

Para explicar corretamente a noc¸a˜o de procedimentos, e tambe´m de varia´veis lo-
cais, e´ importante mudar de exemplo. Vamos considerar o problema de se ler dois
nu´meros reais x e y do teclado, fazer a troca dos conteu´dos e depois imprimir.

Vamos considerar o seguinte proto´tipo para um procedimento que recebe os dois
valores x e y e tem a finalidade de realizar a troca dos conteu´dos destas varia´veis:

procedure troca (var a, b: real) ;

Observe que, assim como no caso da func¸a˜o, na˜o importa muito o nome dos identi-
ficadores dos paraˆmetros, apenas importa que eles definam conteu´dos do tipo REAL.

Podemos enta˜o tentar escrever um programa que leia dois valores e os imprima
trocados, conforme ilustrado na figura 9.53:

3Um exerc´ıcio interessante e´ passar os paraˆmetros por valor e compreender o efeito disso.

9.2. NOC¸O˜ES FUNDAMENTAIS 115

program imprimetrocado ;
var x,y,temp: real ; (∗ variaveis globais ∗)

(∗ procedimento que troca os conteudos da variaveis ∗)
procedure troca (var a, b: real) ;
begin

temp:= a;
a:= b;
b:= temp;

end;

begin (∗ programa principal ∗)
read (x,y) ;
troca (x,y) ;
writeln (x,y) ;

end.

Figura 9.5: Versa˜o com paraˆmetros por refereˆncia.

Este programa usa uma varia´vel global (temp) para auxiliar a troca, o que na˜o
faz muito sentido. Os subprogramas devem funcionar independentemente de varia´veis
globais.

9.2.8 Varia´veis locais

Varia´veis locais sa˜o declaradas nos subprogramas e teˆm escopo local, isto e´, elas so´ sa˜o
conhecidas durante a execuc¸a˜o do subprograma. Consequentemente na˜o interferem
no programa principal. O programa modificado da figura 9.6 faz uso da varia´vel local
temp e torna o co´digo mais robusto.

program imprimetrocado ;
var x,y: real ; (∗ variaveis globais ∗)

(∗ procedimento que troca os conteudos da variaveis ∗)
procedure troca (var a, b: real) ;
var temp: real ; (∗ variavel local , temporaria para uso exclusivo neste procedimento ∗)
begin

temp:= a;
a:= b;
b:= temp;

end;

begin (∗ programa principal ∗)
read (x,y) ;
troca (x,y) ;
writeln (x,y) ;

end.

Figura 9.6: Versa˜o com uma varia´vel local.

116 CAPI´TULO 9. FUNC¸O˜ES E PROCEDIMENTOS

9.3 Alguns exemplos

Nesta sec¸a˜o vamos implementar dois problemas simples para exercitar.

9.3.1 Calculando d´ıgito verificador

Vamos fazer um programa que recebe um nu´mero de N d´ıgitos, sendo o u´ltimo deles
o “d´ıgito verificador” do nu´mero formado pelos N − 1 primeiros. Devemos calcular se
o d´ıgito verificador fornecido pelo usua´rio esta´ correto segundo o esquema de ca´lculo
seguinte: cada d´ıgito do nu´mero, comec¸ando da direita para a esquerda (menos sig-
nificativo para o mais significativo) e´ multiplicado, na ordem, por 1, depois 2, depois
1, depois 2 e assim sucessivamente. O nu´mero de entrada do exemplo e´ 261533-4.

+---+---+---+---+---+---+ +---+

| 2 | 6 | 1 | 5 | 3 | 3 | - | 4 |

+---+---+---+---+---+---+ +---+

| | | | | |

x2 x1 x2 x1 x2 x1

| | | | | |

=4 =6 =2 =5 =6 =3

+---+---+---+---+---+-> = 26

Como 26 tem dois d´ıgitos, vamos repetir o processo acima ate´ gerarmos um nu´mero
de um u´nico d´ıgito. Assim:

+---+---+

| 2 | 6 |

+---+---+

| |

x2 x1

| |

=4 =6

+---+ = 10

Como 10 ainda tem dois d´ıgitos, o algoritmo roda ainda mais uma vez:

+---+---+

| 1 | 0 |

+---+---+

| |

x2 x1

| |

=2 =0

+---+ = 2

Assim, o d´ıgito verificador calculado (2) difere daquele fornecido (4) e o programa
deveria acusar o erro. O programa da figura 9.7 ilustra uma poss´ıvel soluc¸a˜o.

9.3. ALGUNS EXEMPLOS 117

program digitoverificador ;
var numero, n: longint ;

dv, dv correto : integer ;

procedure le (var n: longint) ;
begin

{$i−}
repeat

read (n) ;
until ioresult = 0;
{$i+}

end;

procedure separa numero e dv (n: longint ; var num: longint ; var dv: integer) ;
begin

num:= n div 10;
dv:= n mod 10;

end;

function calcula dv correto (n: longint) : integer ;
var soma, mult, ultimo : integer ;
begin

repeat
soma:= 0;
mult:= 1;
while n <> 0 do
begin

ultimo:= n mod 10;
n:= n div 10;
soma:= soma + mult ∗ ultimo ;
i f mult = 1 then

mult:= 2
else

mult:= 1;
end;
n:= soma;

until (n > 0) and (n<= 9) ;
calcula dv correto:= soma;

end;

begin (∗ programa principal ∗)
le (numero) ;
separa numero e dv (numero, n, dv) ;
dv correto:= calcula dv correto (n) ;
i f dv correto <> dv then

writeln (’digito verificador invalido.’)
end.

Figura 9.7: Calculando d´ıgito verificador.

118 CAPI´TULO 9. FUNC¸O˜ES E PROCEDIMENTOS

O importante para se observar neste co´digo e´ a clareza do algoritmo no programa
principal. O leitor pode acompanhar este trecho e perceber claramente as diversas
etapas em uma linguagem de bastante alto n´ıvel: leitura do nu´mero, separac¸a˜o deste
em duas partes, uma contendo os primeiros d´ıgitos a outra contendo o dv de entrada.
Em seguida o ca´lculo do d´ıgito verificador correto e finalmente a comparac¸a˜o dos
dados calculados com o de entrada, gerando a mensagem final.

No programa principal pode-se ignorar completamente como sa˜o feitas todas as
operac¸o˜es nas func¸o˜es e procedumentos: na˜o importa como os dados sa˜o lidos, nem
como os d´ıgitos sa˜o separados, e muito menos como e´ feito o ca´lculo do d´ıgito verifi-
cador correto. No programa principal o importante e´ o algoritmo em alto n´ıvel.

E´ claro que em algum momento sera´ necessa´rio escrever co´digo para cada uma das
func¸o˜es e procedimentos, mas quando isto for feito o programador estara´ resolvendo
um subproblema de cada vez, o que facilita muito a construc¸a˜o do co´digo para o
problema global.

Por exemplo, a leitura poderia ser feita em uma interface gra´fica ou textual. Foi es-
colhida nesta versa˜o uma interface textual, mas que permite testes de consisteˆncia dos
dados de entrada. Isto, feito separadamente, mante´m