Ŀ
VII - Procedures


VII.1 - Definio
        ---------

        Uma das tcnicas mais utilizadas e tida como vantajosa na confeco
        de programas grandes   a  modularizao.  Consiste  em  dividir  o
        programa   em  diversos  mdulos  ou  subprogramas,  de certa forma
        independentes uns dos outros. Existe um mdulo que  o principal, a
        partir do qual so chamados os outros mdulos, esse mdulo recebe o
        nome de programa principal, enquanto que os outros so chamados  de
        subprogramas. No  sistema  Turbo Pascal, existem dois tipos de sub-
        programas, a saber:

                - Procedures (procedimentos)
                - Functions (funes)

        A  procedure    como  se  fosse  um  programa. Ela tem a estrutura
        praticamente  igual  a de um programa, como veremos mais adiante. A
        procedure deve ser ativada(chamada) pelo programa principal ou  por
        uma outra procedure, ou at por ela mesma.


VII.2 - Declarao de procedures
        ------------------------

        Uma procedure tem praticamente a mesma estrutura de um programa, ou
        seja, ela contm um cabealho, rea de declaraes e  o  corpo   da
        procedure.  Na rea   de declaraes, podemos ter as seguintes sub-
        reas:

           Label - Const - Type - Var - Procedures - Functions.

        Devemos salientar que tudo que for declarado dentro das subreas s
        ser  reconhecido dentro da procedure. Mais para frente, voltaremos
        a falar sobre isso.

        Exemplo:
        ---------------------------------------------------------
        Program Exemplo_1;  (* cabealho do programa *)
        Uses CRT;


        Procedure linha;      (* cabealho da procedure linha *)
        Var i : integer;      (* subrea Var da procedure linha *)
        Begin                 (* corpo da procedure linha *)
           for i:=1 to 80 do write('-');
        End;

        Begin                 (* corpo do programa principal *)
           ClrScr;
           linha;             (* ativao da procedure linha *)
           writeln('teste');
           linha;             (* ativao da procedure linha,
                                 novamente *)
        End.
        ---------------------------------------------------------
        O programa acima, pura e simplesmente faz o seguin-te:

        1-) Apaga a tela e coloca o cursor em 1,1
        2-) Ativa a procedure linha
        3-) Escreve a palavra teste
        4-) Ativa novamente a procedure linha.

        Por sua vez, a procedure linha traa uma linha a partir da  posio
        atual do cursor. Uma observao importantssima a ser  feita  neste
        instante,  que a varivel inteira i,  definida dentro da procedure
        linha s existe dentro da procedure,isto significa que toda vez que
        ativamos a procedure linha, a varivel i  criada  e  toda  vez que
        saimos da procedure linha, ela  destruda.


VII.3 - Passagem de parmetros.
        -----------------------

        No exemplo acima, ao ativarmos a procedure linha,no houve passagem
        de parmetros, mas poderia haver, repare no exemplo abaixo:

        Exemplo:
        ---------------------------------------------------------
        Program Exemplo;
        Uses CRT;

        Var i,j:integer;

        Procedure soma(x,y:integer);
        Begin
           writeln(x+y);
        end;

        Begin
           ClrScr;
           soma(3,4);
           i:=45;
           j:=34;
           soma(i,j);
        end.
        -------------------------------------------------------------------
        Como podemos reparar, a procedure soma depende de dois   parmetros
        inteiros, e ao ativarmos esta procedure, devemos fornecer  os  dois
        parmetros.Esses parmetros podem ser dois nmeros inteiros ou duas
        variveis inteiras, obviamente deve haver compatibilidade entre  os
        parmetros passados. Podemos tambm  passar  parmetros  de   tipos
        diferentes, seno vejamos:
        -------------------------------------------------------------------
        Program Exemplo_1;
        Uses CRT;


        Var i,j:integer;

        Procedure soma(x,y:integer;h,g:real);
        Begin
           writeln(x+y);
           writeln(h/g:10:2);
        end;

        Begin
           ClrScr;
           i:=34;
           j:=35;
           soma(i,j,3.4,4.5);
        End.
        -------------------------------------------------------------------
        Nos exemplos acima,houve passagem de parmetros para as procedures,
        mas   elas  tambm  podem   passar  dados  de volta para o programa
        chamador, exemplo:
        -------------------------------------------------------------------
        Program exemplo;
        Uses CRT;

        Var i : Integer;

        Procedure Soma(x,y:Integer;Var z:Integer);
        Begin
           z:=x+y;
        End;

        Begin
           ClrScr;
           Soma(3,4,i);
           Writeln(i);
        End.
        -------------------------------------------------------------------
        Da forma como foi declarada a procedure soma, quando a ativamos com
        a sequncia Soma(3,4,i), ocorrem as seguintes passagens:

        - O nmero 3  passado para x
        - O nmero 4  passado para y
        - O parmetro z  passado para i.

        Como  podemos ver, houve passagem de dados do programa chamador para
        a procedure e da procedure para o programa chamador.


