Resolución de junio 09

Anuncio
3. Indicar la salida por pantalla (2 puntos-20 minutos)
Indicar la impresión por pantalla del siguiente programa:
_________________________________________________________________
#include <iostream.h>
class ClaseA
{
protected:
int a;
public:
ClaseA(int n):a(n){}
void mostrar(){cout<<a<<endl;}
};
class ClaseB:public ClaseA
{
int b;
public:
ClaseB(int n, int m):b(n),ClaseA(m){}
void mostrar(){cout<<a<<','<<b<<endl;};
} ;
void main()
{
ClaseA ca(2);
ClaseB cb(8,4);
ca.mostrar();
cb.mostrar();
ca=cb;
ca.mostrar();
cb.mostrar();
ClaseA *c1=new ClaseA(1);
ClaseB *c2=new ClaseB(2,3);
ClaseA *c3=c1,*c4=c2;
c3->mostrar();
c4->mostrar();
ClaseB *c5;
c5 = static_cast<ClaseB *>(c4);
c5->mostrar();
delete c1;
delete c2;
}
_____________________________________________________________________
1
2
3
4
5
6
7
8
2
4,8
4
4,8
1
3
3,2
4. Ejercicio de programación (2,5 puntos-50 minutos)
Uno de los clases más clásicas y evidentes en las que se guarda especialmente el encapsulamiento son las
clases contenedoras, cuya misión es la de almacenar referencias a objetos u objetos. Hay varios tipos
clásicos de contenedores, entre los que cabe destacar las pilas de datos, los árboles, las listas enlazadas,
etc.
El siguiente ejercicio consiste en completar y trabajar con una pequeña estructura de clases que
implementa una pila de datos. Para ello se dispone de una clase base denominada EUITIapilable, que
servirá de sustento para los objetos que posteriormente se quieran introducir en una pila. El código de esta
clase está COMPLETO, y es utilizado por la clase EUITIpila que es quien implementa la función de pila,
o dicho de otra forma, de contenedor LIFO (Last In –First Out) .
Esta funcionalidad se logra mediante la inclusión de una lista encadenada de objetos EUITIapilable, tal y
como representa el esquema de la figura:
PILA
Raiz
0
anterior
siguiente
Objeto
Objeto
anterior
anterior
siguiente
siguiente
0
De forma que cada vez que se añade un nuevo elemento a la pila, lo que se hace es que el nodo Raiz,
apunte con su puntero siguiente a este nuevo elemento, y al antiguo elemento que estaba al principio de la
pila se le dice que su puntero anterior apunte al nuevo. De forma coherente se procede a modificar los
punteros anterior y siguiente del nuevo objeto para mantener la lista organizada.
Las funciones que hacen esto se denominan push() para insertar, y pop() para extraer. Además se incluye
una función main, que demuestra un primer uso de EUITIpila.
SE PIDE, por orden:
1.- Escribir la definición del destructor de EUITIpila, el cual eliminará todo lo almacenado. (1 punto)
2.- Escribir la definición del método getNumero() de EUITIpila. (2 puntos)
3.- Sobrecargar el operador += de EUITIpila de forma que se comporte igual que el método push(). (2
puntos)
4.- Escribir completamente la clase Numero de forma que sea coherente con el uso que se da de la
misma en la función main. (2 puntos)
5.- Crear una clase Vector que pueda ser introducida en la pila, y que permita almacenar ternas de tres
números decimales. (2 puntos)
6.- Escribir una función main nueva que permita incluir en la pila tanto Números como Vectores a
elección del usuario, y que después muestre lo almacenado por pantalla. Se recomienda crear para ello
una clase abstracta que de una interfaz de impresión y petición de datos, y de la cual se puede hacer
heredar tanto número como vector. (2 puntos)
NOTA : Aunque la suma de puntuaciones es 11, la máxima nota posible en el ejercicio será de 10.
class EUITIapilable
{
friend class EUITIpila;
EUITIapilable *siguiente;
EUITIapilable *anterior;
protected:
EUITIapilable():siguiente(0),anterior(0){};
virtual ~EUITIapilable(){
if(anterior==0)return; //no esta en la pila
if(siguiente){
anterior->siguiente=siguiente;
siguiente->anterior=anterior;
}
else anterior->siguiente=0;
}
};
class EUITIpila
{
EUITIapilable raiz;
public:
void push(EUITIapilable *obj);
EUITIapilable *pop();
int getNumero(); //numero de elementos en la pila
void vacia();
~EUITIpila(); //elimina los elementos de la pila
};
//introduce el objeto al principio de la pila
void EUITIpila::push(EUITIapilable *obj)
{
if(obj==0)return;
if(raiz.siguiente)( raiz.siguiente)->anterior=obj;
obj->siguiente=raiz.siguiente;
obj->anterior=&raiz;
raiz.siguiente=obj;
}
//saca el primer objeto de la pila
EUITIapilable *EUITIpila::pop()
{
if(raiz.siguiente==0)return 0;
EUITIapilable *aux=raiz.siguiente;
raiz.siguiente=aux->siguiente;
if(raiz.siguiente)( raiz.siguiente)->anterior=&primero;
aux->anterior=aux->siguiente=0;
return aux;
}
//elimina los elementos almacenados y deja la pila
//preparada para ser utilizada de nuevo
void EUITIpila::vacia()
{
EUITIapilable *aux;
while(aux=pop())delete aux;
}
_______________________________________________________________________________
#include <iostream.h>
void main()
{
EUITIpila pila;
Numero *aux;;
int num;
cin>>num;
while(num){
pila.push(new Numero(num));
cin>>num;
}
cout<<"Se han almacenado "<<pila.getNumero()<<"numeros:\n";
while(aux=(Numero *)(pila.pop())){
cout<<aux->num<<endl;
delete aux;
}
}
1.- Escribir la definición del destructor de EUITIpila, el cual eliminará todo lo almacenado. (1 punto)
EUITIpila::~EUITIpila()
{
vacia();
}
2.- Escribir la definición del método getNumero() de EUITIpila. (2 puntos)
int EUITIpila::getNumero()
{
int num=0;
EUITIapilable *aux=&raiz;
while(aux->siguiente){
aux=aux->siguiente;
num++;
}
return num;
}
3.- Sobrecargar el operador += de EUITIpila de forma que se comporte igual que el método push(). (2
puntos)
void EUITIpila::operator += (EUITIapilable *obj)
{
push(obj);
}
4.- Escribir completamente la clase Numero de forma que sea coherente con el uso que se da de la
misma en la función main. (2 puntos)
class Numero:public EUITIapilable
{
public:
int num;
Numero(int n):num(n){};
};
5.- Crear una clase Vector que pueda ser introducida en la pila, y que permita almacenar ternas de tres
números decimales. (2 puntos)
class Vector:public EUITIapilable
{
public:
float data[3];
Vector(float a,float b, float c){
data[0]=a; data[1]=b; data[2]=c;
}
};
6.- Escribir una función main nueva que permita incluir en la pila tanto Números como Vectores a
elección del usuario, y que después muestre lo almacenado por pantalla. Se recomienda crear para ello
una clase abstracta que de una interfaz de impresión y petición de datos, y de la cual se puede hacer
heredar tanto número como vector. (2 puntos)
#include <iostream.h>
class Interfaz: public EUITIapilable
{
public:
virtual void pedir()=0;
virtual void imprimir()=0;
};
class Numero:public Interfaz
{
public:
int num;
Numero(int n=0):num(n){};
void pedir(){
cin>>num;
}
void imprimir(){
cout<<num;
}
};
class Vector:public Interfaz
{
public:
float data[3];
Vector(float a=0,float b=0, float c=0){
data[0]=a; data[1]=b; data[2]=c;
}
void pedir(){
cin>>data[0]>>data[1]>>data[2];
}
void imprimir(){
cout<<data[0]<<data[1]<<data[2];
}
};
void main()
{
EUITIpila pila;
Interfaz *aux;
char sel='1';
while(sel!='3'){
cout<<"1.- Numero"<<endl;
cout<<"2.- Vector"<<endl;
cout<<"3.- Salir"<<endl;
cin>>sel;
if(sel=='1') aux=new Numero();
else if(sel=='2') aux=new Vector();
else aux=0;
if(aux){
aux->pedir();
pila.push(aux);
}
}
cout<<"Se han almacenado "<<pila.getNumero()<<"cosas:\n";
while(aux=(Interfaz *)(pila.pop())){
aux->imprimir();
cout<<endl;
delete aux;
}
}
5. Problema de Análisis y Diseño Orientado a Objetos (2.5 puntos - 50 minutos)
Se pretende desarrollar un programa de simulación de un vapor de agua, para el que se ha desarrollado ya
la siguiente clase, que funciona correctamente y no es necesario modificar:
class Atomo
{
public:
Atomo(int num);
virtual ~Atomo();
void Enlaza(Atomo* a);
void CalculaPosicion();
void Dibuja();
protected:
float x;
float y;
float z;
int numero_atomico;
Atomo* enlace;
};
Ejemplo del resultado final
Supóngase que el método CalculaPosicion() es capaz de calcular la posición del átomo en el
espacio teniendo en cuenta todas las interacciones físicas, incluyendo la posibilidad que dicho átomo haya
establecido un enlace con otro átomo.
El código para dibujar una molécula de agua utilizando la clase Atomo sería el siguiente:
void main()
{
Atomo hidrogeno1(1);
Atomo hidrogeno2(1);
Atomo oxigeno(16);
hidrogeno1.Enlaza(&oxigeno);
hidrogeno2.Enlaza(&oxigeno);
oxigeno.CalculaPosicion();
hidrogeno1.CalculaPosicion();
hidrogeno2.CalculaPosicion();
hidrogeno1.Dibuja();
hidrogeno2.Dibuja();
oxigeno.Dibuja();
}
Donde es importante el orden de cálculo de las posiciones, es decir, primero se calcula la posición del
oxigeno, y después la de los átomos de hidrogeno, que dependen del átomo de oxigeno.
Cuando el programa este completado, el código del main() debe quedar como:
void main()
{
VaporAgua vapor(30);
vapor.CalculaPosicion();
vapor.Dibuja();
}
//30 moleculas de agua
Se pide:
1. Diagrama de Clases de Diseño (DCD de la solución), que incluya orientación a objetos para cada
molécula de agua. (3,5 puntos)
2. Implementación de la solución en C++ (3,5 puntos)
3. Un diagrama de secuencias del cálculo de la posición y el dibujo del vapor, a partir de la función
main().(3 puntos)
SOLUCION:
1:
2:
3:CODIGO
#include "Atomo.h"
//MoleculaAgua.h
class MoleculaAgua
{
public:
MoleculaAgua();
void Dibuja();
void CalculaPosicion();
protected:
Atomo hidrogeno1;
Atomo hidrogeno2;
Atomo oxigeno;
};
//MoleculaAgua.cpp
MoleculaAgua::MoleculaAgua():oxigeno(16),hidrogeno1(1),hidrogeno2(1)
{
hidrogeno1.Enlaza(&oxigeno);
hidrogeno2.Enlaza(&oxigeno);
}
void MoleculaAgua::CalculaPosicion()
{
oxigeno.CalculaPosicion();
hidrogeno1.CalculaPosicion();
hidrogeno2.CalculaPosicion();
}
void MoleculaAgua::Dibuja()
{
hidrogeno1.Dibuja();
hidrogeno2.Dibuja();
oxigeno.Dibuja();
}
//VaporAgua.h
#include "MoleculaAgua.h"
class VaporAgua
{
public:
VaporAgua(int num);
virtual ~VaporAgua();
void CalculaPosicion();
void Dibuja();
protected:
Molecula* moleculas[100];
int num_moleculas;
};
//VaporAgua.cpp
#include "VaporAgua.h"
VaporAgua::VaporAgua(int num)
{
for(int i=0;i<num;i++)
{
Molecula* m=new MoleculaAgua;
moleculas[num_moleculas++]=m;
}
}
VaporAgua::~VaporAgua()
{
for(int i=0;i<num_moleculas;i++)
{
delete moleculas[i];
}
num_moleculas=0;
}
void VaporAgua::Dibuja()
{
for(int i=0;i<num_moleculas;i++)
moleculas[i]->Dibuja();
}
void VaporAgua::CalculaPosicion()
{
for(int i=0;i<num_moleculas;i++)
moleculas[i]->CalculaPosicion();
}
Descargar