Recibo do Exame de 2ª Época de Programação Orientada para Objectos (IGE e ETI),
2002/09/14, 2º semestre de 2001/2002, ISCTE:

Nome do aluno: _____________________________________________ Número do aluno: __________

Assinatura do docente: ________________________________________



Exame de 2ª Época

Programação Orientada para Objectos

IGE e ETI

2002/09/14 - 2º semestre de 2001/2002

ISCTE


Notas:

 

 

 

Questão 1

Assinale com V (Verdadeiro) as expressões que estão correctas e com F (Falso) as que estão incorrectas.

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.

Considere as seguintes definições de classes:

class Veiculo {
  public:
    Veiculo(string const& matricula, double const valor)
        : matricula_(matricula), valor_(valor) {}
    virtual ~Veiculo() {}

    string const& matricula() const {
        return matricula_;
    }

    double valor() const {
        return valor_;
    }

    virtual int velocidadeMaximaNaAutoEstrada() const {
        return 120;
    }

    void mudaValorPara(double const valor) {
        valor_ = valor;
    }

  private:
    string matricula_;
    double valor_;
};

class VeiculoPesado : public Veiculo {
  public:
    VeiculoPesado(string const& matricula,
                  double const valor, double const peso_bruto);
    virtual ~VeiculoPesado() {}

    double valor() const;

    virtual int velocidadeMaximaNaAutoEstrada() const {
        return 100;
    }

  private:
    double peso_bruto;
};

 


Identificação

Nome do aluno: _____________________________________________ Número do aluno: __________


 

1.1  Quais dos seguintes troços de código estão correctos (mesmo que não recomendáveis)?

__ VeiculoPesado::VeiculoPesado(string const& matricula,
                                double const valor,
                                double const peso_bruto)
   
    : Veiculo(matricula, valor), peso_bruto(peso_bruto) {}

__ VeiculoPesado::VeiculoPesado(string const& matricula,
                                       double const valor,
                                       double const peso_bruto)
   {
       Veiculo(matricula, valor);
       peso_bruto(peso_bruto);
   }

__ VeiculoPesado::VeiculoPesado(string const& matricula,
                                       double const valor,
                                       double const peso_bruto_)
       : Veiculo(matricula, valor)
   {
       peso_bruto = peso_bruto_;
   }

[cotação: 1,5 valores]

 

1.2  O método double valor() const da classe VeiculoPesado deve devolver o valor inicial deste veículo (passado ao construtor) menos um valor fixo de 50 de gastos administrativos.  Desta forma, um veículo pesado que seja construído como:

VeiculoPesado pesado1("14-11-AG", 2000, 5000);

deve devolver o valor 1950 quando invocado o método double valor() const.

Quais das implementações seguintes estão correctas?

__ double VeiculoPesado::valor() const { return valor_ - 50; }

__ double VeiculoPesado::valor() const { return Veiculo::valor() - 50; }

__ double VeiculoPesado::valor() const { return super->valor() - 50; }

[cotação: 1,5 valores]

 

 

 

1.3  As seguintes sequências de instruções escrevem valores no ecrã.  Compare as instruções com as saídas anunciadas e verifique se estão correctas.

__ VeiculoPesado* pesado2 = new VeiculoPesado("14-12-AG", 2500, 5000);
   cout << pesado2->valor() << endl;

   Saída no ecrã: 2450

__ VeiculoPesado* pesado2 = new VeiculoPesado("14-12-AG", 2500, 5000);
   cout << pesado2->velocidadeMaximaAutoEstrada() << endl;

   Saída no ecrã: 120

__ Veiculo* pesado3 = new VeiculoPesado("14-13-AG", 1500, 5000);
   cout << pesado3->valor() << endl;

       Saída no ecrã: 1450

__ Veiculo* pesado3 = new VeiculoPesado("14-13-AG", 1500, 5000);
   cout << pesado3->velocidadeMaximaAutoEstrada() << endl;

   Saída no ecrã: 100

[cotação: 2 valores]

 

 

 

 

 

 

 

 

 

 

 

 

 


Identificação

Nome do aluno: _____________________________________________ Número do aluno: __________


Questão 2

Recorde-se que deve ler atentamente todo o enunciado antes de resolver as questões!

A escalada de terrorismo a nível mundial evidenciou a importância de dispor de sistemas em que seja possível aceder rápida e criteriosamente a informações de segurança.  Assim, em Portugal, o SIS (Sistema de Informações de Segurança) pretende substituir o seu sistema de informações, de modo a poder responder prontamente às mais diversas situações.

Numa primeira fase, o sistema a desenvolver deve guardar os dados dos agentes e as informações obtidas por estes. Sobre um agente é necessário guardar o código de identificação e o nome.  Em relação às informações, é necessário guardar a data (inteiro) e o texto, e deve ser possível aceder aos dados do agente que a obteve.

Para cada agente deve ser possível:

Existem dois tipos de informações: informações obtidas a partir de escutas e informações obtidas através de informadores. Para as informações obtidas a partir de escutas, é necessário saber o nome da pessoa escutada.  No caso das informações obtidas através de informadores, é necessário guardar o nome do informador, o contacto deste e uma percentagem de fiabilidade.  As informações obtidas a partir de escutas dividem-se em informações a partir de escutas telefónicas e informações a partir de escutas com microfone.  Para as informações obtidas a partir de escutas telefónicas, importa guardar o número de telefone escutado, a duração da chamada, se o outro telefone foi identificado ou não e, se sim, qual o número do outro telefone.  Para as informações a partir de escutas com microfone, é necessário guardar a localização do microfone, a duração da gravação, se foram identificados os intervenientes e, em caso positivo, os nomes dos mesmos.