VII.4 - A declarao forward.
        ---------------------

        Suponha o programa abaixo:

        ---------------------------------------------------------
        Program exemplo;
        Uses CRT;

        Procedure Soma(x,y:Integer);
        Begin
           linha;
           Writeln(x+y);
        End;

        Procedure Linha;
        Var i:integer;
        Begin
           For i:=1 to 80 do Write('-');
        End;

        Begin
           ClrScr;
           Soma(3,4);
        End.
        ---------------------------------------------------------
        Repare  que a procedure Soma chama uma procedure chamada linha.  No
        entanto, a procedure linha est declarada mais  frente e portanto,
        ao  compilarmos  o  programa,  o  compilador ir "reclamar" que no
        conhece  o  identificador   Linha  e com justa razo, isto porque a
        compilao  feita de cima para baixo e da esquerda para a direita.
        Para  tanto, podemos usar a declarao Forward, cuja finalidade  a
        de   indicar  ao compilador que determinada procedure est definida
        mais para frente.

        Exemplo:
        ---------------------------------------------------------
        Program exemplo;
        Uses CRT;

        Procedure Linha; Forward;

        Procedure Soma(x,y:Integer);
        Begin
           linha;
           Writeln(x+y);
        End;

        Procedure Linha;
        Var i:integer;
        Begin
           For i:=1 to 80 do Write('-');
        End;

        Begin
           ClrScr;
           Soma(3,4);
        End.
        ---------------------------------------------------------

        Agora sim, podemos compilar o programa sem erro.


VII.5 - O escopo de objetos num programa
        ---------------------------------

        Reparem o Exemplo abaixo:
        ---------------------------------------------------------
        Program Exemplo;
        Uses CRT;

        Const a=100;                     (* constante global *)

        Label fim;                       (* Label global *)

        Var i,x,y : Integer;             (* variveis globais *)

        Procedure Linha;
        Var i : Integer;                 (* i  local  procedure
                                            linha *)
        Begin
           For i:=1 to 80 do Write('-');
        End;

        Procedure Teste;
        Procedure Sub_teste;              (* a procedure
                                           Sub_teste  local
                                            procedure Teste *)
        Begin
           Write('Estive em sub_teste');
        End;
        Begin
           Sub_teste;
           Writeln;
        End;

        Begin
           ClrScr;
           i:=100;
           Linha;
           x:=20;
           y:=30;
           Teste;
           Linha;
           Writeln('i=',i,' y=',y,' x=',x);
        End.
        ---------------------------------------------------------

        Todos  os  elementos (constantes, variveis, labels etc.) que forem
        definidos antes de comear o corpo do  programa,  so  considerados
        globais e podem ser utilizados por todas as procedures, functions e
        o prprio programa. O espao para tais elementos  criado durante a
        compilao. J, os elementos declarados dentro de uma procedure, s
        existem  dentro  da procedure, exemplo: ao declararmos uma varivel
        dentro  de  uma  procedure, toda vez que ativarmos a procedure, tal
        varivel  ser criada e ao sairmos da procedure ela ser destruda.
        Portanto, dizemos que esta varivel  local  procedure.

        No  entanto,  se  repararmos bem no exemplo, veremos que existe uma
        varivel i inteira declarada antes do incio do  programa, portanto
        global,  e  outra  dentro da procedure linha, portanto local a esta
        procedure.  Mas no h problema, pois o Turbo Pascal ir consider-
        las   diferentes.  Quando  estivermos  dentro  do programa, teremos
        acesso   varivel  global e quando estivermos dentro da procedure,
        teremos acesso  varivel local.

