Baixe o app para aproveitar ainda mais
Prévia do material em texto
PCS - 3111 Lab. De Progr. OO 3a. Prova 25 de Novembro de 2015 NOME: _________GABARITO_________________ NUSP: ________________ Testes (valor: 4,8 pontos) . Prova Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 1 C D B B B C A D 2 E C A A C B B A 3 E B D E B C C A ERRATA EM ROXO Scanned by CamScanner A questão 1 era uma simples simulação de uma função recursiva (PCS3110), que na verdade não tem nada a ver com a matéria e sim com a outra. Era parecida com a questão 2-a da P3 de 2015 de PCS3110 mas em C++ e pedia somente o retorno do método. A questão 2 era a seguinte: Considere as seguintes afirmações: i. A coesão é uma métrica que pode ser classificada como Alta quando os membros estão fortemente relacionados e como Baixa quando os membros estão poucos relacionados entre si. ii. O acoplamento é uma métrica que pode ser classificada com Alta quando ocorrer alta interdependência entre as classes e Baixa quando ocorrer baixa interdependência entre as classes. iii. Como regra geral, deve-se sempre minimizar o acoplamento e maximizar a coesão. Assinale a alternativa correta. a) Somente I e II b) Todas as afirmações estão corretas c) Somente I e III d) Somente II e III e) Somente a III. Scanned by CamScanner Scanned by CamScanner Scanned by CamScanner Q1) [ 2.6 pontos] Pretende-se construir um módulo simulador de controle de iluminação de uma residência. Cada cômodo da residência tem o seu módulo de iluminação que pode estar aceso ou apagado, exceto os do tipo quarto que tem 3 estágios: aceso, meia luz ou apagado. Para isso, considere o simulador com os seguintes elementos de software: - Residência: Tem uma estrutura que permite integrar e controlar um máximo de 15 cômodos. Sobre as operações da classe: Construtor cria uma estrutura que abrigue os cômodos, em quantidade variável (dica: utilizar vector e iterator da STL – Standard Template Library). A operação adicionarComodo () recebe o endereço do cômodo (que pode ser quarto ou outro tipo de comodo) na memória e insere na referida estrutura iniciando a respectiva iluminação como apagada; A operação acenderTudo() comanda a iluminação de todos os cômodos da residência para o estágio aceso; A operação apagarMeiaLuz() comanda a iluminação para estágio apagado de todos os cômodos e, nos casos dos quartos, o estágio da luminosidade é levado para meia luz; A operação apagarTudo() faz com que todos os cômodos, inclusive os quartos tenham o estágio apagado de iluminação. A operação consultarIluminaçao() imprime um painel de iluminação da residência como uma lista de nomes de comodos e respectivos estágios de iluminação. Dica: um vetor ajuda a criar a estrutura de cômodos da residência; - Cômodo: Tem pelo menos um atributo para o nome do cômodo e um atributo de indica o nível de iluminação: 0 – apagado; 1 – aceso. Dica: getter e setters facilitam outras operações do simulador; - Quarto: é um tipo de cômodo com um comportamento especializado na iluminação. Apresenta os seguintes níveis de iluminação: 0 - aceso, 1 - apagado e 2 - meia luz. O método da operação apagar() tem uma particularidade: a cada comando apagar() ele muda o estágio da iluminação – do estágio aceso, apagar() muda o estágio da luminosidade para a meia luz. Do estágio meia luz, apagar() leva ao estágio apagado; - Outro tipo de Comodo (para os demais tipos de cômodos) tem os seguintes níveis de iluminações: apagado e aceso. O método da operação apagar() nesta classe sempre leva a iluminação para o estágio apagado; Pede-se: a) (2.0 pontos) Codificar as definições (.h) das classes Comodo, Quarto, OutroTipoComodo e Residencia. Definir a classe Comodo como abstrata e o método apagar()como abstrato. Escrever a implementação do método (.cpp) apagar() da classe Quarto. b) (0.6 pontos) Codificar um programa principal main() que cria uma residência com 4 cômodos: 1 quarto, 1 banheiro, sala, cozinha e corredor. O programa ainda realiza a seguinte sequência de comandos: i. Acender todos os comodos usando a operação acenderTudo(); ii. Apagar todos os comodos para meia luz, usando apagarMeiaLuz(); iii. Apagar todos os comodos para apagado, usando apagarTudo(); iv. Evidenciar os estágios de iluminação dos passos i), ii) e iii) usando consultarIluminacao(). Atenção: faz parte da avaliação a interpretação do texto para identificar e definir a codificação solicitada nos itens a) e b). (folha de respostas) a) (2.0 pontos) Codificar as definições (.h) das classes Comodo, Quarto, OutroTipoComodo e Residencia. Definir a classe Comodo como abstrata e o método apagar()como abstrato. Escrever a implementação do método (.cpp) apagar() da classe Quarto. (folha de resposta) b) (0.6 pontos) Codificar um programa principal main() que cria uma residência com 4 cômodos: 1 quarto, 1 banheiro, sala, cozinha e corredor. O programa ainda realiza a seguinte sequência de comandos: v. Acender todos os comodos usando a operação acenderTudo(); vi. Apagar todos os comodos para meia luz, usando apagarMeiaLuz(); vii. Apagar todos os comodos para apagado, usando apagarTudo(); viii. Evidenciar os estágios de iluminação dos passos i), ii) e iii) usando consultarIluminacao(). #include <iostream> using namespace std; #define QTDEMAXCOMODOS 15 class Comodo { protected: string nome; int iluminacao; public: Comodo( string nome ); ~Comodo(); string getNome(); int getIluminacao(); int acender(); virtual int apagar()=0; }; class Quarto:public Comodo { public: Quarto(string nome); ~Quarto(); int apagar(); }; class OutroTipoComodo:public Comodo { public: OutroTipoComodo(string nome); ~OutroTipoComodo(); int apagar(); }; class Residencia { protected: string Nome; int QtdeComodos; Comodo *Comodos[QTDEMAXCOMODOS]; public: Residencia(string nome); ~Residencia(); int adicionarComodo (Comodo *EnderecoComodo); void acenderTudo(); void apagarTudo(); void apagarMeiaLuz(); void consultarIluminacao(); }; Comodo::Comodo(string nome) { this->nome = nome; this->iluminacao = 0; // apagado } Comodo::~Comodo() { } int Comodo::getIluminacao(){ return this->iluminacao; } string Comodo::getNome(){ return this->nome; } int Comodo::acender(){ this->iluminacao = 1; return (this->iluminacao); } /* int Comodo::apagar(){ this->iluminacao = 0; return (this->iluminacao); } */ Quarto::Quarto(string nome):Comodo(nome) { //ctor } Quarto::~Quarto() { //dtor } int Quarto::apagar (){ if (iluminacao == 1){ iluminacao = 2; } else { iluminacao = 0; } //cout<< "***Apagar especializado Quarto " << iluminacao << endl; return iluminacao; }; OutroTipoComodo::OutroTipoComodo(string nome):Comodo(nome){ }; OutroTipoComodo::~OutroTipoComodo(){ }; int OutroTipoComodo::apagar(){ //cout<< "***Apagar especializado OutroTipoComodo: " << iluminacao << endl; iluminacao = 0; return iluminacao; } Residencia::Residencia(string nome){ QtdeComodos = 0; nome = nome; }; Residencia::~Residencia(){ delete[] Comodos; }; int Residencia::adicionarComodo(Comodo *EnderecoComodo){ Comodos[QtdeComodos]= EnderecoComodo; QtdeComodos ++; return (QtdeComodos); } void Residencia::acenderTudo(){ int i = 0; for (i=0; i < QtdeComodos; i++){ this->Comodos[i]->acender(); } } void Residencia::apagarTudo(){ int i = 0; for (i=0; i < QtdeComodos; i++){ this->Comodos[i]->apagar(); this->Comodos[i]->apagar(); } } void Residencia::apagarMeiaLuz(){ int i = 0; for (i=0; i < QtdeComodos; i++){ this->Comodos[i]->apagar(); } } void Residencia::consultarIluminacao(){ int i; for (i = 0; i < QtdeComodos; i++){ cout << Comodos[i]->getNome() << " Iluminacao = " << Comodos[i]- >getIluminacao() << endl; } cout << endl << endl; } int main() { Residencia *R = new Residencia ("Reg"); Quarto *Q; OutroTipoComodo *OTC; Q = new Quarto ("Quarto 1"); R->adicionarComodo(Q); Q = new Quarto ("Quarto 2"); R->adicionarComodo(Q); // Q = new Quarto ("Quarto 3"); R->adicionarComodo(Q); // Q = new Quarto ("Quarto 4"); R->adicionarComodo(Q); OTC = new OutroTipoComodo ("Banheiro 1"); R->adicionarComodo(OTC); OTC = new OutroTipoComodo ("Banheiro 2"); R->adicionarComodo(OTC); // OTC = new OutroTipoComodo ("Sala de jantar"); R->adicionarComodo(OTC); OTC = new OutroTipoComodo ("Sala"); R->adicionarComodo(OTC); OTC = new OutroTipoComodo ("Cozinha"); R->adicionarComodo(OTC); OTC = new OutroTipoComodo ("Corredor"); R->adicionarComodo(OTC); R->acenderTudo(); R->consultarIluminacao(); R->apagarMeiaLuz(); R->consultarIluminacao(); R->apagarTudo(); R->consultarIluminacao(); return 0; } NOME: ____Gabarito________________________________________ NUSP: ________________ Questão 2. Valor 2,6 pontos Nesta questão, vamos explorar de forma simplificada os conceitos de localização e internacionalização de software. Localização (ou L10N, sigla adotada para localization) é o processo de versão das mensagens de um software para uma outra língua de modo a torná-lo linguística e culturalmente apropriado para um determinado mercado (Esselink, 1998). Internacionalização (analogamente, I18N para internationalization) refere-se ao suporte de um software a múltiplas línguas. L10N implica em haver versões para várias línguas de todas as mensagens do software ao usuário. Em alguns casos, podem até ser necessárias modificações na aparência da tela para compatibilizar às preferências de cada cultura. I18N implica em que o código seja preparado para não emitir mensagens diretamente ao usuário, mas para fazê-lo por meio de da indexação de Catálogos de Mensagens (Message Catalog). Um Catálogo de Mensagens é um arquivo texto que contém todas as mensagens do software numa determinada língua. Locale é o termo usado para definir aspectos culturais de língua, moeda e representação numérica. Nesta questão, deseja-se realizar a I18N de uma classe responsável pela emissão das mensagens de erro ao usuário em operações de entrada e saída de arquivos. As mensagens relacionadas à manipulação de arquivos estão traduzidas em quatro línguas: inglês, português, espanhol e alemão. Há quatro catálogos de mensagens, que são arquivos texto, de extensão .txt, localizados no mesmo diretório do programa, com nomes que identificam a língua e o país. Cada um deles contém as mensagens de erro em uma dada língua; cada linha corresponde a uma mensagem. A ordem das mensagens é a mesma em todos os arquivos do catálogo, correspondendo aos erros de arquivo inexistente (NO_SUCH_FILE, primeira linha); fim de arquivo (END_OF_FILE, segunda linha), erro de leitura de valor (WRONG_VALUE, terceira linha), falha do dispositivo (DEVICE_FAILED, quarta linha), conforme esquematizado na figura a seguir. Arquivos Catálogos de Mensagens e seu conteúdo. Seja o programa estudado na Aula 10, que lê inteiros de um arquivo para calcular a média, e depois escreve esta média em um outro arquivo. Este código é o que se apresenta a seguir. 1 #include <iostream> 2 #include <fstream> 3 4 using namespace std; 5 6 int main() 7 { 8 double avg; 9 // leitura de arquivo 10 ifstream inFile; 11 12 inFile.open("avg.txt"); 13 14 if (inFile.fail()) No such file End of file Wrong value en_US.txt No such file End of file Wrong value Device failed No such file End of file Wrong value pt_BR.txt Arquivo não existe Fim de arquivo Valor errado Falha no dispositivo No such file End of file Wrong value es_ES.txt El archivo no existe Fin de archivo Valor incorrecto Falla en el dispositivo No such file End of file Wrong value de_DE.txt Kein Document gefunden! Dateiende Falschen Wert Geräteausfsall NOME: ____Gabarito________________________________________ NUSP: ________________ 15 cerr << "Arquivo nao encontrado" << endl; 16 else 17 { 18 double total = 0; 19 int n = 0; 20 while (inFile) // enquanto ultimo dado lido eh valido 21 { 22 double x; 23 inFile >> x; 24 if (inFile) // testa se ultimo dado lido eh valido 25 { 26 total += x; 27 n++; 28 } 29 } 30 if (n > 0) 31 { 32 avg = total / n; 33 cout << "media: " << avg << "\n"; 34 } 35 inFile.close(); 36 } 37 // escrita de arquivo 38 ofstream onFile; 39 onFile.open("avg2.txt"); 40 if (onFile.fail()) 41 cerr << "Arquivo 2 nao encontrado" << endl; 42 else 43 { 44 onFile << avg; 45 onFile.close(); 46 } 47 return 0; 48 } Seja ainda a classe ErroArquivo, como se segue, definida mas apenas parcialmente implementada: ErroArquivo.h 1 #ifndef ERROARQUIVO_H 2 #define ERROARQUIVO_H 3 4 #include <iostream> 5 #include <cstring> 6 #include <string> 7 8 using namespace std; 9 10 class ErroArquivo 11 { 12 public: 13 ErroArquivo(int tipoDoErro); 14 virtual ~ErroArquivo(); 15 16 int getIdLocale (); //obtém locale 17 void escreveMensagem( ); // escreve msg de 18 // erro 19 //constantes para Catalogos de Mensagens 20 static const int enUS=0; 21 static const int ptBR=1; 22 static const int esES=2; 23 static const int deDE=3; 24 25 26 //constantes para as mensagens de erro 27 static const int NO_SUCH_FILE = 0; 28 static const int END_OF_FILE = 1; 29 static const int WRONG_VALUE = 2; 30 static const int DEVICE_FAILED = 3; 31 32 private: 33 int erroOcorrido; 34 }; 35 36 #endif // ERROARQUIVO_H ErroArquivo.cpp 1 #include <iostream> 2 #include <fstream> 3 #include "ErroArquivo.h" 4 5 using namespace std; 6 7 ErroArquivo::ErroArquivo(int tipoDoErro) 8 { 9 this->erroOcorrido = tipoDoErro; 10 } 11 12 13 ErroArquivo::~ErroArquivo() 14 { 15 } 16 17 int ErroArquivo::getIdLocale() 18 { 19 return enUS; //default en_US 20 } 21 22 void ErroArquivo::escreveMensagem()23 { 24 char *nomesCatalogosMensagem[4] = {"en_US.txt","pt_BR.txt","es_ES.txt","de_DE.txt"}; 25 26 // abre o catalogo adequado 27 28 // seleciona a mensagem adequada 29 30 // emite a mensagem de erro 31 // na lingua escolhida 32 33 34 } NOME: ____Gabarito________________________________________ NUSP: ________________ Nas perguntas a e b, indique claramente o local em que você pretende realizar mudanças no código dado. Sugerimos que você use os seguintes comandos: Inserir em XXX, onde XXX é o número da linha acima da qual você deseja inserir seu código; Remover XXX ou Remover XXX-YYY onde XXX é a linha que você pretende excluir (ou o início do bloco, inclusive a própria XXX) e YYY é o fim do bloco (inclusive a própria YYY). Alterar XXX ou Alterar XXX-YYY, para substituir todo o código no intervalo. Por exemplo: Inserir em 1: #include “definicoes.h” #include “outrasdefinicoes.h” a) Valor: 1,5 pontos Modifique o main apresentado, substituindo o tratamento de erros que está sendo feito no código dado por exceções relacionadas a erros na manipulação dos arquivos, usando a classe ErroArquivo dada. Inserir em 3: #include "ErroArquivo.h" Erro na abertura do arquivo avg.txt Modificar de 11 a 15: try { inFile.open("avg.txt"); if (inFile.fail()) throw new ErroArquivo(ErroArquivo::NO_SUCH_FILE); } catch (ErroArquivo* e) { e->escreveMensagem(); } Erro na leitura do arquivo avg.txt: as condições de END_OF_FILE e WRONG_VALUE são tratadas na lógica do programa – nenhuma modificação é necessária mas aceita-se o teste mais específico com eof() e fail(). Mas o erro DEVICE_ERROR precisa jogar uma exceção e terminar o programa. Linha 23, inserir: try { inFile >> x; if (inFile.badbit()) throw new ErroArquivo(ErroArquivo::DEVICE_ERROR); } catch (ErroArquivo* e) { e->escreveMensagem(); } NOME: ____Gabarito________________________________________ NUSP: ________________ Erro no fechamento do arquivo (DEVICE_ERROR) Linha 35, inserir: try { inFile.close(); if (inFile.badbit()) throw new ErroArquivo(ErroArquivo::DEVICE_ERROR); } catch (ErroArquivo* e) { e->escreveMensagem(); return 1; } Erro na abertura do arquivo avg2.txt Modificar de 39 a 41: try { onFile.open("avg2.txt"); if (onFile.fail()) throw new ErroArquivo(ErroArquivo::NO_SUCH_FILE); } catch (ErroArquivo* e) { e->escreveMensagem(); return 1; } Linhas 44 e 45 têm duas operações de manipulação: leitura e fechamento. O tratamento de erro tem que ser feito para cada uma delas, individualmente! try { onFile << avg; if (onFile.badbit()) throw new ErroArquivo(ErroArquivo::DEVICE_ERROR); } catch (ErroArquivo* e) { e->escreveMensagem(); return 1; } try { onFile.close("avg2.txt"); if (onFile.fail()) throw new ErroArquivo(ErroArquivo:: DEVICE_ERROR); } catch (ErroArquivo* e) { e->escreveMensagem(); NOME: ____Gabarito________________________________________ NUSP: ________________ return 1; } Solução alternativa, sem o bloco try-throw-catch Inserir em 3: #include "ErroArquivo.h" Alterar em 15: ErroArquivo *e = new ErroArquivo(ErroArquivo::NOSUCHFILE); e->escreveMensagem(); return 1; Inserir em 24: if (!inFile.eof() && inFile.fail()) { ErroArquivo *e = new ErroArquivo(ErroArquivo::WRONGVALUE); e->escreveMensagem(); return 1; } else if (inFile.bad()) { ErroArquivo *e = new ErroArquivo(ErroArquivo::DEVICEFAILED); e->escreveMensagem(); return 1; } Alterar em 24: else if (inFile) Alterar em 41 ErroArquivo *e = new ErroArquivo(ErroArquivo::NOSUCHFILE); e->escreveMensagem(); return 1; Inserir em 45: if (!onFile) { ErroArquivo *e = new ErroArquivo(ErroArquivo::DEVICEFAILED); e->escreveMensagem(); return 1; } NOME: ____Gabarito________________________________________ NUSP: ________________ b) Valor: 1,0 ponto Faça a I18N do método escreveMensagem, para que ele emita a mensagem de erro devidamente localizada, isto é, na língua definida por getIdLocale(), no dispositivo padrão de mensagens de erro. void ErroArquivo::escreveMensagem() { char *nomesCatalogosMensagem[4] = {"en_US.txt","pt_BR.txt","es_ES.txt","de_DE.txt"}; // abre o catalogo adequado ifstream catalogoMensagem; int idLocale = getIdLocale(); catalogoMensagem.open(nomesCatalogosMensagem[idLocale]); // seleciona a mensagem adequada string mensagem; for (int i=0; i<=erroOcorrido; i++) { getline(catalogoMensagem,mensagem); } // emite a mensagem de erro na lingua escolhida cerr << mensagem << endl; } c) Valor: 0,1 ponto Como você acha que deveria ser implementado o método getIdLocale() para pegar a localização do usuário? A resposta pode ser dissertativa – não é necessário escrever código! A escolha de língua é do usuário da aplicação e em geral é feita para todas as aplicações que vão ser executadas numa determinada máquina. O locale é portanto, uma variável cujo contexto deve ser superior ao das aplicações – é uma variável do sistema operacional. A aplicação deve obter esta informação de alguma biblioteca ou API do sistema operacional, que tenha acesso a esta variável.
Compartilhar