Aula prática 6

Sumário

Objectivos

Os alunos no final desta aula deverão conhecer:

  1. As instruções de controlo de fluxo condicional (if), de selecção (if else) e alternativa (switch).
  2. Os efeitos da instrução break numa instrução alternativa.
  3. As vantagens do desenvolvimento disciplinado de código.

Deverão também ser capazes de:

  1. Desenvolver programas usando instruções condicionais, de selecção e alternativas.
  2. Desenvolver semi-formalmente instruções condicionais, de selecção e alternativas.
  3. Seleccionar o tipo de instrução de controlo de fluxo apropriado para cada problema.

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)  Escreva uma função bool eMultiploDe(int const m, int const n) que devolva verdadeiro se m for múltiplo de n e falso no caso contrário.  Use o seguinte o programa de teste ex1.C que se encontra no directório ~/IP/Aula6.

1.b)  Se na alínea anterior usou instruções de selecção ou condicionais, elimine-as.  Resolva o problema usando apenas uma instrução (que é de retorno).  Experimente com os valores

10 0

à entrada.


Indique a pré-condição e a condição objectivo de todas as rotinas desenvolvidas daqui para a frente.


2.  Escreva uma função que devolva o número de dias de um mês num determinado ano.  Quer o mês quer o ano são passados como argumentos (pode assumir que o ano é maior do que 1752).  Lembre-se que os anos múltiplos de 4 são bissextos, com excepção dos múltiplos de 100, mas incluindo os múltiplos de 400 (esta regra só é válida para datas ocidentais em geral depois de 1752).


3.  Escreva um procedimento void ordena(int& a, int& b, int& c ,int& d) que ordene o valor dos argumentos.  Por exemplo, o seguinte troço de programa

int k = 10;
int l = 5;
int m = 3;
int n = 8;

ordena(k, l, m, n);

cout << k << ' ' << l << ' ' << m << ' ' << n << endl;

deve escrever no ecrã:

3 5 8 10

Pode usar o procedimento void swap(int& a, int& b) (usar #include <algorithm>) que troca os valores dos seus dois argumentos.


4.a)  Um canal de entrada (cin, por exemplo) fica em estado de erro se alguma leitura tiver falhado.  Por exemplo, se durante a leitura de um inteiro o utilizador começar por introduzir uma letra, a leitura falha e o canal fica em estado de erro.  Todas as leituras quando um canal está em estado de erro falham.  Para que as leituras passem a ter sucesso é necessário "limpar" o estado de erro.  Isso consegue-se com a instrução:

cin.clear();

Para saber se um canal está em estado de erro, basta recorrer à operação good() como se segue:

if(not cin.good())
    cout << "A leitura falhou!" << endl;

Escreva um procedimento void pedeInteiroPara(int& valor) que leia um valor inteiro pedido ao utilizador e o guarde no seu argumento, recebido por referência.  Em caso de erro o procedimento deve pedir de novo o inteiro ao utilizador.  Um exemplo de interacção é (valores introduzidos pelo utilizador em negrito):

Introduza um inteiro: tretas
Isso não parece um inteiro...
Introduza um inteiro: melga
Isso não parece um inteiro...
Introduza um inteiro: 10

Note-se que, em caso de erro, toda a linha introduzida deve ser descartada.  Para isso pode-lhe ser útil saber que a leitura de um caractere, sem descartar espaços, tabuladores e fins-de-linha, pode ser feita usando o método get(), que se invoca escrevendo cin.get() (métodos são rotinas "especiais", como se verá mais tarde).  Este método recebe como argumento (passado por referência) a variável onde é colocado o caractere lido e devolve o próprio canal, que, recorda-se, pode ser interpretado como um booleano.

Recorda-se ainda que o caractere correspondente ao fim-de-linha pode ser grafado em C++ usando uma sequência de escape: '\n'.

Escreva também um programa que teste o procedimento desenvolvido.

4.b)  Baseie-se no procedimento acima para escrever um outro procedimento void pedeInteiroLimitadoPara(int& valor, int const minimo, int const maximo) que peça um valor inteiro ao utilizador, o leia e o guarde no seu argumento, recebido por referência.  Só admite inteiros não inferiores a minimo nem superiores a maximo.  Se o utilizador se enganar, assinala o erro, descarta a linha e volta a pedir o valor inteiro.

4.c)  É possível terminar abruptamente um ciclo usando uma instrução de retorno.  Consegue melhorar o código produzido nas alíneas anteriores usando esta informação?


5.a)  Escreva um programa que, dado um número inteiro entre 0 e 99 o escreva por extenso duma forma simplificada.  Use como exemplo o programa no ficheiro ex5.C, que pode encontrar no directório ~/IP/Aula6.  Por exemplo:

Introduza um número: 35
O número introduzido foi três dezenas e cinco unidades.
Modularize o programa o melhor possível.  Faça uso da função desenvolvida nas alíneas 4.b) e 4.c).

5.b)  Se desejasse que o programa escrevesse

O número introduzido foi trinta e cinco.

o que deveria fazer?


6.  Escreva um procedimento que receba com argumento um inteiro entre 1 e 99 e o escreva em numeração romana.  Deverá utilizar os procedimentos void escreveUnidadesEmRomano(int const unidades) e void escreveDezenasEmRomano(int const dezenas).  Crie um programa para experimentar o funcionamento dos procedimentos criados.  Este programa deverá proporcionar o controlo de erros, i.e., evitar que o procedimento, que faz a conversão para numeração romana, receba um argumento com um valor fora da gama de valores possíveis (1 a 99).


7.  Faça um programa que, dado um número inteiro que representa a idade de uma pessoa, escreva qual a sua faixa etária.  As faixas etárias são definidas do seguinte modo: entre 0 e 12 anos - criança, de 13 a 19 - adolescente, de 20 a 59 - adulto, acima de 60 - idoso.


8.a)  Suponha que as letras A, B, C e D foram codificadas em zeros e uns da seguinte forma: A = 0, B = 11, C = 100 e D = 101.  Crie um programa que, quando é introduzido um conjunto de zeros e uns a partir do teclado, descodifique a primeira letra que aparece.  Por exemplo:

Introduza um conjunto de zeros e uns: 1001001100110101.
C

8.b)  Melhore o programa anterior para descodificar uma sequência de zeros e uns até surgir o caractere '.'.  Use a operação peek() dos canais de entrada para "espreitar", sem ler, o próximo caractere disponível para leitura num canal (e.g., cin.peek()).  Por exemplo:

Introduza um conjunto de zeros e uns: 1001001100110101.
CCBAABAD

Em ambas as alíneas considere que qualquer caractere diferente de '0' deve ser interpretado como um '1'.

Para resolver esta alínea deverá recorrer a ciclos.