Ŀ
VIII - Functions.


VIII.1 - Definio
         ---------

        As funes so muito parecidas com as procedures. A principal dife-
        rena  que o identificador de uma funo assume o valor de retorno
        da funo.  Uma  funo  deve  sempre  retornar um valor e em Turbo
        Pascal, este valor  retornado no nome da funo.


VIII.2 - Declarao de funes.
         ----------------------

        A  declarao  de  uma funo  muito parecida com de uma procedure
        que por sua vez  parecida com a de um programa, seno vejamos:

        ---------------------------------------------------------
        Function Nome_da_funo(parmetros) :  Tipo_da_funo;

        < rea de declaraes >

        Begin

                corpo da funo

        End;
        ---------------------------------------------------------

        A  formao  do  nome  da funo deve seguir as mesmas regras  para
        formao de identificadores em Turbo Pascal. Dentro  dos parenteses
        devemos declarar os parmetros e seus respectivos tipos dos quais a
        funo depende. O tipo de valor retornado pela funo  tambm  deve
        ser declarado.

        Na  rea  de   declaraes,  podemos  declarar  labels, constantes,
        variveis e at mesmo Procedures e Functions. Devemos  lembrar  que
        tais elementos s podero ser utilizados dentro do corpo da funo,
        pois so locais a ela. Abaixo, temos o exemplo de uma funo.


        ---------------------------------------------------------
        Program Exemplo;
        Uses CRT;

        Var x,y : Real;                   (* variveis globais *)

        Function Soma(a,b:real):real;     (* Soma  uma funo
                                             que depende de dois
                                             parmetros reais e
                                             devolve um valor
                                             real *)
        Begin
           Soma:=a+b;                     (* reparem que o valor
                                             da funo  retor-
                                             nado p. seu nome *)
        End;

        Begin
           ClrScr;
           x:=Soma(4,5);
           y:=Soma(3,6)-Soma(45.5,5.6);
           Writeln(x:10:2,y:10:2);
           Writeln;
           Write('Valor de x --> ');
           Readln(x);
           Write('Valor de y --> ');
           Readln(y);
           Writeln;
           Writeln(Soma(x,y):10:2);
        End.
        ---------------------------------------------------------

        Devemos  lembrar  que  o Turbo Pascal  possui inmeras  funes  de
        procedures pr-definidas, que iremos ver no decorrer do curso.

        Exemplos:
        ---------------------------------------------------------
        Program Fat;
        Uses CRT;

        (********************************************************
         Programa para calcular o fatorial de um nmero lido do
         teclado, usando o conceito de Function
        ********************************************************)

        Label inicio,fim;

        Var n : Integer;
            tecla : char;

        Function Fatorial(numero:integer) : Real;
        Var i   : Integer;
            Fat : Real;
        Begin (* da funo Fatorial *)
           Fat:=1;
           If numero>1
              Then Begin
                      i:=1;
                      Repeat
                         i:=i+1;
                         Fat:=Fat*i;
                      Until i=numero;
                   End;
           Fatorial:=Fat;
        End; (* da funo fatorial *)

        Begin  (* do programa *)
           ClrScr;
        inicio:
           Write('Valor de n (menor que 0 = fim) --> ');
           Readln(n);
           Writeln;
           If n<0
              Then Begin
                      Write('Nao existe fatorial de numeros negativos');
                      Goto fim;
                   End
              Else Writeln('Fatorial de n = ',fatorial(n):10:0);
           Writeln;
           Goto inicio;
        Fim:
        End. (* do programa *)

        ---------------------------------------------------------

        Program Fibonacci;
        Uses CRT;

        (********************************************************
         Programa para determinar um determinado elemento da se-
         quncia de Fibonacci. A sequncia de fibonacci  defi-
         nida como

                        Fib(0)  =  0

                  Fib(1)  =  1

                  Fib(n)  =  Fib(n-1) + Fib(n-2)


                        Como podemos ver, o elemento atual  determi-
        nado pela soma dos dois elementos anteriores

        ********************************************************)

        Label inicio;

        Var numero:integer;
            tecla : char;

        Function Fib(n:integer):integer;
        Var  a1,a2,i,pe : Integer;
        Begin
           if n=0
              Then Fib:=0
              Else If n=1
                      Then Fib:=1
                      Else Begin
                              a1:=0;
                              a2:=1;
                              i:=1;
                              Repeat
                                 pe:=a1+a2;
                                 i:=i+1;
                                 a1:=a2;
                                 a2:=pe;
                              Until i=n;
                              Fib:=a2;
                           End;
        End;

        Begin
           ClrScr;
        inicio:
           Write('Fib(');
           Read(numero);
           Writeln(') = ',fib(numero));
           Writeln;
           Write('Deseja continuar ? --> ');
           Readln(tecla);
           writeln;
           writeln;
           If tecla='s' Then goto inicio;
        End.
        ---------------------------------------------------------


