MEMec - LEAN
Computação e Programação
(2007/2008 - 1º Semestre)
Exame de 1ª Época: 2008-01-23
DURAÇÃO: 3 horasRESOLUÇÃO
Leia com atenção os pontos que se seguem:
• Comece por escrever o seu nome e número nesta folha, e número nas restantes.
• Não desagrafe as folhas.
• Não se tiram dúvidas durante a realização do exame.
• O exame é sem consulta.
• Escreva as suas respostas nos espaços indicados.
• Se necessitar de mais folhas do que as disponibilizadas junte folhas A4
devidamente identificadas (nome e número) e com a indicação da pergunta/alínea
correspondente.
• Nas perguntas de Verdadeiro e Falso assinale as respostas como
:
no quadrado
respectivo. Caso queira emendar uma resposta, risque completamente o quadrado
respectivo e coloque à esquerda da opção que considera correcta o símbolo
:.
• Cada resposta errada nas perguntas de escolha múltipla desconta metade da
cotação da pergunta (na cotação global do exame)!
• Inicie o exame apenas quando o docente der indicação.
P1 Escolha múltipla (3 valores)
NOTA IMPORTANTE: cada resposta errada nas perguntas de escolha múltipla desconta metade da cotação da pergunta (na cotação global do exame)!
1.a) Erros na compilação de um código fonte implica que: (0.25v)
Seleccione a resposta correcta:
O algoritmo do programa está incorrecto Existem erros semânticos no código fonte
:
Existem erros de sintaxe no código fonte Nenhuma das anteriores1.b) Um conjunto de instruções obtido após compilação e ligação (link) correctas designa-se por: (0.25v) Seleccione a resposta correcta:
Assembler Programa objecto
: Programa executável
Nenhuma das anteriores1.c) Qual dos símbolos representa um operador lógico em C++ ? (0.25v)
Seleccione a resposta correcta: !=
= # >
: Nenhuma das anteriores
1.d) A função main() em C++: (0.25v)
Seleccione a resposta correcta:
Retorna sempre um double para o sistema operativo. Possui um número limite de chamadas a outras funções. Pode ser omitida no código fonte.
1.e) Quantos bits são alocados para uma variável do tipo char (em C++)? (0.25v) Seleccione a resposta correcta:
1 2 4
:
81.f) Quantos bytes são alocados para uma variável do tipo int (em C++)? (0.25v)
Seleccione a resposta correcta:
: 4
6 8
Nenhuma das anteriores
1.g) Qual é valor que é apresentado no monitor quando é executada a seguinte linha de código?
(0.25v)
cout << (int (11.0))/2.0 << endl; Seleccione a resposta correcta:
11/2
: 5.5
5Nenhuma das anteriores
1.h) Qual é valor que é apresentado no monitor quando é executada a seguinte linha de código?
(0.25v)
cout << !(1+1) << endl; Seleccione a resposta correcta:
:
0 1 2 31.i) Quais são os valores de a, b e c após o código ser todo executado? (0.25v)
a = 1; b = a+a++; c = ++a;
Seleccione a resposta correcta:
a = 3, b = 1, c = 4 a = 1, b = 2, c = 2
:
a = 3, b = 2, c = 3 a = 2, b = 4, c = 1 Nenhuma das anteriores1.j) O que é o âmbito (scope) ? (0.25v)
Seleccione a resposta correcta:
:
É a visibilidade e tempo de vida de variáveis locais e globais. É a capacidade que uma função possui de se chamar a si própria.É a possibilidade de distinção entre nomes de variáveis escritas em letras minúsculas e maiúsculas.
Nenhuma das anteriores.
1.l) Considere as seguintes afirmações sobre classes em C++. (0.25v) Seleccione a resposta correcta:
Um acessor tem que possuir o mesmo nome da classe.
:
Os atributos públicos podem ser acedidos directamente fora das definições associadas à classe.É comum que uma classe apenas possua como construtor, o construtor implícito. Um atributo privado pode ser acedido directamente fora das definições
associadas à classe. Nenhuma das anteriores.
1.m) Considere a seguinte declaração de uma classe, em C++.
Como pode alterar a marca do carro denominado oMeuPrimeiroCarro, quando utiliza a
classe carro? (0.25v) class carro { public: int m_ano; string m_marca;
void altera_modelo(string modelo); private:
string m_modelo; };
Seleccione a resposta correcta:
oMeuPrimeiroCarro.altera_marca("Proze"); oMeuPrimeiroCarro.m_marca == "Proze"; m_marca.oMeuPrimeiroCarro = "Proze";
:
oMeuPrimeiroCarro.m_marca = "Proze"; Nenhuma das anteriores.P2 Análise de código em C++ (3 valores)
2.a) Qual é ou quais são os resultados apresentados no monitor, para cada um dos seguintes três
programas? (0.5v)+(0.5v)+(0.5v)
#include <iostream> #include <cmath> using namespace std;
double funcao(double val); int main()
{
cout << (int) funcao(2.1); return 0;
}
double funcao(double val) { return val*pow(abs(ceil(val)),abs(floor(val))); } #include <iostream> #include <vector> using namespace std; int main() { vector<int> vec; for(int k = 0; k < 10; k++) vec.push_back(2*k);
for(unsigned int k = 0; k < vec.size(); k=2*k+1) cout << vec[k] << endl;
return 0; } RESPOSTA: RESPOSTA: 18 0 2 6 14
rectangulo.h #ifndef rectangulo_h #define rectangulo_h class rectangulo { public: rectangulo();
rectangulo(double altura, double largura); double retorna_largura();
double retorna_altura();
void altera_largura(double largura); void altera_altura(double altura); double calc_area(); double calc_perimetro(); private: double m_largura; double m_altura; }; #endif principal.cpp #include <iostream> #include "rectangulo.h" using namespace std; int main() { rectangulo recs[3]; for (int k=0;k<3;k++) recs[k]=rectangulo(k+1,k+2); recs[2].altera_altura(recs[1].calc_perimetro()); rectangulo rec2(recs[2].retorna_largura(),recs[0].calc_area()); cout << rec2.calc_perimetro(); return 0; }
2.b) Modifique os seguintes 3 programas de modo a que estes compilem e executem correctamente. (0.5v)+ (0.5v)+ (0.5v) NOTA IMPORTANTE: para modificar o código deve proceder do seguinte modo:
Numerar todas as linhas do código original.
Na sua resposta deve apenas indicar o número da linha se o código estiver correcto, caso o código esteja incorrecto deve indicar a linha e a respectiva alteração.
Caso necessite de adicionar novas linhas numere-as utilizando a linha anterior como base, seguida de um ponto e das letras a, b, etc.
RESPOSTA:
EXEMPLO: #include <iostream> using namespace std; int main() { string a = "varAux = "; double var = 0.5 cout < a < floor(var); return 0; } FIM DE EXEMPLO. #include <iostream> using namespace std; int main() { double alfa = 0.0, resultado = 0.0, int N = 0;
cout << "Calculo da serie"
<< "geometrica: \n"; cout << "\nInsira alfa e N: ";
cin.ignore() >> N >> alfa; assert(N >= 0);
for (int k = 0; k <= N; k++)
resultado += pow(alfa,k); cout << "Resultado da serie = " << cout << endl; } #include <iostream> #include <cassert> using namespace std; int main() { int vec[10]={0}; ifstream corr_entr; corr_entr.open("fichDeDados.txt".data()); assert(corr_entr.is_closed()); int k=10; while k<10 { if (!corr_entr.eof()) break; else { corr_entr << vec[k]; cout << vec[k] << endl;
k++; } } } RESPOSTA: RESPOSTA: RESPOSTA: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [1]
[1.a] #include <cmath> [1.b] #include <string> [2] [3] [4] [5] [6] [7] double var = 0.5; [8] cout << a << floor(var); [9] [10] [1] [1.a] [1.b] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] #include <iostream> #include <cmath> #include <cassert> using namespace std; int main() { double alfa = 0.0, resultado = 0.0; int N = 0;
cout << "Calculo da serie"
<< "geometrica: \n"; cout << "\nInsira alfa e N: ";
cin >> alfa >> N; assert(N >= 0);
for (int k = 0; k <= N; k++) resultado += pow(alfa,k); cout << "Resultado da serie = "
<< resultado << endl; } [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [1] [1.a] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] #include <iostream> #include <fstream> #include <cassert> using namespace std; int main() { int vec[10]={0}; ifstream corr_entr; corr_entr.open("ficheiroDeDados.txt"); assert(corr_entr.is_open()); int k=0; while (k<10)while (k<10) { if (corr_entr.eof()) break; else{ corr_entr >> vec[k];
cout << vec[k] << endl; k++;
} } }
cao.h #ifndef CAO #define CAO_H class cao { public: cao();
cao(string raca, int idade) const; string retorna_raca() const; void print(ostream & saida) const;
private: double m_raca; int m_idade; }; #endif test.cpp #include <iostream> #include <vector> using namespace std; int main() { vector<cao> canil; char opcao; while(true){
cout << "\nIntroduza raca e idade: "; cin >> raca >> idade;
canil.push_back(cao(idade,raca)); cout << "\nDigite c para continuar ";
cout << "a introduzir dados: "; cin >> opcao;
if (opcao == 'c') break; }
for (int k=0;k<canil.size();k++){ canil(k).print(cout);
cout << endl;} }
RESPOSTA:
(nota: assuma que os métodos estão correctamente definidos em cao.cpp) [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [1] [2] [3] [3.a] [3.b] [3.c] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [19.a] [19.b] [20] [21] [22] [23] [23.a] [23.b] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] cao.h #ifndef CAO #define CAO
#include <string> /// [opcional se em .cpp]
#include <iostream> /// [opcional]
using namespace std; ////[opcional]
class cao {
public: cao();
cao(string raca, int idade);
string retorna_raca() const; void print(ostream & saida) const; private: string m_raca; int m_idade; }; #endif test.cpp #include <iostream> #include <vector>
#include <string> //// [opcional se em .h]
#include "cao.h" using namespace std; int main() { vector<cao> canil; string raca; int idade; char opcao; while(true){
cout << "\nIntroduza raca e idade: "; cin >> raca >> idade;
canil.push_back(cao(raca,idade));
cout << "\nDigite c para continuar "; cout << "a introduzir dados: "; cin >> opcao;
if (opcao != 'c') break;
}
for (int k=0;k<canil.size();k++){
canil[k].print(cout);
cout << endl;} }
P3 Implementação em C++ (6 valores)
NOTA IMPORTANTE: a robustez dos programas ao tipo de entrada apenas deve ser considerada quando explicitamente pedida no enunciado da pergunta!
3.a) Escreva um programa em C++ que leia um ficheiro ASCII, denominado dados.dat (em que cada linha do ficheiro é constituída por um valor real) e que apresente no monitor o valor máximo e
mínimo existente no ficheiro de dados. (2.0v)
#include <iostream> #include <fstream> using namespace std; int main() {
double valor, min, max;
ifstream correnteEntrada; correnteEntrada.open("dados.dat");
if (!correnteEntrada.is_open()) {
cerr << "\n\aO ficheiro dados.dat nao existe!" << endl;
return 0; }
correnteEntrada.peek();
if (correnteEntrada.eof()) {
cout << "\nO ficheiro esta' vazio!!" << endl; correnteEntrada.close(); return 0; } correnteEntrada >> valor; min = valor; max = valor; while(true) { correnteEntrada >> valor; if (correnteEntrada.eof()) break; else { if (valor < min) min = valor;
else if (valor > max)
max = valor;
} }
correnteEntrada.close();
cout << "\nValor maximo = " << max << endl; cout << "Valor minimo = " << min << endl; }
3.b) Pretende-se a implementação de um programa em C++ que permita manipular um ficheiro de base de dados (ASCII) relativo a uma livraria.
Cada livro tem associado os seguintes dados:
- Título;
- Número de exemplares;
O ficheiro de dados (livraria.dat) possui o seguinte formato: 1ª linha define o título do livro 1 (uma ou mais palavras);
2ª linha define o número de exemplares existentes do livro 1 (um inteiro); 3ª linha define o título do livro 2 (uma ou mais palavras);
4ª linha define o número de exemplares existentes do livro 2 (um inteiro); Etc..
O programa deve permitir:
a) Procurar um livro pelo seu título, e caso o encontre, apresentar no monitor o seu número de existências;
b) Apresentar no monitor o número total de livros existentes na livraria; c) terminar programa.
3.b.i) Declare a classe livro (em livro.h) para lidar com o problema (apresente apenas os atributos e métodos que considera necessários para a implementação descrita). (0.5v)
3.b.ii) Defina cada um dos métodos (em livro.cpp) que declarou na alínea anterior. (1.5v)
#ifndef LIVRO #define LIVRO #include <iostream> #include <string> using namespace std; class livro { public:
livro(string titulo,int numExemplares);
int retorna_numExemplares() const; string retorna_titulo() const;
livro ler_dados(istream & corrEntr);
bool operator==(const livro & segundoOperando) const;
private:
string m_titulo;
int m_numExemplares; };
3.b.iii) Escreva o programa principal (em gerirLivraria.cpp) que implemente as
funcionalidades enunciadas. (2.0v)
#include "livro.h"
using namespace std;
livro::livro(string titulo,int numExemplares) {
m_titulo = titulo;
m_numExemplares = numExemplares; }
string livro::retorna_titulo() const
{
return m_titulo; }
int livro::retorna_numExemplares() const
{
return m_numExemplares; }
livro livro::ler_dados(istream & corrEntr) { getline(corrEntr,m_titulo); corrEntr >> m_numExemplares; corrEntr.ignore(1,'\n'); return livro(m_titulo,m_numExemplares); //outro modo:
//return *this; //retorna o próprio objecto
}
bool livro::operator==(const livro & segundoOperando) const
{
return (m_titulo == segundoOperando.retorna_titulo()); } #include <iostream> #include <fstream> #include <vector> #include "livro.h" using namespace std;
bool testaFicheiro (ifstream & corrEntr);
void constroiLivraria(istream & corrEntr,vector<livro> & livraria);
int main() {
const string nomeFicheiro = "livraria.dat";
bool terminar = false;
string opcao;
string titulo;
do
{
cout << "\na) Procurar um livro pelo seu titulo"
<< "\nb) Numero total de livros existentes"
<< "\nc) Prima tecla [c] ou [C] seguida de [enter] para terminar"
<< "\nEscolha uma opcao: "; getline(cin,opcao);
switch (opcao[0]) {
case 'a': case 'A': {
ifstream corrEntr;
if (testaFicheiro(corrEntr)) {
vector<livro> livraria;
constroiLivraria(corrEntr,livraria); corrEntr.close();
cout << "\nIntroduza um titulo: ";
getline(cin, titulo);
int posicao=-1;
for (unsigned int k=0;k<livraria.size();k++) { if (livraria.at(k)==livro(titulo,0)) posicao = int (k); } if (posicao !=-1) { cout << "\nExistem " <<livraria.at(posicao).retorna_numExemplares() << " exemplares do livro: " << titulo << endl; }
else
{
cout << "O livro: " << titulo
<< " nao existe na livraria!" << endl; } } else { corrEntr.close(); } } break; case 'b': case 'B': { ifstream corrEntr; corrEntr.open(nomeFicheiro.data()); if (testaFicheiro(corrEntr)) { vector<livro> livraria; constroiLivraria(corrEntr,livraria); corrEntr.close(); int somatorio=0;
for (unsigned int k=0;k<livraria.size();k++) {
somatorio +=livraria.at(k).retorna_numExemplares();
}
cout << "\nExistem " << somatorio << " livros na livraria!"
<< endl; } else { corrEntr.close(); } } break; case 'c': case 'C': {
cout << "\nOptou por terminar!";
terminar = true;
}
break;
default:
cerr << "\n\aOpcao invalida!" << endl; }
}
while(!terminar);
cout << "\nPrima qualquer tecla para encerrar o programa"
<< endl;
cin.get(opcao[0]); }
bool testaFicheiro(ifstream & corrEntr) {
if (!corrEntr.is_open()) {
cerr << "\n\aO ficheiro livraria.dat nao existe!" << endl;
return false; }
corrEntr.peek();
if (corrEntr.eof()) {
cout << "\nO ficheiro esta' vazio!!" << endl;
return false; }
return true; }
void constroiLivraria(istream & corrEntr,vector<livro> & livraria) { livro umLivro("",0); while(true) { corrEntr.peek(); if (corrEntr.eof()) return; livraria.push_back(umLivro.ler_dados(corrEntr)); } }
P4 MATLAB (6 valores)
NOTA IMPORTANTE: a robustez dos programas ao tipo de entrada apenas deve ser considerada quando explicitamente pedida no enunciado da pergunta!
4.a) Considere que as variáveis A=[1 , 2 ; 3 4] e x = [2 5], foram definidas na linha de comandos do Matlab. Escreva os comandos necessários em Matlab, de modo a que:
4.a.i) A variável z seja um vector coluna, e tal que cada um dos seus elementos seja igual
aos da 2ª linha de A. (0.25v)
4.a.ii) A variável z seja um vector linha, e tal que cada um dos seus elementos seja definido do seguinte modo: cada elemento de x como divisor de cada elemento correspondente do vector definido pela 1ª coluna de A. (0.25v)
4.a.iii) A variável z seja uma matriz de dimensão 2×3, igual à concatenação de A com o vector coluna correspondente aos elementos de x ao quadrado. (0.25v)
4.b) Escreva um pequeno script (m file) que defina a variável celula tal que esta seja um cell
array de dimensão 1×360, em que o conteúdo de cada elemento da célula é igual ao seno de 0º, 1º,
2º, …, 359º. (0.75v) z = A(2,:)' z = (A(:,1)')./x z = [A , (x.*x)'] for k=0:1:359 celula{1,k+1} = sin(k*(pi/180)); end
4.c) Escreva um script (m file), que peça ao utilizador um array linha (de dimensão variável) composto de valores inteiros e verifique se o array é um array linha e composto por inteiros. Após a verificação dos dados de entrada, o script deve apresentar uma mensagem correspondente no monitor. [Notas: A função rem(x,y) retorna o resto da divisão de x por y. A função round(z) retorna o valor inteiro mais próximo de z]. (1.5v)
clear all; close all; clc;
arrayEntrada = input('Introduza um array linha constituído apenas por valores inteiros: \n');
[numLinhas,numColunas]=size(arrayEntrada);
if (numLinhas == 1)
mensagem1 = 'O array é um array linha!';
else
mensagem1 = 'O array não é um array linha!';
end
mensagem2 = 'O array é composto apenas por valores inteiros!';
for k=1:1:numLinhas*numColunas
if arrayEntrada(k) ~= round(arrayEntrada(k))
mensagem2 = 'O array não é composto apenas por valores inteiros!'; break; end end disp(mensagem1); disp(mensagem2);
4.d) Escreva um script em MATLAB que calcule os N primeiros termos, da sucessão (definida recursivamente por):
y(n+2) = a × y(n+1) + b × y(n)
O script deve pedir ao utilizador os valores de N, a, b, y(0) e y(1), e apresentar um gráfico com o resultado. Deve ser implementada uma função recursiva (denominada dinamica.m), a qual deve ser chamada pelo script.
O programa só deve terminar após opção do utilizador, caso contrário deve pedir novos dados para cálculo. (3.0v) oMeuScript.m clear all; close all; clc; continuar=1; while(continuar) N=input('Introduza N: '); a=input('Introduza a: '); b=input('Introduza b: '); y_0=input('Introduza y(0): '); y_1=input('Introduza y(1): '); for k=0:1:N y_k(k+1) = dinamica(k,a,b,y_0,y_1); end stem(0:1:N,y_k);
title('y(n+2) = a × y(n+1) + b × y(n)'); xlabel('N');
ylabel('y');
continuar = input('Para terminar digite a tecla 0 [zero] seguida de [enter]: \n');
end
dinamica.m
function [y_N] = dinamica (N, a, b, y_0 , y_1) switch (N) case 0 y_N = y_0; case 1 y_N = y_1; otherwise
y_N = a * dinamica(N-1,a,b,y_0,y_1) + b * dinamica(N-2,a,b,y_0,y_1);
end
P5 Algoritmia (2 valores)
5.a) Pretende-se implementar uma função, que irá fazer parte do software de uma máquina de Multibanco, que terá como objectivo minimizar o número de notas a dar ao utilizador.
Essa função deve receber um valor múltiplo de 5 (euros) e menor ou igual a 200 (euros), ou seja, o dinheiro a levantar, e deve devolver o número mínimo de notas (200, 100, 50, 20, 10 e 5 euros) que perfazem a quantia a levantar.
Assume-se, por simplificação, que existem infinitas notas de cada tipo. Escreva um algoritmo que descreva o comportamento da função.
Algoritmo:
1) Verificar as pré-condições da quantia a levantar: quantia >=0, quantia <=200 e quantia é múltiplo de 5.
Se todas as pré-condições forem verdadeira continuar para 2), caso contrário enviar mensagem de erro e terminar. 2) Se:
2.1) quantia > 0
2.1.1) numNotas200 = quantia / 200 (divisão inteira)
2.1.2) quantia = quantia % 200 (resto da divisão inteira) 2.1.3) numNotas100 = quantia / 100 (divisão inteira)
2.1.4) quantia = quantia % 100 (resto da divisão inteira) 2.1.5) numNotas50 = quantia / 50 (divisão inteira)
2.1.6) quantia = quantia % 50 (resto da divisão inteira) 2.1.7) numNotas20 = quantia / 20 (divisão inteira)
2.1.8) quantia = quantia % 20 (resto da divisão inteira) 2.1.9) numNotas10 = quantia / 10 (divisão inteira)
2.1.10) quantia = quantia % 10 (resto da divisão inteira) 2.1.11) numNotas5 = quantia / 5 (divisão inteira)
2.2) Caso contrário:
2.2.1) numNotas200= numNotas100= numNotas50=numNotas20= numNotas10= numNotoas5=0 3) Devolver: numNotas200, numNotas100, numNotas50, numNotas20, numNotas10, numNotoas5