Nome do aluno: _______________________________________________
Número do aluno: ______________________
Assinatura do docente: ________________________________________
Identificação
Nome do aluno: _______________________________________________Número do aluno: ______________________
Turma: ____________
Frequência
Introdução à Programação
IGE e ETI
1º semestre de 2001/2002
ISCTE
Deve preencher todos os espaços indicados por um sublinhado (___) com V ou F. Qualquer espaço não preenchido será considerado como uma resposta errada.
Em geral as alíneas podem ter zero ou mais respostas correctas. Cada resposta correctamente assinalada vale 0,5 valores.
Nas alíneas em que apenas uma resposta está correcta (se existirem estão assinaladas no texto), responder com mais ou menos do que um V anula a cotação. A resposta correcta corresponde à cotação completa. Qualquer outra resposta corresponde a zero valores.
Em todos os casos em que não é explicitamente referida a localização de uma instrução, considere que esta é dada na função main() do programa seguinte:
#include <iostream>
#include <vector>
using namespace std;
class Lâmpada {
public:
Lâmpada(bool const está_acesa = true);
bool estáAcesa() const;
void acende();
void apaga();
private:
enum Estado {apagada, acesa};
Estado estado;
};
Lâmpada::Lâmpada(bool const está_acesa)
: estado(está_acesa ? acesa : apagada)
{}
void Lâmpada::acende()
{
estado = acesa;
}
void Lâmpada::apaga()
{
estado = apagada;
}
bool Lâmpada::estáAcesa() const
{
return estado == acesa;
}
int main()
{
Lâmpada const vigia;
...
}
1.1 Admita que qualquer uma destas instruções é dada na função main() imediatamente após a definição da constante vigia. Quais das seguintes instruções estão correctas?
__ Lâmpada a;
__ Lâmpada a(Lâmpada::apagada);
__ Lâmpada a(vigia.estáAcesa());
[cotação: 1,5]
1.2 Admita que qualquer uma destas instruções é dada na função main() do programa acima. Quais das seguintes instruções estão correctas?
__ Lâmpada a = vigia;
__ vigia.apaga();
__ bool estado = vigia.estáAcesa();
__ cout << vigia.estado;
[cotação: 2]
1.3 Assuma que as seguintes instruções
são dadas dentro de uma função ou procedimento membro
da classe
Lâmpada
e que não são declaradas quaisquer variáveis
ou constantes dentro dessa função ou procedimento (que não
tem quaisquer parâmetros). Quais das seguintes instruções
estão correctas?
__ estáAcesa() = true;
__ estado = false;
[cotação: 1]
1.4 Suponha o seguinte código adicional:
Assumindo que os restantes métodos da classe estão definidos, qual é o resultado da invocação do programa?
void acendeLâmpadasPares(vector<Lâmpada> luzes_de_natal)
{
for(vector<Lâmpada>::size_type i = 0;
i < luzes_de_natal.size();
i += 2)
luzes_de_natal[i].acende();
}
int númeroDeLâmpadasAcesas(vector<Lâmpada> const& luzes_de_natal)
{
int número_de_lâmpadas_acesas = 0;
for(vector<Lâmpada>::size_type i = 0;
i != luzes_de_natal.size();
++i)
if(luzes_de_natal[i].estáAcesa())
++número_de_lâmpadas_acesas;
return número_de_lâmpadas_acesas;
}
int main()
{
vector<Lampada> luzes_de_natal(50);
acendeLâmpadasPares(luzes_de_natal);
cout << númeroDeLâmpadasAcesas(luzes_de_natal) << endl;
}
__ 50
__ 0
__ 25
__ 26
[cotação: 0,5]
Identificação
Nome do aluno: _______________________________________________Número do aluno: ______________________
Questão 2
Dada a grande quantidade de informação que actualmente é difundida usando o SMS (Short Message Service) começa a sentir-se a necessidade de dispor de sistemas de gestão de informação que permitam guardar as mensagens que são trocadas usando o telemóvel. Normalmente, as mensagens recebidas são guardadas numa pasta de entradas e as mensagens enviadas numa pasta de saídas. Ambas as pastas têm uma capacidade limitada, relativamente pequena.
Pretende-se desenvolver um sistema que permita gerir as
mensagens de texto, trocadas usando o telemóvel, num computador
pessoal. Deste modo teríamos capacidade para guardar maior
número de mensagens, bem como de aumentar o número de pastas
permitindo uma melhor organização da informação.
As mensagens de texto são constituídas pelo texto da mensagem
(cadeia de caracteres), pelo remetente (cadeia de caracteres), pela data (Data
) e pela hora
(Hora
).
2.1 Defina apenas a interface de uma classe C++ MensagemDeTexto que representa uma mensagem de texto. A classe C++ MensagemDeTexto deve dispor de um construtor que recebe os dados necessários à construção de uma mensagem de texto e operações que permitam inspeccionar:
Não é necessário nesta alínea definir quaisquer métodos da classe.
[cotação: 3]
2.2 A classe Pasta representa uma pasta onde são guardadas as mensagens de texto:
/**
Representa uma pasta que guarda mensagens de texto.@invariant
nome_
<> "".*/
class Pasta {
Constrói uma pasta.
public:
/**
@pre
nome
<> "".
@post
nome()
=nome
enúmeroDeMensagens()
= 0.*/
Pasta(string const& nome);
/**
Devolve o nome da pasta.
@pre V.
@post
nome()
é o nome da pasta.*/
string nome() const;
Devolve o número de mensagens na pasta.
/**
@pre V.
@post
númeroDeMensagens()
é o número de mensagens da pasta.*/
int númeroDeMensagens() const;
Adiciona a mensagem de texto recebida como argumento no fim da pasta.
/**
@pre
númeroDeMensagens()
= n e (Q j : 0 <= j < n :mensagem(
j)
= mj).
@post (Q j : 0 <= j <
númeroDeMensagens()
- 1 :mensagem(
j)
= mj) e
mensagem[númeroDeMensagens()
- 1]
=mensagem_de_texto
e
númeroDeMensagens()
= n + 1.*/
void adiciona(MensagemDeTexto const& mensagem_de_texto);
/**
Remove a mensagem de texto na posição recebida como argumento.
@pre 0 <=
posição
eposição
<númeroDeMensagens()
e
númeroDeMensagens()
= n e (Q j : 0 <= j < n :mensagem(
j)
= mj).
@post (Q j : 0 <= j <
posição
:mensagem(
j)
= mj) e(Q j :
posição
<= j <númeroDeMensagens()
:mensagem(
j)
= mj+1)
númeroDeMensagens()
= n - 1.*/
void removeMensagemNaPosicao(int const posição)
Devolve a mensagem de texto na posição recebida como argumento.
/**
@pre 0 <=
posição
eposição
<númeroDeMensagens()
.@post
mensagem()
é a mensagem de texto na posiçãoposição
.*/
MensagemDeTexto const& mensagem(int const posição) const;
/**
Mostra no ecrã o cabeçalho de todas as mensagens de texto.
@pre V.
@post
¬canal
ou o ecrã contém o remetente, a data e a hora de todas as mensagens.void mostraMensagens() const;
Devolve verdadeiro se o invariante se verificar.
private:
string nome_;
vector<MensagensDeTexto> mensagens_de_texto;
/**
@pre V.
@post
cumpreInvariante
=nome_
<> "".*/
bool cumpreInvariante() const;
};
Defina os métodos:
void removeMensagemNaPosicao(int const posição)
,
sem esquecer que, de acordo com a CO, a ordem das mensagens na pasta não
deve ser alterada (note que dadas estas especificações, seria mais adequado
usar uma lista (list<Tipo>
) em vez de um
vector (vector<Tipo>
) na representação
da pasta, no entanto, só na disciplina de POO é que estas serão
abordadas); evoid mostraMensagens() const
, sabendo que o cabeçalho
de uma mensagem é composto pelo remetente, a data e a hora.No caso do método void removeMensagemNaPosicao(int const posição)
coloque instruções de asserção para verificar a PC e a CIC.
Não tente explicitar nestas asserções os termos das condições envolvendo
quantificadores.
[cotação: 3.5]
Questão 3
Considere um tipo abstracto de dados que permita representar números binários como cadeias de '0' e '1'.
Uma cadeia é binária se contiver apenas '0' e '1' ou se estiver vazia. Uma cadeia binária é normalizada se for binária, tiver comprimento maior ou igual a um, e não contiver '0' à esquerda, excepto se contiver um único '0'.
/**
Indica se a cadeia recebida contém apenas '0' e '1'.@pre V.
@post
éBinario =
(Q j : 0 <= j <
bits.length()
:bits[j]
= '0' oubits[j]
= '1').*/
Indica se a cadeia recebida é binária e está normalizada, i.e., não contém zeros
bool éBinário(string const& bits);
/**
à esquerda (excepto se existir um único bit).
@pre V.
@post
éBinárioNormalizado
=éBinário(bits)
ebits.length()
!= 0e (
bits.length()
= 1 oubits[0]
= '1').*/
Devolve a versão normalizada da cadeia binária à entrada.
bool éBinárioNormalizado(string const& bits);
/**@pre
éBinário(bits)
.@post
éBinárioNormalizado(versaoBináriaNormalizadaDe)
ee
versaoBináriaNormalizadaDebits
representam o mesmo
número binário.
*/
Devolve uma versao invertida da cadeia à entrada.
string versaoBináriaNormalizadaDe(string bits);
/**@pre V.
@post
inversoDe.length() = cadeia.length()
e(Q j : 0 <= j <
cadeia.size()
:
inversoDe[
j]
=cadeia[cadeia.length()
- 1 - j]
).*/
Representa números binários como cadeias de '0' e '1'.
string inversoDe(string const& cadeia);
/**@invariant
éBinárioNormalizado(bits_)
.*/
Constrói novo número binário dada uma cadeia de bits.
class Binário {
public:
/**@pre
éBinário(bits).
@post
*this
ebits
representam o mesmo número binário.*/
Devolve a cadeia de bits correspondente ao binário.
Binário(string const& bits);
/**@pre V.
@post
eBinárioNormalizado(bits)
ebits
e*this
representam o mesmonúmero binário.
*/
Devolve o "ou" binário (bit a bit) do binário com outro binário dado.
string const& bits() const;
/**@pre V.
@post
operator or
é o ou bit a bit dos números binários*this
eoutro
.*/
Indica se o binário cumpre a condição invariante de classe.
Binário const operator or (Binário const& outro) const;
private:
string bits_;
/**@pre V.
@post
éBinárioNormalizado(bits_)
.*/
bool cumpreInvariante() const;
};
Sabendo que
string const& Binário::bits() const
{
assert(cumpreInvariante());
return bits_;
}
bool Binário::cumpreInvariante() const
{
return éBinárioNormalizado(bits_);
}
implemente os métodos restantes, de modo a que o seguinte código seja válido.
Binário
um_número_binário("001");
Aparece 1;
cout << um_número_binário.bits()
<<
endl; //
Aparece 1000;
Binário outro_número_binário("1000");
cout << outro_número_binário.bits()
<< endl;
//
Aparece 1001;
Binário disjunção =
um_número_binário or outro_número_binário;
cout << disjunção.bits() <<
endl; //
[cotação: 3,5]
Identificação
Nome do aluno: _______________________________________________Número do aluno: ______________________
Questão 4
Suponha a função double traçoDe(double const m[tamanho][tamanho], int const n)
que devolve o
traço da matriz quadrada de double
definida pelos n
×n
primeiros elementos de
m
:
4.1 Indique a pré-condição (PC) e a condição objectivo (CO) da função e ainda a condição invariante (CI) do seu ciclo interno.
int const tamanho = 10;
double traçoDe(double const m[tamanho][tamanho], int const n)
{
assert(0 <= n and n <= tamanho);
double traço = 0.0;
for(int i = 0; i != n; ++i)
traço += m[i][i];
return traço;
}
[cotação: 1,5]
4.2 Prove que o ciclo está parcialmente correcto verificando que:
[cotação: 1,5]
Identificação
Nome do aluno: _______________________________________________Número do aluno: ______________________
Questão 5
Explique porque, numa determinada máquina, sucede a seguinte situação:
int n = 2147483647;
Aparece no ecrã -2147483648
++n;
cout << n << endl; //
Se lhe parecer conveniente para a explicação, admita que
os int
têm três bits.
[cotação: 2]