VIII.3 - Recursividade
         -------------

         A   linguagem Pascal  e  o Turbo Pascal  permitem a utilizao  de
         funes recursivas. Uma funo  dita recursiva quando ela chama a
         si  mesma. Devemos tomar cuidado ao lidar com esse tipo de funo,
         pois  podemos criar loops infinitos. Existem pessoas que tm faci-
         lidade para  pensar  recursivamente  e outras no. A recursividade
         permite  criar  funes elegantes e torna os programas mais fceis
         de serem entendidos. Abaixo, temos os mesmos programas anteriores,
         s que utilizando o conceito de recursividade.

        ---------------------------------------------------------
        Program Fatorial;
        Uses CRT;

        Label inicio,fim;

        Var n : Integer;
            tecla : char;


        Function Fat(n:integer):real;
        Begin
           if n=0
              Then Fat:=1
              Else Fat:=n*Fat(n-1);   (* repare que estamos
                                         chamando novamente a
                                         funo Fat *)
        End;


        Begin
           ClrScr;
        inicio:
           Write('Valor de n (menor que 0 = fim) --> ');
           Readln(n);
           Writeln;
           If n<0
              Then Begin
                      Write('Nao existe fatorial de numeros negativos');
                      Goto fim;
                   End
              Else Writeln('Fatorial de n = ',fat(n):10:0);
           Writeln;
           Goto inicio;
        Fim:
        End.

        ---------------------------------------------------------

        Program Fibonacci;
        Uses CRT;

        Label inicio;

        Var numero:integer;
            tecla : char;

        Function Fib(n:integer):integer;
        Begin
           If n=0
           Then Fib:=0
           Else If n=1
                   Then Fib:=1
                   Else Fib:=Fib(n-1)+fib(n-2);
        End;

        Begin
           ClrScr;
        inicio:
           Write('Fib(');
           Read(numero);
           Writeln(') = ',fib(numero));
           Writeln;
           Write('Deseja continuar ? --> ');
           Readln(tecla);
           writeln;
           writeln;
           If tecla='s' Then goto inicio;
        End.
        ---------------------------------------------------------
