Aula prática 5

Sumário

Objectivos

Os alunos no final desta aula deverão conhecer:

  1. O mecanismo de invocação de rotinas.
  2. A noção de sobrecarga de nomes de rotinas.

Deverão também ser capazes de:

  1. Desenvolver rotinas simples usando recursividade.
  2. Distinguir entre uma boa e uma má aplicação da recursividade.
  3. Usar a sobrecarga para dar nomes idênticos para rotinas operando sobre argumentos de tipos diferentes.

Caso os alunos sintam que os objectivos não foram atingidos na totalidade deverão concluir/repetir os exercícios desta aula autonomamente e ou recorrer aos horários de dúvidas.

Resumo

O resumo da matéria abordada nesta aula prática pode ser consultado aqui.

Exercícios

1.a)  Crie três procedimentos denominados troca(), cada um com dois parâmetros do mesmo tipo.  Cada um dos três procedimentos opera sobre um dos seguintes tipos de dados: char, int e double.  Pode reutilizar o procedimento void troca(char, char) feito no exercício 3 da Aula prática 4.  Escreva um programa que teste os procedimentos desenvolvidos (inspire-se no código sugerido na Secção 1 do resumo).

Verifique, fazendo o traçado do programa, que é executado o procedimento apropriado ao número e tipo de argumentos passado durante cada invocação do procedimento sobrecarregado.

1.b)  Transfira as definições dos procedimentos que escreveu para o fim do programa (após a função main()).  Compile e interprete o resultado.  Corrija o programa sem alterar a ordem das definições.


2.  Abra o ficheiro ex2.C que se encontra no directório ~/IP/Aula5.  Faça o traçado do programa e verifique se os valores constantes na tabela abaixo estão correctos.

Traçado da invocação factorialDe(4)
  valor de n: devolução de:
1ª invocação: factorialDe(4) 4 24 = 4 × 6
2ª invocação: factorialDe(3) 3 6 = 3 × 2
3ª invocação: factorialDe(2) 2 2 = 2 × 1
4ª invocação: factorialDe(1) 1 1

A tabela mostra o valor do parâmetro n e do valor devolvido pela função factorialDe() em cada uma das invocações embutidas.


Já concluiu o Problema?  Se sim, continue fazendo os exercícios abaixo.  Se não, dedique o resto da aula à sua resolução e regresse a estes exercícios logo que possa.


3.a)  Desenvolva uma função recursiva int potênciaDe(int const base, int const expoente) que devolva a potência expoente de base.  Escreva um pequeno programa para testar a função.  Faça o traçado da função invocando-a com os argumentos 2 e 4.  Durante o traçado, sempre que chegar a uma invocação da função potência() faça (s)tep no depurador para que o traçado entre na função.  Preencha a seguinte tabela:
 

Traçado da invocação potênciaDe(2, 4)
  valor de base: valor de expoente: devolução de:
1ª invocação:       
2ª invocação:       
3ª invocação:      
4ª invocação:       
       

3.b)  Corrija a função potênciaDe() para suportar expoentes negativos (volte a fazer uso da recursividade).


4.a)  Considere uma sucessão de números que denota o número de casais de coelhos existente na exploração do Sr. Fibonacci em determinado mês.  Estes coelhos são de uma raça especial, imortal, e que se caracteriza por, em cada mês, cada casal de coelhos procriar dando origem a outro casal de coelhos.  Estes coelhos demoram dois meses a atingir a maturidade.  Admita que, no mês 1, o Sr. Fibonacci comprou um casal bebé destes coelhos miraculosos.  No mês 2 a exploração terá ainda um par de coelhos, mas no mês 3 terá já dois pares de coelhos (pois o casal original, atingida a maturidade, reproduziu-se).  No mês 4 os primeiros reproduzem-se novamente (embora os últimos ainda não o possam fazer) e portanto a exploração terá três pares de coelhos.  No mês 5 dois desses três pares podem-se reproduzir, do que resultam cinco pares de coelhos.  E assim sucessivamente.  Se nenhum dos coelhos morrer, o número de pares de coelhos existente em cada mês é dado pela chamada sucessão de Fibonacci.  Essa sucessão pode ser definida recorrentemente por:

F0 = 0 (no mês zero o Sr. Fibonacci não tem coelhos)
F1 = 1
Fn = Fn-1 + Fn-2, se n > 1

Os primeiros termos da sucessão são portanto: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

Implemente uma função recursiva que devolva o número de coelhos do Sr. Fibonacci num dado mês.

4.b)  Implemente a versão iterativa da função feita na alínea anterior.  Teste ambas as funções utilizando o programa fib.C que pode encontrar no directório ~/IP/Aula5).

Para ver um gráfico dos tempos que cada função demora a fazer os seus cálculos, dê o comando:

tcsh mostraGrafico 35


5.  Tente calcular analiticamente o número de invocações da função fibonacciRecursiva() quando lhe é passado o argumento n.  Verifique que o número de invocações pode ser expresso de uma forma recursiva muito semelhante à da própria sucessão de Fibonacci!  Escreva uma nova função, unsigned long nFibonacciRecursiva(int const n) (na sua forma iterativa!) que devolva o número de invocações à função fibonacciRecursiva() quando lhe é passado o argumento n.

Verifique que o valor calculado está correcto comparando-o com os valores calculados por si próprio.


6.a)  Crie quatro funções de multiplicação (com o mesmo nome produtoDe()) para três tipos de argumentos diferentes (int, float e double).  As funções com parâmetros int e float devem ter exactamente dois parâmetros.  Para parâmetros double devem existir duas funções com dois e três parâmetros respectivamente.  Use o seguinte o programa ex6.C no directório ~/IP/Aula5 para testar as funções.

Verifique, fazendo o traçado do programa, que é executada a função apropriada ao número e tipo de argumentos passado durante cada invocação da função.

6.b)  Transfira as definições das funções que escreveu para o fim do programa (após a função main()). Compile e interprete o resultado.  Corrija o programa sem alterar a ordem das definições.