Guião da 6ª Aula Prática

Sumário

Começar por introduzir brevemente a instrução switch e o efeito de break num ciclo.

A parte restante deste guião tem a ver com o primeiro exercício da aula.  Talvez deva ser seguido levando um aluno ao quadro.

O objectivo é escrever uma função bool éMultiploDe(int const m, int const n) que devolva verdadeiro se e só se m for múltiplo de n.

A estrutura da função é:

bool éMultiploDe(int const m, int const n)
{
    ...
}

Discutir soluções.  Implementar a solução sugerida:

bool éMultiploDe(int const m, int const n)
{
    if(m % n == 0)
        return true;
    else
        return false;
}

Suponham que esta função foi escrita por vocês no âmbito de um projecto mais ou menos complexo.  Há uma equipa encarregue de testar o código produzido que aparece passado uns tempos a dizer que o vosso programa de vez em quando estoira com uma mensagem de erro:

Floating exception: core dumped

Chato, não é?  Entram em depuração do programa, e, passado algum tempo, detectam a origem do erro: a função não está preparada para lidar com o caso de n ser zero!

Discutir soluções.  Perguntar que fazer se o n for zero.  Sugerir caso com m = 10 e n = 0.

Perfeito.  A função foi corrigida:

bool éMultiploDe(int const m, int const n)
{
    if(n != 0)
        if(m % n == 0)
            return true;
        else
            return false;
    else
        return false;
}

A equipa de testes não detecta erro nenhum.  O programa é entregue ao cliente que o usa com sucesso durante meses.  Ao fim de uns meses o cliente detecta um problema: há casos em que os resultados do programa estão pura e simplesmente errados!  E duma forma subtil!  O cliente fica logo desconfiado que, por causa desse problema, pode ter perdido bastante dinheiro nos meses em que usou o programa sem o detectar.  Enraivecido, telefona à vossa empresa.  Vocês, depois de dias de depuração, detectam o problema:  a função diz que 0 não é múltiplo de 0!  A função finalmente atinge a correcção...

bool éMultiploDe(int const m, int const n)
{
    if(n != 0)
        if(m % n == 0)
            return true;
        else
            return false;
    else
        if(m == 0)
            return true;
        else
            return false;
}

Perfeito!  Mas vocês olham para o código e pensam.  "Caramba, tanto if.  O melhor era escrever uma só instrução de retorno com uma expressão booleana apropriada..."  Dito e feito:

bool éMultiploDe(int const m, int const n)
{
    return (m % n == 0 and n != 0) or (m == 0 and n == 0);
}

Entregam ao cliente e...  passado pouco tempo este aparece em pessoa, querendo bater em alguém: o programa estoira de vez em quando escrevendo uma mensagem incompreensível:

Floating exception: core dumped

Claro!  Outra vez a divisão por zero!  Para a evitar basta trocar a ordem dos termos da primeira conjunção:

bool éMultiploDe(int const m, int const n)
{
    return (n != 0 and m % n == 0) or (m == 0 and n == 0);
}

O mesmo resultado pode ser obtido usando

bool éMultiploDe(int const m, int const n)
{
    return (n != 0 and m % n == 0) or m == 0;
}

onde se faz uso do facto de 0 ser múltiplo de qualquer inteiro.

Aproveitar para falar de novo do cálculo atalhado dos operadores lógicos.

Moralizar um pouco, dizendo que é muito importante pensar bem nos problemas antes de os tentar resolver!

Resoluções

2.  Ver ex2.C.

3.  Ver ex3.C.  Uma sequência de valores é uma permutação de outra se:

4.a)  Ver ex4a.C.  Chamar a atenção para as várias formas de resolver o problema.  Começar por um ciclo clássico, com saída pela guarda.

4.b)  Ver ex4b.C.

4.c)  Esta alínea é ou não relevante, dependendo da forma como os alunos escreveram os ciclos nas alíneas anteriores.

5.a)  Ver ex5a.C.

5.b)  Ver ex5b.C.

6.  Ver ex6.C.

7.  Ver ex7.C.

8.a)  Ver ex8a.C.

8.b)  Ver ex8b.C.  Notar que, ou o '.' aparece no local certo (no final de uma sequência de dígitos correspondentes a um número inteiro de letras), ou será considerado como equivalente a '1'!