Os alunos no final das aulas 10 a 12 deverão conhecer:
Deverão também ser capazes de:
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.
O resumo da matéria abordada nesta aula prática pode ser consultado aqui.
Indique claramente pré-condição e condição objectivo de cada operação de cada classe desenvolvida.
1. Desenvolva um TAD chamado Lampada
, que represente uma
lâmpada. Acrescente o seu código ao ficheiro lampada.C
no directório ~/IP/Aula10
.
Nota: A lâmpada deve estar inicialmente apagada.
Nota importante: Este enunciado será resolvido ao longo de duas ou, se necessário, três aulas!
2. Pretende-se desenvolver um programa que permita gerir uma fila de espera de uma repartição pública. O funcionamento que se pretende para a repartição é o seguinte:
2.a) Faça o corpo principal do programa que contenha um menu com quatro opções:
string
. Cada uma das opções invoca operações (i.e., rotinas membro)
de um TAD FilaDeBI
a implementar de seguida. Este TAD
representa filas de BI.
Use um typedef
para definir BI
como sinónimo de
string. Porquê?
Ao longo do desenvolvimento, deixe um comentário no lugar onde ficará código que não esteja ainda em condições de escrever. Por exemplo:
// !!
Põebi
na traseira da fila.ou
/* !!
a fila está cheia?*/
É importante que marque com !!
(ou outro padrão à sua
escolha) os locais onde ainda falta acrescentar código. Dessa forma é
mais fácil encontrá-los com uma simples pesquisa textual (<ctrl-s>
no XEmacs).
Se necessário, anexe a esses comentário apenas o código necessário para que o código compile e para que seja possível testá-lo. A ideia é que seja sempre possível compilar e executar o código, ainda que incompleto!
Siga os seguintes passos na definição da interface do TAD (Tipo Abstracto
de Dados) FilaDeBI
.
Muitas vezes, ao executar um dos passos sugeridos, conclui-se que se cometeram
erros ou omissões nos passos anteriores. Nesse caso deve-se
voltar atrás voltando a repetir os passos intermédios!
2.b)
Comece por pensar o que é uma FilaDeBI
. Neste passo é
particularmente importante pensar que operações podem ser
realizadas sobre uma fila de string
. Inspire-se no código
já desenvolvido para identificar as operações necessárias para este TAD. Um tipo particularmente importante
de operações são as operações construtoras.
Estas operações são usadas para construir novas variáveis
do TAD (pense no que é necessário saber para construir
uma nova fila).
2.c) Defina a interface do TAD. Este passo corresponde a indicar todos os membros públicos da classe C++. A maior parte das vezes os membros públicos são apenas operações (rotinas membro), embora por vezes sejam também tipos e, mais raramente, constantes. Na interface do TAD devem estar declaradas as operações do TAD, incluindo a respectiva documentação!
Será razoável que a classe permita à
função main()
aceder sem quaisquer restrições
aos números de bilhete de identidade guardados na fila? Por exemplo deverá
ser permitido escrever por cima de um bilhete de identidade no meio da fila ("dar o golpe")?
Como impedir que um programador que utiliza esta classe C++ (programador
consumidor) o faça de modo indevido? Coloque políticas de
acesso apropriadas nos membros da classe C++, se é que ainda não o fez. Resista
sempre à
tentação de tornar os atributos públicos (particularmente
se forem variáveis membro).
Em simultâneo com a definição
da interface do TAD, desenvolva um programa de teste que permita
verificar o seu bom funcionamento. Esse programa deve testar
exaustivamente todas as
operações da interface do TAD, num conjunto tão vasto quanto possível de
possibilidades. Esse programa deve ser colocado numa
função main()
à parte. Os testes devem verificar o bom
funcionamento da classe e respectivas operações através de instruções de
asserção. Note-se que o programa de teste ou não faz nada, o que
significa que os testes foram executados com êxito, ou aborta numa asserção
falhada, se houver algum problema.
O ficheiro deve ter a seguinte estrutura:
#include <iostream>
#include <iostream>
#include <string>...
#ifdef TESTE
///
O programa de teste.
int main()
{
...
}
#else
///
O programa propriamente dito.
int main()
{
...
}
#endif // TESTE
Altere o programa de gestão de filas de espera de modo a fazer uso do novo TAD, ainda não totalmente definido.
Para construir o programa da gestão de filas de espera usa-se o comando de
compilação usual. Para construir o programa de teste deve editar a linha
de compilação à mão (copie para lá o comando de compilação, que começa
com c++
e que surge na janela de compilação) colocando a opção -DTESTE
logo após c++
. Ou seja, o comando deve começar com c++
-DTESTE
.
Ao programa de teste, dedicado a testar o TAD FilaDeBI
,
chama-se teste de unidade.
2.d) Faça um embrião da implementação. Isto é, defina parcialmente todas as operações do TAD, deixando o respectivo corpo vazio (ou contendo apenas o necessário para não ocorrerem erros de compilação) embora incluindo um comentário explicando o que falta
// !!
e colocando desde já asserções para verificar:
(A uma condição que é verdadeira se o estado da implementação de um TAD for válido e falsa no caso contrário chama-se condição invariante de classe.)
Para a condição invariante de classe precisa de declarar um predicado privado
(e definir o respectivo método) chamado cumpreInvariante()
.
Neste momento já pode, e deve, compilar e executar o programa de gestão de filas de espera bem como o programa de teste. Como é óbvio, ainda não farão aquilo que é suposto...
2.e) Escolha uma representação para o TAD. Siga os seguintes passos:
cumpreInvariante()
). Neste caso os atributos são as
variáveis membro em que já pensou.cumpreInvariante()
.Implemente o construtor da classe (que inicializa os atributos da classe de modo a que a fila esteja vazia).
Como é evidente, ambos os programas devem continuar a compilar, embora funcionem deficientemente.
2.f) Implemente iterativamente cada uma das operações do TAD. (À implementação de uma operação chama-se método.)
Teste cada método logo que o implementar. Naturalmente deve começar por implementar pelo menos um construtor do TAD.
2.g) Teste o programa de gestão de filas de espera desenvolvido. Como o TAD está já testado, tem alguma certeza de que erros, a existirem, já não se devem ao TAD! Com um pouco de sorte ter-se-á enganado na implementação, o que lhe permitirá perceber a vantagem da programação por contrato, onde se usam exaustivamente instruções de asserção.
3. Utilize o enumerado DiaDaSemana
definido no início
na secção Tipos enumerados
do resumo e defina o operador --
sufixo para este tipo de dados.