Programação Orientada para Objectos
IGE e ETI
2º semestre de 1999/2000
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.
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>using namespace std;
class A {public:A(int a, int b = 0): a(a + b) {}int h() const { return a; }
protected:int a;};
class B : public A {public:B(int a) : A(2*a) { ba = new A(a); }virtual int h() const { return 2*a; }virtual ~B() {f();delete ba;}int g();
private:A* ba;void f() const {cout << ba->h() << endl;}};
int main(){...}
V
A a(7, 0);
O construtor da classe
A
aceita dois argumentos do tipo inteiros.
F A*
a = new a(3);
A seguir ao operadorFnewdeve aparecer o nome de um tipo.anão é nome de nenhum tipo.
B*
b = new B();
Ao construtor da classe
B
deve ser sempre passado um argumento inteiro.
[1,5 valores]
main()
qual o resultado produzido pelo programa (apenas uma das respostas está correcta)? Atenção aos procedimentos virtuais!B* b = new B(1);A* a = b;cout << " " << b->h() << " " << a->h() << " ";delete b;
V
4 2 1
F
4 4 1
F
4 2 2
Na primeira instrução é construída uma variável dinâmica da classe[0,5 valores]Be o seu endereço é colocado no ponteirob, do tipoB*. Em seguida o mesmo endereço é colocado no ponteiroa, do tipoA*. A construção da variável dinâmica é feita invocando o construtor da classeBcom o argumento 1. Esse construtor invoca o construtor da classe baseAcom argumento 2, que inicializa a variável membroA::acom o valor 2. Depois o construtor de B constrói um variável dinâmica do tipo A e coloca o seu endereço na variável membroB::ba. A construção dessa variável dinâmica é feita invocando o construtor deAcom argumento 1. Logo, essa variável dinâmica ficará com a sua variável membroA::acom valor 1.
A instrução seguinte invoca funçõesh()escrevendo o valor devolvido no ecrã. Como a funçãoA::h()não é virtual, a sua chamada através de ponteiros está sujeita a ligação estática, pelo que a primeira invocação (através de um ponteiro paraB) será deB::h()e a segunda (através de um ponteiro paraA) será deA::h().
Assim, no ecrã surge primeiro 4 e depois 2.
Finalmente é destruída a variável dinâmica. A invocação do seu destrutor leva à execução do procedimentoB::h(), que por sua vez escreve no ecrã o resultado da chamada deA::h()(por causa da ligação estática), o que faz surgir 1 no ecrã.
F
A a(5); a.a = 3;
A instrução errada éFa.a = 3;porquea, membro da classeA, tem como categoria de acessoprotected, logo não pode ser acedido dentro da funçãomain(ver Aula Prática 8).
B*
b(1); cout << b->h();
A instrução errada é[1 valor]B* b(1), pois para criar a variável dinâmica para quebdeveria apontar deveria ter sido usado o operadornew. A instrução está a tentar atribuir 1 (inteiro) a um ponteiro.
int B::g() (membro da classe
B).
Quais delas estão correctas?
V
A* p = ba;
Vbaé do tipo ponteiro paraA.
int&
r = a;
Vaé um inteiro e, como a sua categoria de acesso éprotected, pode ser acedido nas funções e procedimentos membro da classeB(derivada deA). Logo está correcta a inicialização de uma referência para umintatravés de uma variávelint.
int*
pi = &a;
Tendo definidoVpicomo um ponteiro parainte sendo a categoria de acesso deaprotected,pipode guardar o endereço dea.
A**
pp = &ba;
[2 valores]baé do tipo ponteiro paraA, logo definindoppcomo um ponteiro para um ponteiro paraA, este pode guardar o endereço de um ponteiro paraA.
Pretende-se para isso desenvolver uma hierarquia de classes que represente os vários tipos de textos disponíveis: textos literários, científicos e jornalísticos.
No topo da hierarquia está a classe abstracta
TextoEmProsa:
Assuma que o construtorclass TextoEmProsa {public:TextoEmProsa(std::string const& título, std::string const& autor,int const número_de_palavras, int const número_de_frases,int const número_de_parágrafos): título_(título), autor_(autor),número_de_palavras(número_de_palavras),número_de_frases(número_de_frases),número_de_parágrafos(número_de_parágrafos) {}TextoEmProsa(std::istream& entrada);virtual ~TextoEmProsa() {}
//Devolve o tipo do texto (literário, científico ou jornalístico):virtual string tipo() const = 0;
//Facilidade de leitura do texto:virtual double legibilidade() const {return double(número_de_palavras)/número_de_frases;}
//Funções de inspecção:std::string const& título() const {return título_;}std::string const& autor() const {return autor_;}int númeroDePalavras() const {return número_de_palavras;}int númeroDeFrases() const {return número_de_frases;}int númeroDeParágrafos() const {return número_de_parágrafos;}//Mostra no ecrã o que é comum a todos osTextoEmProsa:virtual void mostra() const;
//Carrega do canalentradao que é comum a todos osTextoEmProsa:virtual void carrega(std::istream& entrada);
//Guarda no canalsaidao que é comum a todos osTextoEmProsa:virtual void guarda(std::ostream& saida) const;
private:std::string título_;std::string autor_;int número_de_palavras;int número_de_frases;int número_de_parágrafos;};
TextoEmProsa(std:::istream&
entrada) e os procedimentos mostra(), carrega()
e guarda() estão já definidos algures.
TextoCientífico
que é um texto em prosa e contém a seguinte informação:
"TextoCientífico".
O índice de legibilidade de um texto científico é dado pelo número médio de equações por parágrafo.
Defina todos os procedimentos e funções
da classe TextoCientífico, excepto o construtor que recebe
um canal de entrada (istream).
Defina também as classes TextoLiterário
e TextoJornalístico, mas não especifique os seus
membros, ou seja, não inclua nada entre {}. Explicite
apenas se derivam de alguma outra classe. I.e., use o formato:
[1,5 valores]class B /*aqui deve especificar as heranças, se existirem.*/ {//Aqui não ponha nada!};
Faz-se uma definição completa. A resposta necessária é indicada a negrito.
std::string leLinha(std::istream& entrada) {std::string linha;int c;while(entrada.get(c) && c != '\n')linha += c;return linha;}
class Data {public:Data(int const dia = 1, int const mes = 1, int const ano = 1900): dia_(dia), mes_(mes), ano_(ano) {}
int dia() const {return dia_;}int mes() const {return mes_;}int ano() const {return ano_;}
void carrega(std::istream& entrada);void guarda(std::ostream& saida) const;
private:int dia_, mes_, ano_;};
ostream& operator <<(ostream& saida, Data const& data);
class TextoEmProsa {public:TextoEmProsa(std::string const& titulo, std::string const& autor,int const numero_de_palavras, int const numero_de_frases,int const numero_de_paragrafos): titulo_(titulo), autor_(autor),numero_de_palavras(numero_de_palavras),numero_de_frases(numero_de_frases),numero_de_paragrafos(numero_de_paragrafos) {}TextoEmProsa(std::istream& entrada);virtual ~TextoEmProsa() {}
//Devolve o tipo do texto (literário, científico ou jornalístico):virtual string tipo() const = 0;
//Facilidade de leitura do texto:virtual double legibilidade() const {return double(numero_de_palavras)/numero_de_frases;}
//Funções de inspecção:std::string const& titulo() const {return titulo_;}std::string const& autor() const {return autor_;}int numeroDePalavras() const {return numero_de_palavras;}int numeroDeFrases() const {return numero_de_frases;}int numeroDeParagrafos() const {return numero_de_paragrafos;}//Mostra no ecrã o que é comum a todos osTextoEmProsa:virtual void mostra() const;
//Carrega do canal entrada o que é comum a todos osTextoEmProsa:virtual void carrega(std::istream& entrada);
//Guarda no canal saida o que é comum a todos osTextoEmProsa:virtual void guarda(std::ostream& saida) const;
private:std::string titulo_;std::string autor_;int numero_de_palavras;int numero_de_frases;int numero_de_paragrafos;};
TextoEmProsa::TextoEmProsa(std::istream& entrada) {carrega(entrada);}
void TextoEmProsa::mostra() const {cout << "Título: " << titulo_ << endl;cout << "Autor: " << autor_ << endl;cout << "Número de palavras: " << numero_de_palavras << endl;cout << "Número de frases: " << numero_de_frases << endl;cout << "Número de parágrafos: " << numero_de_paragrafos << endl;}
void TextoEmProsa::carrega(std::istream& entrada) {titulo_ = leLinha(entrada);autor_ = leLinha(entrada);entrada >> numero_de_palavras;entrada >> numero_de_frases;entrada >> numero_de_paragrafos;leLinha(entrada); //limpa a última linha em leitura.}
void TextoEmProsa::guarda(std::ostream& saida) const {saida << titulo_ << endl;saida << autor_ << endl;saida << numero_de_palavras << endl;saida << numero_de_frases << endl;saida << numero_de_paragrafos << endl;}
class TextoCientifico : public TextoEmProsa {public:TextoCientifico(std::string const& titulo, std::string const& autor,int const numero_de_palavras,int const numero_de_frases,int const numero_de_paragrafos,std::string const& area_cientifica,int const numero_de_equacoes,std::string const& titulo_da_publicacao): TextoEmProsa(titulo, autor, numero_de_palavras,numero_de_frases, numero_de_paragrafos),area_cientifica(area_cientifica),numero_de_equacoes(numero_de_equacoes),titulo_da_publicacao(titulo_da_publicacao) {}TextoCientifico(std::istream& entrada);
virtual string tipo() const {return "TextoCientífico";}
virtual double legibilidade() const {return double(numero_de_equacoes) / numeroDeParagrafos();}
string areaCientifica() const {return area_cientifica;}int numeroDeEquacoes() const {return numero_de_equacoes;}string tituloDaPublicacao() const {return titulo_da_publicacao;}virtual void mostra() const;
void areaCientifica(string const& nova_area) {area_cientifica = nova_area;}
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:string area_cientifica;int numero_de_equacoes;string titulo_da_publicacao;
void carregaPrivado(std::istream& entrada);};
TextoCientifico::TextoCientifico(std::istream& entrada): TextoEmProsa(entrada) {carregaPrivado(entrada);}
void TextoCientifico::mostra() const {cout << "Tipo de texto: " << tipo() << endl;TextoEmProsa::mostra();cout << "Área Científica: " << areaCientifica() << endl;cout << "Número de equações: " << numeroDeEquacoes() << endl;cout << "Título da publicação: " << tituloDaPublicacao() << endl;}
void TextoCientifico::carrega(std::istream& entrada) {TextoEmProsa::carrega(entrada);carregaPrivado(entrada);}
void TextoCientifico::guarda(std::ostream& saida) const {TextoEmProsa::guarda(saida);saida << area_cientifica;saida << numero_de_equacoes;saida << titulo_da_publicacao;}
void TextoCientifico::carregaPrivado(std::istream& entrada) {area_cientifica = leLinha(entrada);// entrada >> area_cientificaentrada >> numero_de_equacoes;titulo_da_publicacao = leLinha(entrada);}
class TextoLiterario : public TextoEmProsa {public:TextoLiterario(std::string const& titulo, std::string const& autor,int const numero_de_palavras, int const numero_de_frases,int const numero_de_paragrafos,std::string const& critica): TextoEmProsa(titulo, autor, numero_de_palavras,numero_de_frases, numero_de_paragrafos), critica_(critica) {}TextoLiterario(std::istream& entrada);
virtual string tipo() const {return "TextoLiterario";}
string critica() const {return critica_;}
void critica(std::string const& nova_critica) {critica_ = nova_critica;}
virtual void mostra() const;
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:string critica_;};
TextoLiterario::TextoLiterario(std::istream& entrada): TextoEmProsa(entrada) {critica_ = leLinha(entrada);}
void TextoLiterario::mostra() const {cout << "Tipo de texto: " << tipo() << endl;TextoEmProsa::mostra();cout << "Crítica: " << critica() << endl;}
void TextoLiterario::carrega(std::istream& entrada) {TextoEmProsa::carrega(entrada);critica_ = leLinha(entrada);}
void TextoLiterario::guarda(std::ostream& saida) const {saida << tipo() << endl;TextoEmProsa::guarda(saida);saida << critica_;}
class TextoJornalistico : public TextoEmProsa {public:TextoJornalistico(std::string const& titulo, std::string const& autor,int const numero_de_palavras,int const numero_de_frases,int const numero_de_paragrafos,std::string const& jornal,Data const& data): TextoEmProsa(titulo, autor, numero_de_palavras,numero_de_frases, numero_de_paragrafos),jornal_(jornal), data_(data) {}TextoJornalistico(std::istream& entrada);
virtual string tipo() const {return "TextoJornalistico";}
string jornal() const {return jornal_;}Data data() const {return data_;}
virtual void mostra() const;
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:string jornal_;Data data_;};
TextoJornalistico::TextoJornalistico(std::istream& entrada): TextoEmProsa(entrada) {jornal_ = leLinha(entrada);data_.carrega(entrada);}
void TextoJornalistico::mostra() const {cout << "Tipo de texto: " << tipo() << endl;TextoEmProsa::mostra();cout << "Jornal: " << jornal() << endl;cout << "Data: " << data() << endl;}
void TextoJornalistico::carrega(std::istream& entrada) {TextoEmProsa::carrega(entrada);jornal_ = leLinha(entrada);data_.carrega(entrada);}
void TextoJornalistico::guarda(std::ostream& saida) const {saida << tipo() << endl;TextoEmProsa::guarda(saida);saida << jornal_;data_.guarda(saida);}
Assim, deve ser introduzida uma nova classe abstracta
Texto
que representa qualquer tipo de texto. Deve ser ainda criada uma
nova classe concreta que represente os novos textos em verso, sabendo
que tanto os textos em verso, como os textos em prosa são textos.
Os textos em verso contêm o título, o autor,
o número de palavras e o número de estrofes, e dispõem
das respectivas funções de inspecção.
O índice de legibilidade de um texto poético é 0 e
o tipo é "TextoEmVerso".
Reestruture a hierarquia de classes de modo a acomodar estas alterações. Defina todas as classes, mas não defina nenhum dos métodos.
Tal como na alínea anterior, não especifique
os membros das classes TextoLiterário e TextoJornalístico.
[2 valores]
ColecçãoDeTextos que
contém uma lista de ponteiros para os textos que o compõem.
Esta classe deve dispor de funções e procedimentos que realizem
as operações permitidas às colecções
de texto (referidas acima). Deve ainda existir um destrutor, que será
responsável pela destruição das instâncias de
classes concretas derivadas da classe Texto para as quais o itens
da lista apontam.
Para definir a lista pode usar qualquer das possibilidades
referidas durante as aulas: list<Texto*>, ListaPonteiroTexto
ou Lista<Texto*>.
Não é necessário implementar nenhum dos métodos nesta alínea.
[1 valor]
ColecçãoDeTextos.
[1 valor]
ColecçãoDeTextos
que remove um texto da colecção, dado o seu título.
Não deve abortar o programa em nenhuma circunstância.
No caso de não existir nenhum texto com o título dado o procedimento
não faz nada.
[1,5 valores]
ColecçãoDeTextos
que calcula o índice médio de legibilidade da colecção.
[1 valor]
ColecçãoDeTextos
que lê textos a partir de um canal. Admita que os textos lidos
têm todos títulos diferentes.
Os dados lidos do canal têm o seguinte formato:
[1,5 valores]número_de_textostipo_do_primeiro_texto
...informação do primeiro textotipo_do_segundo_texto
...informação do segundo texto
...tipo_do_último_texto
...informação do último texto
ColecçãoDeTextos
que guarda uma colecção num canal (no formato da alínea
anterior).
[1 valor]
Faz-se uma definição completa (mas não são tratados erros de leitura...). A resposta necessária é indicada a negrito.
std::string leLinha(std::istream& entrada) {std::string linha;int c;while(entrada.get(c) && c != '\n')linha += c;return linha;}
class Data {public:Data(int const dia = 1, int const mes = 1, int const ano = 1900): dia_(dia), mes_(mes), ano_(ano) {}
int dia() const {return dia_;}int mes() const {return mes_;}int ano() const {return ano_;}
void carrega(std::istream& entrada);void guarda(std::ostream& saida) const;
private:int dia_, mes_, ano_;};
ostream& operator <<(ostream& saida, Data const& data);
class Texto {public:Texto(std::string const& titulo, std::string const& autor,int const numero_de_palavras): titulo_(titulo), autor_(autor),numero_de_palavras(numero_de_palavras) {}Texto(std::istream& entrada);virtual ~Texto() {}
//Cria um clone:virtual Texto* clona() const = 0;
virtual std::string tipo() const = 0;virtual double legibilidade() const = 0;
std::string const& titulo() const {return titulo_;}std::string const& autor() const {return autor_;}int numeroDePalavras() const {return numero_de_palavras;}
virtual void mostra() const;
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:std::string titulo_;std::string autor_;int numero_de_palavras;};
Texto::Texto(std::istream& entrada) {carrega(entrada);}
void Texto::mostra() const {cout << "Título: " << titulo_ << endl;cout << "Autor: " << autor_ << endl;cout << "Número de palavras: " << numero_de_palavras << endl;}
void Texto::carrega(std::istream& entrada) {titulo_ = leLinha(entrada);autor_ = leLinha(entrada);entrada >> numero_de_palavras;leLinha(entrada); // limpa a última linha em leitura}
void Texto::guarda(std::ostream& saida) const {saida << titulo_ << endl;saida << autor_ << endl;saida << numero_de_palavras << endl;}
class TextoEmProsa : public Texto {public:TextoEmProsa(std::string const& titulo, std::string const& autor,int const numero_de_palavras, int const numero_de_frases,int const numero_de_paragrafos): Texto(titulo, autor, numero_de_palavras),numero_de_frases(numero_de_frases),numero_de_paragrafos(numero_de_paragrafos) {}TextoEmProsa(std::istream& entrada);
//Cria um clone:virtual TextoEmProsa* clona() const {return new TextoEmProsa(*this);}
virtual string tipo() const = 0;
virtual double legibilidade() const {return double(numeroDePalavras())/numero_de_frases;}
int numeroDeFrases() const {return numero_de_frases;}int numeroDeParagrafos() const {return numero_de_paragrafos;}virtual void mostra() const;
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:int numero_de_frases;int numero_de_paragrafos;
void carregaPrivado(std::istream& entrada);};
TextoEmProsa::TextoEmProsa(std::istream& entrada): Texto(entrada) {carregaPrivado(entrada);}
void TextoEmProsa::mostra() const {Texto::mostra();cout << "Número de frases: " << numero_de_frases << endl;cout << "Número de parágrafos: " << numero_de_paragrafos << endl;}
void TextoEmProsa::carrega(std::istream& entrada) {Texto::carrega(entrada);carregaPrivado(entrada);}
void TextoEmProsa::guarda(std::ostream& saida) const {Texto::guarda(saida);saida << numero_de_frases << endl;saida << numero_de_paragrafos << endl;}
void TextoEmProsa::carregaPrivado(std::istream& entrada) {entrada >> numero_de_frases;entrada >> numero_de_paragrafos;leLinha(entrada); //limpa a última linha em leitura.}
class TextoEmVerso : public Texto {public:TextoEmVerso(std::string const& titulo,std::string const& autor,int const numero_de_palavras,int const numero_de_estrofes): Texto(titulo, autor, numero_de_palavras),numero_de_estrofes(numero_de_estrofes) {}TextoEmVerso(std::istream& entrada);
//Cria um clone:virtual TextoEmVerso* clona() const {return new TextoEmVerso(*this);}
virtual string tipo() const {return "TextoEmVerso";}
virtual double legibilidade() const {return 0.0;}virtual void mostra() const;
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:int numero_de_estrofes;};
TextoEmVerso::TextoEmVerso(std::istream& entrada): Texto(entrada) {entrada >> numero_de_estrofes;leLinha(entrada);}
void TextoEmVerso::mostra() const {cout << "Tipo de texto: " << tipo() << endl;Texto::mostra();cout << "Número de estrofes: " << numero_de_estrofes << endl;}
void TextoEmVerso::carrega(std::istream& entrada) {Texto::carrega(entrada);entrada >> numero_de_estrofes;leLinha(entrada);}
void TextoEmVerso::guarda(std::ostream& saida) const {Texto::guarda(saida);saida << numero_de_estrofes << endl;}
class TextoCientifico : public TextoEmProsa {public:TextoCientifico(std::string const& titulo,std::string const& autor,int const numero_de_palavras,int const numero_de_frases,int const numero_de_paragrafos,std::string const& area_cientifica,int const numero_de_equacoes,std::string const& titulo_da_publicacao): TextoEmProsa(titulo, autor, numero_de_palavras,numero_de_frases, numero_de_paragrafos),area_cientifica(area_cientifica),numero_de_equacoes(numero_de_equacoes),titulo_da_publicacao(titulo_da_publicacao) {}TextoCientifico(std::istream& entrada);
//Cria um clone:virtual TextoCientífico* clona() const {return new TextoCientifico(*this);}
virtual string tipo() const {return "TextoCientífico";}
virtual double legibilidade() const {return double(numero_de_equacoes)/numeroDeParagrafos();}
string areaCientifica() const {return area_cientifica;}int numeroDeEquacoes() const {return numero_de_equacoes;}string tituloDaPublicacao() const {return titulo_da_publicacao;}
void areaCientifica(std::string const& nova_area) {area_cientifica = nova_area;}
virtual void mostra() const;
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:string area_cientifica;int numero_de_equacoes;string titulo_da_publicacao;
void carregaPrivado(std::istream& entrada);};
TextoCientifico::TextoCientifico(std::istream& entrada): TextoEmProsa(entrada) {carregaPrivado(entrada);}
void TextoCientifico::mostra() const {cout << "Tipo de texto: " << tipo() << endl;TextoEmProsa::mostra();cout << "Área Científica: " << areaCientifica() << endl;cout << "Número de equações: " << numeroDeEquacoes() << endl;cout << "Título da publicação: " << tituloDaPublicacao() << endl;}
void TextoCientifico::carrega(std::istream& entrada) {TextoEmProsa::carrega(entrada);carregaPrivado(entrada);}
void TextoCientifico::guarda(std::ostream& saida) const {saida << tipo() << endl;TextoEmProsa::guarda(saida);saida << area_cientifica;saida << numero_de_equacoes;saida << titulo_da_publicacao;}
void TextoCientifico::carregaPrivado(std::istream& entrada) {area_cientifica = leLinha(entrada);entrada >> numero_de_equacoes;titulo_da_publicacao = leLinha(entrada);}
class TextoLiterario : public TextoEmProsa {public:TextoLiterario(std::string const& titulo, std::string const& autor,int const numero_de_palavras, int const numero_de_frases,int const numero_de_paragrafos,std::string const& critica): TextoEmProsa(titulo, autor, numero_de_palavras,numero_de_frases, numero_de_paragrafos),critica_(critica) {}TextoLiterario(std::istream& entrada);
//Cria um clone:virtual TextoLiterario* clona() const {return new TextoLiterario(*this);}
virtual string tipo() const {return "TextoLiterario";}
string critica() const {return critica_;}
void critica(std::string const& nova_critica) {critica_ = nova_critica;}
virtual void mostra() const;
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:string critica_;};
TextoLiterario::TextoLiterario(std::istream& entrada): TextoEmProsa(entrada) {critica_ = leLinha(entrada);}
void TextoLiterario::mostra() const {cout << "Tipo de texto: " << tipo() << endl;TextoEmProsa::mostra();cout << "Crítica: " << critica() << endl;}
void TextoLiterario::carrega(std::istream& entrada) {TextoEmProsa::carrega(entrada);critica_ = leLinha(entrada);}
void TextoLiterario::guarda(std::ostream& saida) const {saida << tipo() << endl;TextoEmProsa::guarda(saida);saida << critica_;}
class TextoJornalistico : public TextoEmProsa {public:TextoJornalistico(std::string const& titulo, std::string const& autor,int const numero_de_palavras,int const numero_de_frases,int const numero_de_paragrafos,std::string const& jornal,Data const& data): TextoEmProsa(titulo, autor, numero_de_palavras,numero_de_frases, numero_de_paragrafos),jornal_(jornal),data_(data) {}TextoJornalistico(std::istream& entrada);
//Cria um clone:virtual TextoJornalistico* clona() const {return new TextoJornalistico(*this);}
virtual string tipo() const {return "TextoJornalistico";}
string jornal() const {return jornal_;}Data data() const {return data_;}
virtual void mostra() const;
virtual void carrega(std::istream& entrada);virtual void guarda(std::ostream& saida) const;
private:string jornal_;Data data_;};
TextoJornalistico::TextoJornalistico(std::istream& entrada): TextoEmProsa(entrada) {jornal_ = leLinha(entrada);data_.carrega(entrada);}
void TextoJornalistico::mostra() const {cout << "Tipo de texto: " << tipo() << endl;TextoEmProsa::mostra();cout << "Jornal: " << jornal() << endl;cout << "Data: " << data() << endl;}
void TextoJornalistico::carrega(std::istream& entrada) {TextoEmProsa::carrega(entrada);jornal_ = leLinha(entrada);data_.carrega(entrada);}
void TextoJornalistico::guarda(std::ostream& saida) const {saida << tipo() << endl;TextoEmProsa::guarda(saida);saida << jornal_;data_.guarda(saida);}
class ColeccaoDeTextos {public:ColeccaoDeTextos() {};ColeccaoDeTextos(ColeccaoDeTextos const& c);~ColeccaoDeTextos();
void operator = (ColeccaoDeTextos const& c);
void informacao(std::string const& titulo) const;
void acrescenta(Texto* t);void remove(std::string const& titulo);
double indiceMedioDeLegibilidade() const;
void carrega(std::istream& entrada);void guarda(std::ostream& saida) const;
private:list<Texto*> textos;};
ColeccaoDeTextos::ColeccaoDeTextos(ColeccaoDeTextos const& c) {for(list<Texto*>::const_iterator i = c.textos.begin();i != c.textos.end(); ++i)textos.push_back((*i)->clona());}
ColeccaoDeTextos::~ColeccaoDeTextos() {for(list<Texto*>::const_iterator i = textos.begin(); i != textos.end();++i)delete *i;}
void ColeccaoDeTextos::operator =(ColeccaoDeTextos const& c) {while(!textos.empty()) {delete textos.front();textos.pop_front();}
for(list<Texto*>::const_iterator i = c.textos.begin();i != c.textos.end(); ++i)textos.push_back((*i)->clona());}
void ColeccaoDeTextos::informacao(std::string const& titulo) const {for(list<Texto*>::const_iterator i = textos.begin(); i != textos.end();++i)if((*i)->titulo() == titulo) {(*i)->mostra();return;}}
void ColeccaoDeTextos::acrescenta(Texto* t) {textos.push_back(t);}
void ColeccaoDeTextos::remove(std::string const& titulo) {for(list<Texto*>::iterator i = textos.begin(); i != textos.end(); ++i)if((*i)->titulo() == titulo) {delete *i;textos.erase(i);return;}}
double ColeccaoDeTextos::indiceMedioDeLegibilidade() const {double total = 0.0;
for(list<Texto*>::const_iterator i = textos.begin(); i != textos.end();++i)total += (*i)->legibilidade();
return total / textos.size();}
void ColeccaoDeTextos::carrega(std::istream& entrada) {int numero_de_textos;entrada >> numero_de_textos;
for(int i = 0; i != numero_de_textos; ++i) {std::string tipo_de_texto;entrada >> tipo_de_texto;
if(tipo_de_texto == "TextoEmVerso")textos.push_back(new TextoEmVerso(entrada));else if (tipo_de_texto == "TextoCientífico")textos.push_back(new TextoCientifico(entrada));else if (tipo_de_texto == "TextoLiterário")textos.push_back(new TextoLiterario(entrada));else if (tipo_de_texto == "TextoJornalístico")textos.push_back(new TextoJornalistico(entrada));else {cerr << "Erro: tipo inválido." << endl;exit(1);}}}
void ColeccaoDeTextos::guarda(std::ostream& saida) const {saida << textos.size() << endl;for(list<Texto*>::const_iterator i = textos.begin(); i != textos.end();++i) {saida << (*i)->tipo() << endl;(*i)->guarda(saida);}}
usada para representar os elos de uma cadeia duplamente ligada com a particularidade de ser circular, i.e., o elo seguinte do último elo da cadeia é o primeiro elo da cadeia e o elo anterior do primeiro elo da cadeia é o último elo da cadeia. A cadeia não tem guardas.struct Elo {typedef int Item;
Item item;Elo* anterior;Elo* seguinte;};
Considere que existe um procedimento
que troca dois ponteiros parainline void troca(Elo*& a, Elo*& b) {Elo* aux = a;a = b;b = aux;}
Elo.
Defina um procedimento void inverte(Elo*& primeiro)
que inverta a ordem dos elos de uma cadeia duplamente ligada e circular
cujo primeiro elo é apontado pelo ponteiro primeiro.
Note que quando a cadeia está vazia o ponteiro para o primeiro elemento
tem o valor 0. Note também que em geral o primeiro elo da
cadeia passa a ser o que antes era o último.
Faça desenhos da cadeia em várias situações! Só assim resolverá com sucesso esta alínea!
[1,5 valores]
Apresenta-se um programa completo, com o qual é possível testar o algoritmo. A negrito a resposta necessária.
#include <iostream>
using namespace std;
struct Elo {typedef int Item;
Item item;Elo* anterior;Elo* seguinte;Elo(Item const& item, Elo* anterior = 0, Elo* seguinte = 0): item(item), anterior(anterior), seguinte(seguinte) {}};
inline void troca(Elo*& a, Elo*& b) {Elo* aux = a;a = b;b = aux;}
void poeUltimo(Elo*& primeiro, Elo::Item const& item) {if(primeiro == 0) {primeiro = new Elo(item);primeiro->seguinte = primeiro;primeiro->anterior = primeiro;} elseprimeiro->anterior = primeiro->anterior->seguinte =new Elo(item, primeiro->anterior, primeiro);}
void mostra(Elo* primeiro) {if(primeiro != 0) {
Elo* elo = primeiro;
do {
cout << elo->item << endl;
elo = elo->seguinte;
} while(elo != primeiro);
}
}
void inverte(Elo*& primeiro) {
if(primeiro != 0) {
Elo* elo = primeiro = primeiro = primeiro->anterior;
do {
troca(elo->anterior, elo->seguinte);
elo = elo->seguinte;
} while(elo != primeiro);
}}
int main(){cout << "Cadeia com 0 itens: " << endl;Elo* primeiro0 = 0;mostra(primeiro0);inverte(primeiro0);mostra(primeiro0);
cout << "Cadeia com 1 itens: " << endl;Elo* primeiro1 = 0;poeUltimo(primeiro1, 1);mostra(primeiro1);inverte(primeiro1);mostra(primeiro1);
cout << "Cadeia com 2 itens: " << endl;Elo* primeiro2 = 0;poeUltimo(primeiro2, 1);poeUltimo(primeiro2, 2);mostra(primeiro2);inverte(primeiro2);mostra(primeiro2);
cout << "Cadeia com 3 itens: " << endl;Elo* primeiro3 = 0;poeUltimo(primeiro3, 1);poeUltimo(primeiro3, 2);poeUltimo(primeiro3, 3);mostra(primeiro3);inverte(primeiro3);mostra(primeiro3);}
Defina a funçãoclass PilhaInt {public:typedef int Item;
PilhaInt(int tamanho_inicial = tamanho_minimo); //construtor da classe.PilhaInt(PilhaInt const& p); //construtor por cópia da classe.~PilhaInt(); //destrutor da classe.
PilhaInt& operator = (PilhaInt const& p); //atribuição por cópia da classe.
...
bool vazia() const; //devolvetruesse a pilha estiver vazia.bool cheia() const; //devolvetruesse a pilha estiver cheia.int altura() const; //devolve o número de itens na pilha.
...
private:static int const tamanho_minimo = 32; //tamanho mínimo da matriz (tem de ser > 0).
mutable int tamanho; //tamanho corrente da matriz.int quantos; //número de itens actualmente na pilha.mutable Item* itens; //matriz dinâmica dos itens.};
bool PilhaInt::cheia()
const. Uma pilha está cheia quando não havendo
mais elementos disponíveis na matriz dinâmica, se tenta duplicar
o tamanho desta matriz e tal não é possível por ter
sido lançada uma excepção.
Observação: a excepção lançada
pelo operador new em caso de falta de memória é
bad_alloc.
Mas é preferível lidar com o problema para qualquer excepção.
Defina as funções e procedimentos (membros ou não) que achar necessários.
[2 valores]
Ver Resolução da Aula Prática 6.
[1 valor]
Ver Aula Prática 8.