




                                CAPTULO 6              
            
                               PROCEDIMENTOS         
            
            
            
            6.1. DEFINIO, PROCEDIMENTOS SEM PARMETROS 
            
                 Um procedimento (procedure)  um trecho de programa que
            possui seus  prprios objetos (variveis, constantes, tipos,
            funes, outros  procedimentos, ...)  .  Juntamente  com  as
            funes,  os   procedimentos   formam   o   que   se   chama
            genericamente   de    subprogramas   (ou   subrotinas).   Os
            procedimentos diferem  das  funes  apenas  pelo  fato  das
            funes retornarem  sempre um  nico valor,  enquanto que os
            procedimentos no retornam valor algum.
                 A criao  de um procedimento em Pascal  feita atravs
            de sua declarao na rea de declaraes do programa.
                 Um procedimento  possui um cabealho, identificado pela
            palavra reservada  PROCEDURE seguida do nome do procedimento
            e uma lista opcional de parmetros. Segue-se ao cabealho um
            bloco de  declaraes dos  objetos locais do procedimento, e
            um bloco  de comandos delimitados pelas palavras chave BEGIN
            e END com um ponto-e-vrgula no final:
            
            PROCEDURE NomeDoProcedimento (parmetro1, parmetro2, ...);
            
            (* declaraes de tipos, variveis, constantes, ... *)
            
            BEGIN
              comando1;
              comando2;
              ...
            END;
            
                 A chamada  ou  ativao  de  um  procedimento    feita
            referenciando-se o  seu nome  no local  do programa  onde  o
            mesmo deve  ser ativado, ou seja, onde sua execuo deve ser
            iniciada.  Ao  final  da  execuo  de  um  procedimento,  o
            controle do  programa retorna ao comando seguinte aquele que
            provocou sua  chamada. Assim,  a execuo de um procedimento
            se constitui  na transferncia  temporria  da  execuo  do
            programa para  o  trecho  do  programa  que  corresponde  ao
            procedimento.
                 Tudo que  for declarado dentro de um procedimento, ser
            considerado um  objeto local  e ser  conhecido apenas  pelo
            procedimento.
            
            Exemplo: Um  uso bastante  comum de  procedimentos  para se
            evitar repetio de trechos anlogos em um programa. Observe
            o esboo de programa a seguir:
            
                           PROGRAM Teste;
                      

                                        - 89 -





                           VAR x, y, z: real;
            
                           BEGIN
                             comando1;
                             comando2;
                             x := funo1;
                             y := funo2;
                             comando3;
                             comando1;
                             comando2;
                             x := funo1;
                             z := Cos(x);
                             comando4;
                             comando1;
                             comando2;
                             x := funo1;
                             comando5;
                           END.
            
                 Observe que o trecho
            
                           comando1;
                           comando2;
                           x := funo1;
            
            se repete  no programa.  Neste caso,  seria mais  prtico se
            declarar esse trecho como sendo um procedimento, digamos que
            com nome  REPETE, e assim, toda vez que o trecho aparecesse,
            simplesmente colocaramos a palavra REPETE no seu lugar:
            
                           PROGRAM Teste;
            
                           VAR x, y, z: real;
                           
                           PROCEDURE REPETE;
            
                           BEGIN (* inicio do procedimento *)
                             comando1;
                             comando2;
                             x := funo1;
                           END; (* fim do procedimento *)
            
                           BEGIN (* inicio da seo principal *)
                             REPETE;
                             y := funo2;
                             comando3;
                             REPETE;
                             z := Cos(x);
                             comando4;
                             REPETE;
                             comando5;
                           END. (* fim do programa *)
            

                                        - 90 -





                 Os   dois    esboos   de   programa   anteriores   so
            equivalentes.
            
            Exemplo:  Os  procedimentos  aumentam  significativamente  a
            clareza  dos   programas.  Voltemos  aquele  nosso  primeiro
            programa do  Captulo 2, aquele que somava dois inteiros. Um
            programa desse tipo  feito basicamente em trs etapas:
                           (1) Ler os inteiros;
                           (2) Calcular sua soma;
                           (3) Mostrar seu resultado.
                 Cada etapa  na elaborao  de um  programa,  sugere  um
            procedimento   prprio.    Neste   caso,    usaremos    trs
            procedimentos LERNUMEROS,  CALCULARSOMA e  MOSTRARRESULTADO.
            Com isso o programa principal se limitar a listar as etapas
            na execuo do programa:
            
            PROGRAM SomaDeInteiros;
            
            VAR
              x, y, soma: integer;
            
            PROCEDURE LerNumeros;
            
            BEGIN
              Writeln;
              Write('Forneca o valor de x : '); Readln(x);
              Write('Forneca o valor de y : '); Readln(y);
            END; (* fim de LerNumeros *)
            
            PROCEDURE CalcularSoma;
            
            BEGIN
              soma := x + y;
            END; (* fim de CalcularSoma *)
            
            PROCEDURE MostrarResultado;
            
            BEGIN
              Writeln;
              Writeln('Soma = ', soma);
              Writeln;
              Write('Pressione ENTER para encerrar.');
              Readln;
            END; (* fim de MostrarResultado *)
            
            BEGIN (* inicio do programa principal *)
              LerNumeros;
              CalcularSoma;
              MostrarResultado
            END. (* fim do programa *)
            
                 Neste  exemplo,   as  variveis   X,  Y,  SOMA  so  do
            conhecimento de  todo o  programa pois  elas foram definidas
            fora  de   qualquer  procedimento  ou  funo.  Dizemos  que

                                        - 91 -





            variveis assim so globais. O uso de variveis globais deve                                globais                                 
            ser evitado,  pois pode  levar a  erros  difceis  de  serem
            detectados. O  uso de  parmetros evita  o  uso  abusivo  de
            variveis globais.
                 O programa  ficou grande, mas fica mais fcil de se ler
            uma vez  que cada  parte  do  programa  executa  uma  tarefa
            especfica. Podemos  estar interessado  apenas na  sada dos
            resultados,  e   a,  bastaramos   olhar   o   procedimento
            MOSTRARRESULTADO e ignorar os demais. O programa fica tambm
            mais fcil de se consertar ou de se fazer mudanas.
            
            
            6.2 PROCEDIMENTOS COM PARMETROS        
            
                 A lista  de parmetros, delimitada por parnteses, pode
            aparecer no  cabealho de  um procedimento.  Nessa lista, se
            ela existir,  so  designadas  as  variveis  que  recebero
            valores enviados ao procedimento na hora de sua chamada.
                 Na lista de parmetros, cada nome de varivel  seguido
            do nome  do respectivo  tipo. Entre  o  tipo  e  o  nome  da
            varivel deve haver um sinal de dois pontos. Variveis de um
            mesmo tipo  podem estar  separadas entre si por vrgulas e o
            tipo comum  ser mencionado  apenas uma  vez. Aps  o nome de
            cada tipo deve vir um ponto-e-vrgula:
            
            PROCEDURE NomeDoProcedimento(var1: tipo1; var2: tipo2; ...);
            
                 Cada varivel  listada no  cabealho de um procedimento
            ser considerada uma varivel local. Portanto, outras partes
            do programa  nem ao menos tm conhecimento dessas variveis,
            mesmo que  tenham o mesmo nome. Um "x" usado no cabealho de
            um procedimento  normalmente no  tem nenhuma relao com um
            outro "x" do programa principal.
            
            Exemplo: PROCEDURE Teste(a, b, c: integer);
                 Um  procedimento   que  tenha   este  cabealho,   est
            preparado para  aceitar exatamente 3 inteiros quando ele for
            ativado. Um comando no programa como TESTE(1, 2, 3), forar
            a  execuo   do  procedimento  TESTE  com  os  valores  dos
            parmetros a  = 1, b = 2 e c = 3. TESTE parece uma funo de
            3 variveis  inteiras, mas observe a grande diferena de que
            nenhum valor   retornado,  ou seja,  no h  nada que possa
            servir de contradomnio para TESTE.
                 Esto  erradas   as   seguindes   chamadas   a   TESTE:
            TESTE(3,5), TESTE(6, 5, 2, -1) e TESTE(3.2, -1.0, 7).
            
            Exemplo: PROCEDURE TesteDois(nome: string; mat: longint);
                 Com esta  declarao, uma  chamada a TESTEDOIS pode ser
            feita como
                 TESTEDOIS('Jose J J da Silva', 91110023);
            ou como
                 TESTEDOIS('Antonio A Braga', 92101234);

                                        - 92 -





                 No ltimo  caso, a  execuo do  procedimento TESTEDOIS
            est sendo  chamada com  os  parmetros  mat  =  92101234  e
            nome = 'Antonio A Brag.
            
            Exemplo: Uma chamada ao procedimento a seguir pode ser usada
            no lugar  dos dois  comandos TEXTCOLOR  e TEXTBACKGROUND que
            compem o procedimento.
            
                      PROCEDURE Cor(x, y: byte);
            
                      BEGIN
                        TextColor(x);
                        TextBackground(y)
                      END.
            
                 Por exemplo, o comando Cor(7, 3) faz o mesmo efeito que
            o par de comandos TextColor(7) e TextBackground(3).
            
                 Quando um  procedimento   chamado, o  Pascal  faz  uma
            cpia na  memria de  cada argumento  para que  a cpia seja
            usada pelo  procedimento. As  operaes  executadas  com  as
            cpias no alteram os valores dos argumentos originais. Para
            evitar que  o Pascal  faa cpia  de varivel e passe para o
            procedimento a  prpria varivel  para  ser  usada,  deve-se
            colocar a  palavra chave  VAR antes  do nome  da varivel na
            lista de  parmetros  no  cabealho.  Neste  caso,  qualquer
            modificao feita  com o  parmetro durante  a  execuo  do
            procedimento afetar  o valor  da varivel  original que foi
            passada como parmetro.
                  de  fundamental importncia saber quando se deve usar
            ou no  a palavra  VAR antes de um parmetro no cabealho de
            um procedimento.  O uso  do VAR  onde no for necessrio no
            constitui erro, mas no  recomendado.
            
            Exemplo:
            
                 PROCEDURE IncrementaUm(x: byte; VAR y: byte; z: byte);
            
                 BEGIN
                   x := x + 1;
                   y := y + 1;
                   z := z + 1;
                 END.
            
                 Neste exemplo,  o procedimento  INCREMENTAUM incrementa
            de uma  unidade os valores de cada parmetro. Suponhamos que
            a, b,  c sejam  trs  variveis  inteiras  (tipo  byte)  com
            valores respectivamente  iguais a  10, 11  e  12.  Aps  uma
            chamada a INCREMENTAUM, como por exemplo,
                           IncrementaUm(a, b, c);
            teremos a  = 10, b = 12 e c = 12. Observe que apenas o valor
            de b   alterado,  pois  o nico parmetro precedido por um
            VAR no cabealho.
                 Se o cabealho fosse

                                        - 93 -





            
                 PROCEDURE IncrementaUm(VAR x, y, z: byte);
            
            o que  equivalente a
            
            PROCEDURE IncrementaUm(VAR x: byte; VAR y:byte; VAR z:byte);
            
            ento, se a, b, c valessem 10, 11 e 12 respectivamente, aps
            a chamada a IncrementaUm,
                           IncrementaUm(a, b, c);
            teramos a = 11, b = 12 e c = 13.
            
            Observao: Se  a declarao de um parmetro no cabealho de
            um procedimento  possui a  palavra VAR,  ento diz-se  que a
            passagem do  parmetro  uma passagem por referncia (porque 
            nesse caso o Pascal informa ao procedimento a localizao na
            memria  da   varivel  usada   como  parmetro).  Quando  a
            declarao no  tem a  palavra VAR, ento temos uma passagem 
            por valor do parmetro.   
            
            
            Exemplo: O  procedimento  a  seguir  troca  os  valores  dos
            parmetros. Isso  s pode  ser feito  com o  uso do  VAR  no
            cabealho, pois   um  caso em que os valores dos parmetros
            so alterados.
            
                 PROCEDURE Troca(VAR x, y: real);
            
                 VAR
                   aux: real; (* variavel local ao procedimento *)
            
                 BEGIN
                   aux := x;
                   x := y;
                   y := aux
                 END.
            
                 Se tivermos, por exemplo, x = 1 e y = 2, aps o comando
                                Troca(x, y);
            teremos x = 2 e y = 1.
                 Se no houver o VAR no cabealho do procedimento, ento
            os valores de x e y no sero alterados aps Troca(x, y).
            
            Exemplo:  Toda   funo  pode   ser   substituda   por   um
            procedimento:
            
            FUNCTION f(x: real): real; <---> PROCEDURE F(x: real,
                                                           VAR y: real);
            ...                             ...
                     y := f(x);        <--->       F(x, y);
            
                 A recproca  tambm   verdadeira, mas  no parece  ser
            muito natural.

                                        - 94 -





                 Neste exemplo, calculamos o fatorial de n atravs de um
            procedimento. No  estamos, no momento, preocupados em fazer
            um programinha breve e pequeno.
            
            
            PROGRAM CalculandoMaisUmaVezOFatorialDeN;
            
            USES
              Crt;
            
            VAR
              n: integer;   (* variaveis *)
              m: longint;   (* globais   *)
            
            PROCEDURE Encerrar;
            
            BEGIN
              Writeln;
              Writeln('Valor de n invalido.');
              Writeln;
              Halt;
            END;
            
            PROCEDURE LerN(VAR n: integer);
            
            (*
               Neste procedimento,   fundamental o VAR acima. Sem ele,
               o valor de N ficaria desconhecido do programa principal.
            *)
            
            BEGIN
              ClrScr; Writeln;
              Write('Forneca o valor do inteiro n: ');
              Readln(n);
              if (n < 0) or (n > 13) then Encerrar;  (*  Observe  que
                                     temos aqui a chamada a um proce-
                                     dimento de dentro de outro.   *)
            END;
            
            PROCEDURE CalcularFatorial(n: integer; VAR fat: longint);
            
            VAR
              i: longint; (* variavel local *)
            
            BEGIN
              fat := 1;
              for i := 2 to n do
                fat := fat * i;
            END;
            
            PROCEDURE MostrarResultado(n: integer; fat: longint);
            
            VAR
              pausa: char; (* variavel local *)

                                        - 95 -





            
            BEGIN
              Writeln;
              Writeln(n, '! = ', fat);
              Writeln;
              Write('Para encerrar, pressione qualquer tecla.');
              pausa := ReadKey;
            END;
            
            
            BEGIN (* inicio do programa principal *)
              LerN(n);
              CalcularFatorial(n, m);
              MostrarResultado(n, m)
            END. (* fim do programa *)
            
            
            Exemplo: Um procedimento pode chamar outro (como  o caso do
            exemplo anterior, em que LERN pode chamar ENCERRAR) e tambm
            pode ter suas prprias funes e procedimentos internos:
            
                 PROCEDURE Externo;
            
                   PROCEDURE Interno1;
                   begin
                     ...
                   end;
            
                   PROCEDURE Interno2;
                   begin
                     ...
                   end;
            
                   FUNCTION f_interna(x: real): real;
                   begin
                     ...
                   end;
            
                 VAR
                   (* variveis locais do procedimento EXTERNO *)
            
                 BEGIN (* incio do procedimento EXTERNO *)
                   ...
                   (* comandos *)
                   ...
                 END; (* fim do procedimento EXTERNO *)
            
                 Neste caso, toda parte do programa que seja exterior ao
            procedimento EXTERNO  no tem conhecimento da existncia dos
            procedimentos INTERNO1  e INTERNO2  e da  funo  F_INTERNA.
            Esses procedimentos e funo internos podem fazer referncia
            entre si. Por exemplo, INTERNO2 pode usar o INTERNO1.
            
            

                                        - 96 -