Todos os tipos de informação devem possuir:

O cálculo da relevância de uma informação funciona do seguinte modo:

  1. Cálculo do coeficiente textual: número de palavras diferentes no texto da informação a dividir pelo número total de palavras do texto da informação;
  2. Cálculo do coeficiente específico:
  3. Cálculo da relevância: 0,70 × coeficiente textual + 0,30 × coeficiente específico.

As informações devem ser guardadas numa base de conhecimento, organizadas por data e por relevância.  A base de conhecimento deve permitir

Os dados dos vários agentes são guardados no quadro de agentes da organização.

Pretende-se implementar, em C++, uma aplicação para apoio à gestão e consulta de informações de segurança.  Esta aplicação permite aos seus utilizadores consultar as informações presentes na base de conhecimento e adicionar as novas informações que vão sendo obtidas, bem como realizar a gestão dos agentes do quadro.

Considere a existência da classe genérica std::list disponível na biblioteca padrão do C++ e utilize variáveis dinâmicas quando entender adequado.

2.1  Desenhe um diagrama de classes, utilizando a notação UML, que corresponda a parte do modelo da aplicação descrita. Este diagrama deve incluir as classes Agente, Informação, InformaçãoAPartirDeEscuta, InformaçãoAPartirDeInformador, InformaçãoAPartirDeEscutaTelefónica, InformaçãoAPartirDeEscutaComMicrofone, BaseDeConhecimento e Quadro.  É necessário incluir no diagrama a representação das classes, das relações entre as classes e das multiplicidades das associações.

Não é necessário nesta alínea inscrever nas classe os respectivos atributos e operações.

[cotação: 2]

 

 

 

 

 

 

 

 

 

2.2  Defina as classes Agente, Informação, InformaçãoAPartirDeEscuta, InformaçãoAPartirDeInformador, InformaçãoAPartirDeEscutaTelefónica e BaseDeConhecimento.  Indique a condição invariante de classe (CIC).  Adicione a operação necessária para verificar a CIC.

Não é necessário nesta alínea definir quaisquer métodos das classes.

[cotação: 2]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.3  Implemente os métodos da classe BaseDeConhecimento que permitem:

[cotação: 2]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.4  Implemente o destrutor da classe BaseDeConhecimento.

[cotação: 1]

 

 

 

 

 

 

 

 

 

 

 

 

 

2.5  Implemente o método da classe BaseDeConhecimento que permite saber se há informações com classificação superior a uma dada relevância.

[cotação: 1]

 

 

 

 

 

 

 

 

 

 

2.6  Implemente os métodos das classes InformaçãoAPartirDeEscutaTelefónica e InformaçãoAPartirDeInformador responsáveis pelo cálculo da classificação da informação.

[cotação: 1,5]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Identificação

Nome do aluno: _____________________________________________ Número do aluno: __________


Questão 3

No desenvolvimento de aplicações para o processamento de língua escrita é, em muitas situações, necessário usar informação estatística obtida a partir de texto.  Esta informação é usada nas aplicações na forma de um dicionário.  Neste caso, como a informação que nos interessa é a frequência das entradas na língua escrita e não a definição da entrada (como é comum), estes dicionários são denominados dicionários de frequência.  Por outro lado, nos dicionários comuns, normalmente, as entradas são palavras.  No entanto, nesta área isso nem sempre é verdade.  Com efeito, podemos ter vários tipos de entradas: palavras, expressões, tuplos de palavras, ...

Assim, pretende-se desenvolver uma classe genérica DicionárioDeFrequência que representa dicionários de frequência em que as entradas podem ser de qualquer tipo, mas não em simultâneo.

A classe C++ genérica deve permitir

Considere preferencialmente a existência da classe std::map disponível na biblioteca padrão do C++, ou em alternativa a classe std::list.

3.1  Defina completamente a classe genérica DicionárioDeFrequência.  Indique a condição invariante de classe (CIC).  Adicione a operação necessária para verificar a CIC.

[cotação: 1,5]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.2  Indique que requisitos deve verificar a classe que representa as entradas do dicionário.

[cotação: 1]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Identificação

Nome do aluno: _____________________________________________ Número do aluno: __________


Questão 4

Considere a definição do agregado Elo usado para implementar o conceito de cadeia duplamente ligada (não circular) com guardas.

struct Elo {
    //
O item propriamente dito:
    int item;
    //
Ponteiro para o elo anterior na cadeia:
    Elo* anterior;
    //
Ponteiro para o elo seguinte na cadeia:
    Elo* seguinte;
};

4.1  Observe atentamente o código abaixo e dê um nome apropriado ao procedimento.

void xxxxx(Elo* const elo, Elo const* const inicial, Elo const* const final)
{
    assert(elo != inicial and elo != final);

    elo->anterior->seguinte = elo->seguinte;
    elo->seguinte->anterior = elo->anterior;
}

[cotação: 0,5]

 

 

 

 

 

 

 

 

 

 

 

4.2  Implemente o procedimento que realiza a operação inversa do apresentado na alínea anterior.  Adicione ao cabeçalho do procedimento o(s) parâmetro(s) necessário(s).  Indique claramente através de um pequeno comentário as opções tomadas.

[cotação: 1,5]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Identificação

Nome do aluno: _____________________________________________ Número do aluno: __________


Questão 5

Quais os níveis de garantia de segurança face a excepções que é comum considerarem-se? Explique resumidamente cada um deles.

[cotação: 1]