Aula prática 3

Sumário

Objectivos

Os alunos no final desta aula deverão conhecer:

  1. As vantagens e desvantagens da modularização.
  2. As rotinas (funções e procedimentos) do C++.
  3. As noções de invocação, parâmetro, argumento, retorno e devolução.
  4. As noções de contrato e programação por contrato.

Deverão também ser capazes de:

  1. Desenvolver programas simples com a abordagem descendente.
  2. Modularizar programas simples com funções e procedimentos usando instruções de asserção.
  3. Documentar as rotinas de um programa.

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.  Abra o ficheiro ex1.C que se encontra no directório ~/IP/Aula3, compile-o e faça o seu traçado (execute-o em modo de depuração (debug) linha a linha) Quando for executar a linha onde a função é invocada use o step (s), em vez de next (n), de modo a entrar na função.  Verifique que a próxima instrução executada é a primeira que se encontra no corpo da função.  Observe sempre os valores das variáveis (use os comandos (p)rint ou (disp)lay).


Para todos os exercícios que se seguem deve fazer um pequeno programa de teste que permita verificar se as rotinas implementadas funcionam de modo adequado.

Para todos os exercícios que se seguem deve explicitar claramente a pré-condição e a condição objectivo, i.e., o contrato, de todas as rotinas desenvolvidas.


2.a)  Implemente uma função que, dados três valores de vírgula flutuante como argumentos, interpretados como componentes de um vector, calcule a sua norma.  Lembre-se que a norma de um vector é a raiz quadrada do somatório dos quadrados de cada um dos seus componentes.  Faça um pequeno programa para testar esta função (como foi feito no exemplo).  Para calcular a raiz quadrada use a função sqrt(), acrescentando ao topo do seu programa a linha #include <cmath>.

2.b)  Usou a função double quadradoDe(double const a) na alínea anterior?  Se não usou, modifique o seu programa de modo a usar.


3.a)  Desenvolva um procedimento que desenhe uma linha com n asteriscos, em que n é dado como argumento.  Faça um pequeno programa para testar esse procedimento.  A execução do programa deve ter o seguinte aspecto:

Qual o tamanho da linha? 7
*******

3.b)  Desenvolva um procedimento que desenhe um quadrado de altura n, em que n é dado como argumento.  Use no seu programa o procedimento desenvolvido na alínea anterior.  Faça um pequeno programa para testar esse procedimento.  A execução do programa deve ter o segunte aspecto:

Qual o tamanho do quadrado? 4
****
****
****
****


4.a)  Implemente uma função int inteiroPedido() que peça ao utilizador para introduzir um número e o devolva.

4.b)  Implemente uma função bool estáEntre(int const valor, int const mínimo, int const máximo) que verifique se o valor valor está entre máximo e mínimo inclusive e devolva true se assim for e false no caso contrário.  Inclua a linha #include <cassert> no início do programa e a linha assert(mínimo <= máximo); no início da função.   Escreva um programa que teste a função desenvolvida.  Verifique o que acontece se mínimo > máximo.


Para todos os exercícios que se seguem deve não só explicitar claramente a pré-condição e a condição objectivo, i.e., o contrato, de todas as rotinas desenvolvidas, como também explicitá-lo no próprio código através de instruções de asserção como sugerido nas alíneas anteriores.


4.c)  Implemente uma função int inteiroPedidoEntre(int mínimo, int máximo) que peça ao utilizador para introduzir um número e verifique se este está entre mínimo e máximo inclusive.  Verifique se mínimo é de facto menor ou igual a máximo usando a instrução assert como acima.  Este procedimento deve pedir repetidamente ao utilizador um número até que ele insira um que esteja de facto entre mínimo e máximo.  Relembra-se que o ciclo while permite repetir um conjunto de instruções enquanto determinada condição for verdadeira.  Alternativamente, pode ser útil usar o ciclo do while.


Nota:  As funções das alíneas 4.a) e 4.b) deveriam na realidade ser procedimentos, mas isso implicaria usar passagens de argumentos por referência, que é matéria futura.  Corrija-os logo que essa matéria for introduzida!


5.a)  Faça uma função que calcule a raiz positiva de um polinómio do segundo grau.  Recorda-se que a raiz positiva de um polinómio do segundo grau p(x) = a × x2 + b × x + c (i.e., a raiz da equação p(x) = 0) é dada por (-b + (b2 - 4ac)0,5) / 2a. Assuma que b2 - 4ac >= 0.

5.b)  E quando o utilizador dá às variáveis a b e c valores tais que  b2 - 4ac < 0 o que acontece?  Equipe a função com um instrução de asserção para verificar se b2 - 4ac >= 0, como se pretende.  Utilize a instrução if (descrita no Resumo da Aula 2) de modo a que, se o utilizador der valores às variáveis a, b e c tais que b2 - 4ac < 0, o programa emita a mensagem de erro:

Não existem raízes reais.


6.  Construa uma função que devolva o valor booleano true caso os seus dois argumentos (do tipo char) sejam iguais e false no caso contrário.


7.  Faça um procedimento que permita desenhar uma "árvore de natal" (como no exemplo abaixo) com o número de níveis indicado pelo utilizador.  O número de níveis deve ser um argumento do procedimento.

Quantos níveis? 5

    *
    *
   ***
    *
   ***
  *****
    *
   ***
  *****
 *******
    *
   ***
  *****
 *******
*********