Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y...

220
Programación II Relación de Ejercicios y Soluciones Sonido e Imagen UNIVERSIDAD DE MÁLAGA Dpto. Lenguajes y CC. Computación E.T.S.I. Telecomunicación Contenido Tema 1: Almacenamiento en Memoria Secundaria. Ficheros 2 Tema 2: Tipos Abstractos de Datos 15 Tema 2.1: Programacion Modular ................................ 15 Tema 2.2: Tipos Abstractos de Datos .............................. 25 Tema 3: Gestión de Memoria Dinámica 44 Tema 3.1: Listas Enlazadas ................................... 44 Tema 3.2: Abstracción en la Gestión de Memoria Dinámica ................. 64 Tema 4: Introducción a la Programación Orientada a Objetos 93 Tema 5: Colecciones 139 Prácticas de Laboratorio 150 Práctica 1: Almacenamiento Persistente de Datos ....................... 150 Práctica 2: Tipos Abstractos de Datos (I) ........................... 160 Práctica 3: Tipos Abstractos de Datos (II) ........................... 165 Práctica 4: Tipos Abstractos de Datos (III) .......................... 171 Práctica 5: Gestión de Memoria Dinámica ........................... 183 Práctica 6: Abstracción en la Gestión de Memoria Dinámica (I) ............... 191 Práctica 7: Abstracción en la Gestión de Memoria Dinámica (II) .............. 197 Práctica 8: Introducción a la Programación Orientada a Objetos .............. 203 Práctica 9: La Clase Vector de la Biblioteca Estándar .................... 209 Prácticas de Autoevaluación 214 Gestión de Factoría de Androides ................................ 214 Gestión de Tareas Periódicas .................................. 218 cc Esta obra se encuentra bajo una licencia Reconocimiento-NoComercial-CompartirIgual 4.0 Internacional (CC BY-NC-SA 4.0) de Creative Commons. Véase http://creativecommons.org/licenses/by-nc-sa/4.0/deed.es_ES 1

Transcript of Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y...

Page 1: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Programación II

Relación de Ejerciciosy Soluciones

Sonido e ImagenUNIVERSIDAD DE MÁLAGADpto. Lenguajes y CC. Computación

E.T.S.I. Telecomunicación

Contenido

Tema 1: Almacenamiento en Memoria Secundaria. Ficheros 2

Tema 2: Tipos Abstractos de Datos 15

Tema 2.1: Programacion Modular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

Tema 2.2: Tipos Abstractos de Datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Tema 3: Gestión de Memoria Dinámica 44

Tema 3.1: Listas Enlazadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

Tema 3.2: Abstracción en la Gestión de Memoria Dinámica . . . . . . . . . . . . . . . . . 64

Tema 4: Introducción a la Programación Orientada a Objetos 93

Tema 5: Colecciones 139

Prácticas de Laboratorio 150

Práctica 1: Almacenamiento Persistente de Datos . . . . . . . . . . . . . . . . . . . . . . . 150

Práctica 2: Tipos Abstractos de Datos (I) . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

Práctica 3: Tipos Abstractos de Datos (II) . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

Práctica 4: Tipos Abstractos de Datos (III) . . . . . . . . . . . . . . . . . . . . . . . . . . 171

Práctica 5: Gestión de Memoria Dinámica . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

Práctica 6: Abstracción en la Gestión de Memoria Dinámica (I) . . . . . . . . . . . . . . . 191

Práctica 7: Abstracción en la Gestión de Memoria Dinámica (II) . . . . . . . . . . . . . . 197

Práctica 8: Introducción a la Programación Orientada a Objetos . . . . . . . . . . . . . . 203

Práctica 9: La Clase Vector de la Biblioteca Estándar . . . . . . . . . . . . . . . . . . . . 209

Prácticas de Autoevaluación 214

Gestión de Factoría de Androides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214

Gestión de Tareas Periódicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218

©cc Esta obra se encuentra bajo una licencia Reconocimiento-NoComercial-CompartirIgual 4.0 Internacional (CC BY-NC-SA 4.0) deCreative Commons. Véase http://creativecommons.org/licenses/by-nc-sa/4.0/deed.es_ES

1

Page 2: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Nota: en la solución a los ejercicios, se ha utilizado el tipo array de TR1, que ha sido incorporado a la biblio-teca de C++ en el estándar de 2011. Si su biblioteca estándar no contiene la definición del tipo array, puededescargarla desde la siguiente dirección: http://www.lcc.uma.es/%7Evicente/docencia/cpplibs/array_tr1.zip

Tema 1: Almacenamiento en Memoria Secundaria. Ficheros1. Escribir un programa que cuente el número de letras minúsculas, de letras mayúsculas y de dígitos de un

fichero.

Solución� �#include <iostream>#include <fstream>using namespace std;struct Estad {

unsigned may;unsigned min;unsigned dig;

};

// i n i c i a l i z a cuenta de e s t a d i s t i c a svoid inic(Estad& sts){

sts.may = 0;sts.min = 0;sts.dig = 0;

}// muestra l a s e s t a d i s t i c a svoid escribir(const Estad& sts){

cout << "Mayusculas: " << sts.may << endl;cout << "Minusculas: " << sts.min << endl;cout << "Digitos: " << sts.dig << endl;

}inline bool es_mayuscula(char c){

return (c >= 'A' && c <= 'Z');}inline bool es_minuscula(char c){

return (c >= 'a' && c <= 'z');}inline bool es_digito(char c){

return (c >= '0' && c <= '9');}void procesar(char c, Estad& sts){

if (es_mayuscula(c)) {++sts.may;

} else if (es_minuscula(c)) {++sts.min;

} else if (es_digito(c)) {++sts.dig;

}}

void estadisticas(const string& nombre , bool& ok , Estad& sts){

ifstream fich;fich.open(nombre.c_str ());if (fich.fail ()) {

ok = false;} else {

inic(sts);char c;fich.get(c);while (! fich.fail ()) {

procesar(c, sts);fich.get(c);

}ok = fich.eof();

2

Page 3: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

fich.close ();}

}

int main(){

bool ok;Estad sts;cout << "Introduzca el nombre del fichero: ";string nombre;cin >> nombre;estadisticas(nombre , ok , sts);if (ok) {

escribir(sts);} else {

cout << "Error al procesar el fichero" << endl;}

}� �2. Escribir un programa con la opción de encriptar y de desencriptar un fichero de texto, dependiendo de la

extensión del fichero de entrada. La encriptación (codificación) consiste en que dado un fichero de textode entrada (extensión txt) genere otro fichero de salida encriptado (extensión cod). Esta codificaciónconsiste reemplazar cada letra por la tercera siguiente de forma circular (ej. a→d, b→e, · · ·, w→z, x→a,y→b, z→c). La opción de desencriptado consiste en leer un fichero codificado (extensión cod) y recuperarla información original en un fichero de texto (extensión txt).

Solución� �#include <iostream>#include <fstream>using namespace std;

const unsigned DESPL = 3;

const int CIFRAR = 0;const int DESCIFRAR = 1;const int ERROR = 2;

// c i f r ado ro t a c i ona l (DESPL) de l e t r achar cifrar(char c){

if (c >= 'a' && c <= 'z') {c = char(c + DESPL );if (c > 'z') {

c = char('a' + c - 'z' - 1);}

} else if (c >= 'A' && c <= 'Z') {c = char(c + DESPL );if (c > 'Z') {

c = char('A' + c - 'Z' - 1);}

}return c;

}// de s c i f r ado ro t a c i ona l (DESPL) de l e t r achar descifrar(char c){

if (c >= 'a' && c <= 'z') {c = char(c - DESPL );if (c < 'a') {

c = char('z' + c - 'a' + 1);}

} else if (c >= 'A' && c <= 'Z') {c = char(c - DESPL );if (c < 'A') {

c = char('Z' + c - 'A' + 1);}

}return c;

}

// transforma una l e t r a segun e l codigo de operacion

3

Page 4: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

char transformar(char c, int op){

char res;if (op == CIFRAR) {

res = cifrar(c);} else {

res = descifrar(c);}return res;

}

// trasnforma e l f i c h e r o de entrada y l o e s c r i b e en e l f i c h e r o de s a l i d avoid transformar_fichero(const string& entrada , const string& salida ,

int op, bool& ok){

ifstream f_ent;f_ent.open(entrada.c_str ());if (f_ent.fail ()) {

ok = false;} else {

ofstream f_sal;f_sal.open(salida.c_str ());if (f_sal.fail ()) {

ok = false;} else {

char ch;f_ent.get(ch);while (! f_ent.fail() && ! f_sal.fail ()) {

f_sal.put(transformar(ch , op));f_ent.get(ch);

}ok = (f_ent.eof() && ! f_sal.fail ());f_sal.close ();

}f_ent.close ();

}}

// busca un carac t e r e una cadenaunsigned buscar(const string& nombre , char c){

unsigned i = 0;while ((i < nombre.size ())&&(c != nombre[i])) {

++i;}return i;

}

// devue l ve l a ex t ens ion de l nombre de f i c h e r ostring extension(const string& nombre){

string res = "";unsigned i = buscar(nombre , '.');if (i < nombre.size ()) {

res = nombre.substr(i+1, nombre.size()-(i+1));}return res;

}

// ca l c u l a l a operacion a r e a l i z a r a p a r t i r de l a s ex t ens iones de l o s// f i c h e r o s de entrada y s a l i d aint codigo_op(const string& entrada , const string& salida){

int res;if (( extension(entrada)=="txt")&&(extension(salida)=="cod")) {

res = CIFRAR;} else if (( extension(entrada)=="cod")&&(extension(salida)=="txt")) {

res = DESCIFRAR;} else {

res = ERROR;}return res;

}

4

Page 5: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

int main(){

bool ok;cout << "Introduzca el nombre del fichero de entrada: ";string nombre_ent;cin >> nombre_ent;cout << "Introduzca el nombre del fichero de salida: ";string nombre_sal;cin >> nombre_sal;int op = codigo_op(nombre_ent , nombre_sal );if (op != ERROR) {

transformar_fichero(nombre_ent , nombre_sal , op , ok);if (ok) {

cout << "Procesamiento correcto" << endl;} else {

cout << "Error al procesar el fichero" << endl;}

} else {cout << "Error: extensiones erroneas" << endl;

}}� �

3. Escribir un programa para procesar información sobre los clientes de una agencia matrimonial. El programadebe crear un fichero de texto (cuyo nombre se leerá por teclado) en el que se guarde la información deun número indeterminado de personas. La información que se guardará por cada persona será:Nombre: Cadena de caracteres.Edad int.Género char (M/F).Arte char (S/N).Deporte char (S/N).Libros char (S/N).Música char (S/N).

La información correspondiente a cada persona se leerá del teclado. El proceso finalizará cuando se tecleeun campo Nombre que esté vacío.

Solución� �#include <iostream>#include <fstream>#include <string>#include <array>using namespace std;using namespace std;

const char FEMENINO = 'F';const char MASCULINO = 'M';

const unsigned NAFICCIONES = 4;typedef array<string , NAFICCIONES> StrAficciones;const StrAficciones AFICCIONES = {{

"Arte", "Deporte", "Libros", "Musica"}};typedef array<bool , NAFICCIONES> Aficciones;

struct Persona {string nombre;unsigned edad;char gen;Aficciones af;

};

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// conv i e r t e una l e t r a a mayusculasinline char mayuscula(char c){

if (c >= 'a' && c <= 'z') {c = char(c - 'a' + 'A');

}return c;

5

Page 6: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Leer de Teclado −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e r una opcion (S/N) a boo linline void leer(bool& a){

char c;cin >> c;a = (mayuscula(c) == 'S');

}

// l e e r e l genero (M/F) a charinline void leer_genero(char& g){

char c;cin >> c;if (mayuscula(c) == MASCULINO) {

g = MASCULINO;} else {

g = FEMENINO;}

}

// l e e r a f i c c i on e svoid leer(Aficciones& af){

for (unsigned i = 0; i < af.size (); ++i) {cout << AFICCIONES[i] << " (S/N): ";leer(af[i]);

}}

// l e e r datos de personavoid leer(Persona& p){

cout << "Nombre: ";getline(cin , p.nombre );if (p.nombre.size() > 0) {

cout << "Edad: ";cin >> p.edad;cout << "Genero (M/F): ";leer_genero(p.gen);leer(p.af);cin.ignore (1000 , '\n');

}}

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Esc r i b i r a Fichero −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// e s c r i b i r una opcion (S/N) boo l a f i c h e r oinline void escribir(ofstream& fich , bool a){

if (a) {fich << 'S';

} else {fich << 'N';

}}// e s c r i b i r e l genero (M/F) char a f i c h e r oinline void escribir_genero(ofstream& fich , char g){

if (g == MASCULINO) {fich << MASCULINO;

} else {fich << FEMENINO;

}}// e s c r i b i r una persona a f i c h e r ovoid escribir(ofstream& fich , const Persona& p){

fich << p.nombre << endl;

6

Page 7: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

fich << p.edad << " " ;escribir(fich , p.gen);for (unsigned i = 0; i < p.af.size (); ++i) {

escribir(fich , p.af[i]);}fich << endl;

}

void crear_fichero(const string& nombre , bool& ok){

ofstream fich;fich.open(nombre.c_str ());if (fich.fail ()) {

ok = false;} else {

Persona p;leer(p);while ( !cin.fail() && (p.nombre.size() > 0)&& ! fich.fail ()) {

escribir(fich , p);leer(p);

}ok = !cin.fail() && ! fich.fail ();fich.close ();

}}

int main(){

bool ok;cout << "Introduzca el nombre del fichero: ";string nombre;cin >> nombre;cin.ignore (1000 , '\n');crear_fichero(nombre , ok);if (ok) {

cout << "Procesamiento correcto" << endl;} else {

cout << "Error al procesar el fichero" << endl;}

}� �4. Ampliar el programa que procesa clientes de una agencia matrimonial para que tome los datos de todos los

candidatos a estudiar del fichero del ejercicio anterior, lea el cliente del teclado y finalmente genere comoresultado un fichero (cuyo nombre será leído desde teclado) con toda la información correspondiente a loscandidatos aceptados. Una persona del fichero de entrada se considerará aceptable como candidato si tienediferente género y por lo menos tres aficiones comunes con respecto al aspirante introducido por pantalla.(El programa debe ser capaz de trabajar con cualquier número de personas en el fichero de entrada).

Solución� �#include <iostream>#include <fstream>#include <string>#include <array>using namespace std;using namespace std;

const char FEMENINO = 'F';const char MASCULINO = 'M';

const unsigned NAFICCIONES = 4;typedef array<string , NAFICCIONES> StrAficciones;const StrAficciones AFICCIONES = {{

"Arte", "Deporte", "Libros", "Musica"}};typedef array<bool , NAFICCIONES> Aficciones;

const unsigned NAFICCOMP = 3;

struct Persona {string nombre;unsigned edad;

7

Page 8: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

char gen;Aficciones af;

};

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// conv i e r t e una l e t r a a mayusculasinline char mayuscula(char c){

if (c >= 'a' && c <= 'z') {c = char(c - 'a' + 'A');

}return c;

}

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Leer de Teclado −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e r una opcion (S/N) a boo linline void leer(bool& a){

char c;cin >> c;a = (mayuscula(c) == 'S');

}

// l e e r e l genero (M/F) a charinline void leer_genero(char& g){

char c;cin >> c;if (mayuscula(c) == MASCULINO) {

g = MASCULINO;} else {

g = FEMENINO;}

}

// l e e r a f i c c i on e svoid leer(Aficciones& af){

for (unsigned i = 0; i < af.size (); ++i) {cout << AFICCIONES[i] << " (S/N): ";leer(af[i]);

}}

// l e e r datos de personavoid leer(Persona& p){

cout << "Nombre: ";getline(cin , p.nombre );if (p.nombre.size() > 0) {

cout << "Edad: ";cin >> p.edad;cout << "Genero: ";leer_genero(p.gen);leer(p.af);cin.ignore (1000 , '\n');

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Leer de Fichero −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e r una opcion (S/N) a boo linline void leer(ifstream& in , bool& a){

char c;in >> c;a = (mayuscula(c) == 'S');

}

// l e e r e l genero (M/F) a charinline void leer_genero(ifstream& in, char& g){

8

Page 9: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

char c;in >> c;if (mayuscula(c) == MASCULINO) {

g = MASCULINO;} else {

g = FEMENINO;}

}

// l e e r datos de personavoid leer(ifstream& in , Persona& p){

getline(in , p.nombre );in >> p.edad;leer_genero(in, p.gen);for (unsigned i = 0; i < p.af.size (); ++i) {

leer(in , p.af[i]);}in.ignore (1000, '\n');

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Esc r i b i r a Fichero −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// e s c r i b i r una opcion (S/N) boo l a f i c h e r oinline void escribir(ofstream& fich , bool a){

if (a) {fich << 'S';

} else {fich << 'N';

}}// e s c r i b i r e l genero (M/F) char a f i c h e r oinline void escribir_genero(ofstream& fich , char g){

if (g == MASCULINO) {fich << MASCULINO;

} else {fich << FEMENINO;

}}// e s c r i b i t una persona a f i c h e r ovoid escribir(ofstream& fich , const Persona& p){

fich << p.nombre << endl;fich << p.edad << " " ;escribir(fich , p.gen);for (unsigned i = 0; i < p.af.size (); ++i) {

escribir(fich , p.af[i]);}fich << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// dos personas son compat ib l e s s i sus a f i c c i on e s comunes superan un// determinado umbralbool es_compatible(const Persona& p1, const Persona& p2){

unsigned cnt = 0;for (unsigned i = 0; i < p1.af.size (); ++i) {

if (p1.af[i] == p2.af[i]) {++cnt;

}}return (p1.gen != p2.gen) && (cnt >= NAFICCOMP );

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void procesar_fichero(const string& nombre_ent , const string& nombre_sal ,

const Persona& pers , bool& ok){

ifstream fich_ent;fich_ent.open(nombre_ent.c_str ());if (fich_ent.fail ()) {

ok = false;} else {

9

Page 10: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

ofstream fich_sal;fich_sal.open(nombre_sal.c_str ());if (fich_sal.fail ()) {

ok = false;} else {

Persona p;leer(fich_ent , p);while ( ! fich_ent.fail() && ! fich_sal.fail ()) {

if (es_compatible(pers , p)) {escribir(fich_sal , p);

}leer(fich_ent , p);

}ok = fich_ent.eof() && ! fich_sal.fail ();fich_sal.close ();

}fich_ent.close ();

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

bool ok;cout << "Introduzca el nombre del fichero de entrada: ";string nombre_ent;cin >> nombre_ent;cout << "Introduzca el nombre del fichero de salida: ";string nombre_sal;cin >> nombre_sal;cin.ignore (1000 , '\n');cout << "Introduzca datos de la persona: ";Persona pers;leer(pers);if (pers.nombre.size() > 0) {

procesar_fichero(nombre_ent , nombre_sal , pers , ok);if (ok) {

cout << "Procesamiento correcto" << endl;} else {

cout << "Error al procesar el fichero" << endl;}

}}� �

5. Codifique un programa que cree un fichero para contener los datos relativos a los artículos de un almacén.Para cada artículo habrá de guardar la siguiente información:Código del artículo NuméricoNombre del artículo Cadena de caracteresExistencias NuméricoPrecio Numérico

Se deberá pedir datos de cada artículo por teclado hasta que se teclee 0 (cero) como código de artículo.

Solución� �#include <iostream>#include <fstream>#include <string>using namespace std;

struct Articulo {unsigned codigo;string nombre;unsigned existencias;unsigned precio;

};

// l e e r a r t i c u l o desde e l t e c l adovoid leer(Articulo& a){

cout << "Codigo de articulo: ";cin >> a.codigo;if (a.codigo != 0) {

10

Page 11: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "Nombre de articulo: ";cin >> ws; // s a l t a separadores de l codigo de a r t i c u l ogetline(cin , a.nombre );cout << "Existencias: ";cin >> a.existencias;cout << "Precio: ";cin >> a.precio;

}}

// e s c r i b e a r t i c u l o a f i c h e r ovoid escribir(ofstream& fich , const Articulo& a){

fich << a.codigo << " " << a.nombre << endl;fich << a.existencias << " " << a.precio << endl;

}

// l e e a r t i c u l o s y l o s e s c r i b e en e l f i c h e r ovoid crear_fichero(const string& nombre , bool& ok){

ofstream fich;fich.open(nombre.c_str ());if (fich.fail ()) {

ok = false;} else {

Articulo a;leer(a);while ( !cin.fail() && (a.codigo != 0)&& ! fich.fail ()) {

escribir(fich , a);leer(a);

}ok = !cin.fail() && ! fich.fail ();fich.close ();

}}

int main(){

bool ok;cout << "Introduzca el nombre del fichero: ";string nombre;cin >> nombre;cin.ignore (1000 , '\n');crear_fichero(nombre , ok);if (ok) {

cout << "Procesamiento correcto" << endl;} else {

cout << "Error al procesar el fichero" << endl;}

}� �6. Escriba un programa que tome como entrada el fichero del ejercicio anterior y una condición sobre los

campos existencias o precio. La condición podrá ser: <campo> [<,<=,>,>=, ==, ! =] <número>

Este programa debe generar como salida un fichero que contenga todos aquellos artículos para los que secumple la condición de entrada.

Solución� �#include <iostream>#include <fstream>#include <string>using namespace std;

const int EXISTENCIAS = 0;const int PRECIO = 1;

const int MENOR = 0;const int MENIG = 1;const int MAYOR = 2;const int MAYIG = 3;const int IGUAL = 4;const int DISTINTO = 5;

11

Page 12: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

struct Condicion {int campo;int cmp;unsigned num;

};

struct Articulo {unsigned codigo;string nombre;unsigned existencias;unsigned precio;

};

// conv i e r t e a mayusculasinline char mayuscula(char c){

if (c >= 'a' && c <= 'z') {c = char(c - 'a' + 'A');

}return c;

}

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Leer de Teclado −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e e l campo por e l que r e a l i z a r l a comparacioninline void leer_campo(int& c, bool& ok){

string s;cin >> s;ok = true;if (s == "existencia") {

c = EXISTENCIAS;} else if (s == "precio") {

c = PRECIO;} else {

ok = false;}

}// l e e e l codigo de comparacioninline void leer_cmp(int& c, bool& ok){

string s;cin >> s;ok = true;if (s == "<") {

c = MENOR;} else if (s == " <=") {

c = MENIG;} else if (s == ">") {

c = MAYOR;} else if (s == " >=") {

c = MAYIG;} else if (s == "==") {

c = IGUAL;} else if (s == "!=") {

c = DISTINTO;} else {

ok = false;}

}

// l e e l a condic ion de procesamiento (campo y comparacion )inline void leer(Condicion& c, bool& ok){

bool ok1 , ok2;cout << "Introduzca campo: (existencia , precio) ";leer_campo(c.campo , ok1);cout << "Introduzca comparacion: (< <= > >= == !=) ";leer_cmp(c.cmp , ok2);cout << "Introduzca numero: ";cin >> c.num;ok = ok1 && ok2;

12

Page 13: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Leer de Fichero −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e un a r t i c u l o de f i c h e r ovoid leer(ifstream& in , Articulo& a){

in >> a.codigo;in >> ws;getline(in , a.nombre );in >> a.existencias;in >> a.precio;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Esc r i b i r a Fichero −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// e s c r i b e a r t i c u l o a f i c h e r ovoid escribir(ofstream& fich , const Articulo& a){

fich << a.codigo << " " << a.nombre << endl;fich << a.existencias << " " << a.precio << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// comprueba s i un a r t i c u l o es compat ib l e con l a condic ion de comparacionbool es_compatible(const Articulo& a, const Condicion& c){

unsigned valor = 0;switch (c.campo) {case EXISTENCIAS: valor = a.existencias; break;case PRECIO: valor = a.precio; break;}bool res = false;switch (c.cmp) {case MENOR: res = valor < c.num; break;case MENIG: res = valor <= c.num; break;case MAYOR: res = valor > c.num; break;case MAYIG: res = valor >= c.num; break;case IGUAL: res = valor == c.num; break;case DISTINTO: res = valor != c.num; break;}return res;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e a r t i c u l o s de f i c h e r o y e s c r i b e en otro f i c h e r o a qu e l l o s que son// compat ib l e s con un codigo de comparacionvoid procesar_fichero(const string& nombre_ent , const string& nombre_sal ,

const Condicion& c, bool& ok){

ifstream fich_ent;fich_ent.open(nombre_ent.c_str ());if (fich_ent.fail ()) {

ok = false;} else {

ofstream fich_sal;fich_sal.open(nombre_sal.c_str ());if (fich_sal.fail ()) {

ok = false;} else {

Articulo a;leer(fich_ent , a);while ( ! fich_ent.fail() && ! fich_sal.fail ()) {

if (es_compatible(a, c)) {escribir(fich_sal , a);

}leer(fich_ent , a);

}ok = fich_ent.eof() && ! fich_sal.fail ();fich_sal.close ();

}fich_ent.close ();

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

13

Page 14: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

int main(){

bool ok;cout << "Introduzca el nombre del fichero de entrada: ";string nombre_ent;cin >> nombre_ent;cout << "Introduzca el nombre del fichero de salida: ";string nombre_sal;cin >> nombre_sal;cin.ignore (1000 , '\n');cout << "Introduzca la condicion de procesamiento: " << endl;Condicion c;leer(c, ok);if (ok) {

procesar_fichero(nombre_ent , nombre_sal , c, ok);if (ok) {

cout << "Procesamiento correcto" << endl;} else {

cout << "Error al procesar el fichero" << endl;}

}}� �

14

Page 15: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Tema 2: Tipos Abstractos de Datos

Tema 2.1: Programacion ModularDiseñe e implemente los siguientes Módulos, dentro del espacio de nombres umalcc, así como programas de

utilización que permitan comprobar su funcionamiento.

1. Diseñe un módulo que proporcione soporte adecuado a la arímetica con números complejos. El módulodeberá definir el tipo Complejo, así como los siguientes subprogramas:

Solución: complejos.hpp� �#ifndef complejos_hpp_#define complejos_hpp_namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−const double ERROR_PRECISION = 1e-6 ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Complejo {

double real ; // par te r e a l d e l numero complejodouble imag ; // par te imaginaria de l numero complejo

} ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void sumar(Complejo& r, const Complejo& a, const Complejo& b) ;// Devuelve un numero complejo ( r ) que cont iene e l r e su l t ado de// sumar l o s numeros complejos (a ) y ( b ) .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void restar(Complejo& r, const Complejo& a, const Complejo& b) ;// Devuelve un numero complejo ( r ) que cont iene e l r e su l t ado de// r e s t a r l o s numeros complejos (a ) y ( b ) .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void multiplicar(Complejo& r, const Complejo& a, const Complejo& b) ;// Devuelve un numero complejo ( r ) que cont iene e l r e su l t ado de// mu l t i p l i c a r l o s numeros complejos (a ) y ( b ) .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void dividir(Complejo& r, const Complejo& a, const Complejo& b) ;// Devuelve un numero complejo ( r ) que cont iene e l r e su l t ado de// d i v i d i r l o s numeros complejos (a ) y ( b ) .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool iguales(const Complejo& a, const Complejo& b) ;// Devuelve t rue s i l o s numeros complejos (a ) y ( b ) son i g u a l e s .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir(const Complejo& a) ;// muestra en pan t a l l a e l numero complejo (a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(Complejo& a) ;// l e e de t e c l ado e l va l o r de l numero complejo (a ) .// l e e l a par te r e a l y l a par te imaginaria de l numero//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}#endif� �

Solución: complejos.cpp� �#include "complejos.hpp"#include <iostream>using namespace std ;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Subprogramas Aux i l i a r e s −−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// cuadrado de un numero (a^2)inline double sq(double a){

15

Page 16: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

return a*a ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Valor ab so l u t o de un numeroinline double abs(double a){

if (a < 0) {a = -a ;

}return a ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Dos numeros r e a l e s son i g u a l e s s i l a d i s t anc i a que l o s// separa es l o su f i c i en t emen te pequenyainline bool iguales(double a, double b){

return abs(a-b) <= ERROR_PRECISION ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Implementación −−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un numero complejo ( r ) que cont iene e l r e su l t ado de// sumar l o s numeros complejos (a ) y ( b ) .void sumar(Complejo& r, const Complejo& a, const Complejo& b){

r.real = a.real + b.real ;r.imag = a.imag + b.imag ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un numero complejo ( r ) que cont iene e l r e su l t ado de// r e s t a r l o s numeros complejos (a ) y ( b ) .void restar(Complejo& r, const Complejo& a, const Complejo& b){

r.real = a.real - b.real ;r.imag = a.imag - b.imag ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un numero complejo ( r ) que cont iene e l r e su l t ado de// mu l t i p l i c a r l o s numeros complejos (a ) y ( b ) .void multiplicar(Complejo& r, const Complejo& a, const Complejo& b){

double p_real = (a.real * b.real) - (a.imag * b.imag) ;double p_imag = (a.real * b.imag) + (a.imag * b.real) ;r.real = p_real;r.imag = p_imag;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un numero complejo ( r ) que cont iene e l r e su l t ado de// d i v i d i r l o s numeros complejos (a ) y ( b ) .void dividir(Complejo& r, const Complejo& a, const Complejo& b){

double divisor = sq(b.real) + sq(b.imag) ;if (:: iguales (0.0, divisor )) {

r.real = 0 ;r.imag = 0 ;

} else {double p_real = ((a.real * b.real) + (a.imag * b.imag)) / divisor ;double p_imag = ((a.imag * b.real) - (a.real * b.imag)) / divisor ;r.real = p_real;r.imag = p_imag;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve t rue s i l o s numeros complejos (a ) y ( b ) son i g u a l e s .bool iguales(const Complejo& a, const Complejo& b){

return :: iguales(a.real , b.real) && :: iguales(a.imag , b.imag) ; }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

16

Page 17: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// muestra en pan t a l l a e l numero complejo (a )void escribir(const Complejo& a){

cout << "{ " << a.real << ", " << a.imag << " }" ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e de t e c l ado e l va l o r de l numero complejo (a ) .// l e e l a par te r e a l y l a par te imaginaria de l numerovoid leer(Complejo& a){

cin >> a.real >> a.imag ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include "complejos.hpp"using namespace std ;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(Complejo& c){

cout << "Introduzca un numero complejo { real img }: " ;// c u a l i f i c a c i o n e x p l í c i t a de l e spac io de nombres uamalcc// para e v i t a r c o l i s i ó n en invocación a subprograma// l e e r (Complejo& c ) de l e spac io de nombres umalccumalcc ::leer(c) ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_suma(const Complejo& c1, const Complejo& c2){

Complejo c0 ;sumar(c0 , c1 , c2) ;escribir(c1) ;cout <<" + " ;escribir(c2) ;cout <<" = " ;escribir(c0) ;cout << endl ;Complejo aux ;restar(aux , c0 , c2) ;if (! iguales(c1, aux)) {

cout << "Error en operaciones de suma/resta"<< endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_resta(const Complejo& c1, const Complejo& c2){

Complejo c0 ;restar(c0, c1, c2) ;escribir(c1) ;cout <<" - " ;escribir(c2) ;cout <<" = " ;escribir(c0) ;cout << endl ;Complejo aux ;sumar(aux , c0, c2) ;if (! iguales(c1, aux)) {

cout << "Error en operaciones de suma/resta"<< endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_mult(const Complejo& c1, const Complejo& c2){

Complejo c0 ;multiplicar(c0, c1, c2) ;escribir(c1) ;cout <<" * " ;escribir(c2) ;cout <<" = " ;

17

Page 18: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

escribir(c0) ;cout << endl ;Complejo aux ;dividir(aux , c0, c2) ;if (! iguales(c1, aux)) {

cout << "Error en operaciones de mult/div"<< endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_div(const Complejo& c1 , const Complejo& c2){

Complejo c0 ;dividir(c0 , c1 , c2) ;escribir(c1) ;cout <<" / " ;escribir(c2) ;cout <<" = " ;escribir(c0) ;cout << endl ;Complejo aux ;multiplicar(aux , c0 , c2) ;if (! iguales(c1, aux)) {

cout << "Error en operaciones de mult/div"<< endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Complejo c1 , c2 ;// c u a l i f i c a c i ó n e x p l í c i t a de l e spac io de nombres g l o b a l// para e v i t a r c o l i s i ó n en invocación a l subprograma// l e e r (Complejo& c ) de l e spac io de nombres g l o b a l::leer(c1) ;::leer(c2) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−prueba_suma(c1, c2) ;prueba_resta(c1 , c2) ;prueba_mult(c1, c2) ;prueba_div(c1 , c2) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �2. Diseñe un módulo que proporcione soporte adecuado a la arímetica con números racionales. El módulo

deberá definir el tipo Racional, así como los subprogramas adecuados teniendo en cuenta las siguientesconsideraciones:

Los números racionales se representan mediante fracciones, donde tanto el numerador como denomi-nador son de tipo int).

Las fracciones se representarán en todo momento normalizadas (simplificadas):

• Es recomendable implementar un subprograma privado de simplificación de la fracción medianteel cálculo del máximo común divisor (m.c.d.) del numerador y el denominador y su posteriordivisión por dicho m.c.d.Para calcular el máximo común divisor de dos numeros enteros positivos n y m, el algoritmo deEuclides funciona como se indica a continuación:a) Si n < m, entonces se intercambian los valores de n y m (para asegurarnos que n siempre sea mayor

o igual que m).b) Si el valor de m es distinto de 0, entonces sea r el resto de la división entera entre n y m; después

modificamos los valores de n y m de la siguiente forma: n toma ahora el valor de m y m toma ahorael valor de r (el resto de la división entera entre n y m calculado anteriormente), y se repite esteproceso especificado hasta que el valor de m sea igual a 0.

c) Finalmente, cuando el proceso iterativo acaba, el valor de n es el máximo común divisor de ambosnúmeros.

• Para simplificar la determinación del signo de la fracción puede asumirse que el denominador dela fracción es siempre positivo (por lo que una fracción de signo negativo tendrá un numeradorde signo negativo y un denominador de signo positivo).

El número cero se guardará siempre en su forma canónica 0/1.

18

Page 19: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Debe evitarse en todo momento la asignación de cero a un denominador.

Debe proporcionar subprogramas para leer, escribir, sumar, restar, multiplicar y dividir fracciones.

Pueden también suministrarse métodos para comparación de números racionales (iguales, menor,etc).

Solución: racionales.hpp� �#ifndef racionales_hpp_#define racionales_hpp_namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Racional {

int num; // numeradorint denom; // denominador

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void sumar(Racional& r, const Racional& r1, const Racional& r2);// Asigna a l número rac iona l ( r ) e l r e su l t ado de// sumar l o s números rac i ona l e s ( r1 ) y ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void restar(Racional& r, const Racional& r1, const Racional& r2);// Asigna a l número rac iona l ( r ) e l r e su l t ado de// r e s t a r l o s números rac i ona l e s ( r1 ) y ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void multiplicar(Racional& r, const Racional& r1 , const Racional& r2);// Asigna a l número rac iona l ( r ) e l r e su l t ado de// mu l t i p l i c a r l o s números rac i ona l e s ( r1 ) y ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void dividir(Racional& r, const Racional& r1 , const Racional& r2);// Asigna a l número rac iona l ( r ) e l r e su l t ado de// d i v i d i r l o s números rac i ona l e s ( r1 ) y ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir(const Racional& r);// Muestra en pan t a l l a e l va l o r de l número rac iona l ( r )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(Racional& r);// Lee de t e c l ado e l va l o r de l número rac iona l ( r )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool igual(const Racional& r1 , const Racional& r2);// Devuelve t rue s i e l número rac iona l ( r1 ) es i g u a l a ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool menor(const Racional& r1 , const Racional& r2);// Devuelve t rue s i e l número rac iona l ( r1 ) es menor que ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}#endif� �

Solución: racionales.cpp� �#include "racionales.hpp"#include <iostream>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Subprogramas Aux i l i a r e s −−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// va l o r ab so l u t o de un numero enteroinline int abs(int x){

if (x < 0) {x = -x;

}return x;

}

19

Page 20: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// maximo comun d i v i s o r . a l gor i tmo de eu c l i d e sint mcd(int n, int m){

n = abs(n);m = abs(m);if (n < m) {

int x = n;n = m;m = x;

}while (m != 0) {

int r = n % m;n = m;m = r;

}return n;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// minimo comun mu l t i p l o// i n l i n e i n t mcm( in t a , i n t b )// {// a = abs (a ) ;// b = abs ( b ) ;// re turn (a / mcd(a , b )) ∗ b ;// }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// normal izar un numero rac iona lvoid normalizar(Racional& r){

if (r.denom == 0) {// Error denominador ceror.num = 0;r.denom = 0;

} else if (r.num == 0) {// Forma canonicar.num = 0;r.denom = 1;

} else {// d i v i d i r numerador y denominador por MCDint max_com_div = mcd(r.num , r.denom );r.num /= max_com_div;r.denom /= max_com_div;// s i denominador negat ivo , entonces cambiar s ignoif (r.denom < 0) {

r.num = -r.num;r.denom = -r.denom;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void sumar(Racional& r, const Racional& r1, const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗d2 n2∗d1 (n1∗d2)+(n2∗d1 )// −−−− + −−−− == −−−−−−− + −−−−−−− == −−−−−−−−−−−−−−−−−// d1 d2 d1∗d2 d2∗d1 d1∗d2//−−−−−−−−−−−−−−−−−−−−−−−−−r.num = ((r1.num * r2.denom) + (r2.num * r1.denom ));r.denom = r1.denom * r2.denom;normalizar(r);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void restar(Racional& r, const Racional& r1, const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗d2 n2∗d1 (n1∗d2)−(n2∗d1 )

20

Page 21: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// −−−− − −−−− == −−−−−−− − −−−−−−− == −−−−−−−−−−−−−−−−−// d1 d2 d1∗d2 d2∗d1 d1∗d2//−−−−−−−−−−−−−−−−−−−−−−−−−r.num = ((r1.num * r2.denom) - (r2.num * r1.denom ));r.denom = r1.denom * r2.denom;normalizar(r);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void multiplicar(Racional& r, const Racional& r1 , const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗n2// −−−− ∗ −−−− == −−−−−−−// d1 d2 d1∗d2//−−−−−−−−−−−−−−−−−−−−−−−−−r.num = r1.num * r2.num;r.denom = r1.denom * r2.denom;normalizar(r);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void dividir(Racional& r, const Racional& r1 , const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗d2// −−−− / −−−− == −−−−−−−// d1 d2 d1∗n2//−−−−−−−−−−−−−−−−−−−−−−−−−if ((r1.denom == 0)||(r2.denom == 0)) {

r.num = 0;r.denom = 0;

} else {int p_num = r1.num * r2.denom;int p_denom = r1.denom * r2.num;r.num = p_num;r.denom = p_denom;

}normalizar(r);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir(const Racional& r){

if (r.denom == 0) {cout << "Error";

} else {cout << r.num << " / " << r.denom;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(Racional& r){

cin >> r.num >> r.denom;normalizar(r);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool igual(const Racional& r1 , const Racional& r2){

// ambos numeros es tan normalizadosreturn (r1.num == r2.num && r1.denom == r2.denom);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool menor(const Racional& r1 , const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗d2 n2∗d1 (n1∗d2 ) < (n2∗d1 )// −−−− < −−−− ==> −−−−−−− < −−−−−−− ==> −−−−−−−−−−−−−−−−−// d1 d2 d1∗d2 d2∗d1 d1∗d2//−−−−−−−−−−−−−−−−−−−−−−−−−return (r1.num * r2.denom) < (r2.num * r1.denom);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp

21

Page 22: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

� �#include <iostream>#include <string>#include <cassert>#include "racionales.hpp"using namespace std;using namespace umalcc;

void escribir(const string& msj , const Racional& r){

cout << msj;escribir(r);cout << endl;

}int main(){

//−−−−−−−−−−−−−−−−−−−−−−−−−cout << "Introduzca numerador y denominador: ";Racional r1;leer(r1);escribir("R1: ", r1);//−−−−−−−−−−−−−−−−−−−−−−−−−cout << "Introduzca numerador y denominador: ";Racional r2;leer(r2);escribir("R2: ", r2);//−−−−−−−−−−−−−−−−−−−−−−−−−Racional r3;sumar(r3 , r1 , r2);escribir("R3 (r1 + r2): ", r3);//−−−−−−−−−−−−−−−−−−−−−−−−−Racional r4;restar(r4, r3, r2);escribir("R4 (r3 - r2): ", r4);if ( ! igual(r1, r4)) {

cout << "Error en suma/resta"<<endl;}//−−−−−−−−−−−−−−−−−−−−−−−−−Racional r5;multiplicar(r5, r1, r2);escribir("R5 (r1 * r2): ", r5);//−−−−−−−−−−−−−−−−−−−−−−−−−Racional r6;dividir(r6 , r5 , r2);escribir("R6 (r5 / r2): ", r6);if ( ! igual(r1, r6)) {

cout << "Error en multiplicacion/division"<<endl;}//−−−−−−−−−−−−−−−−−−−−−−−−−

}� �3. Diseñe un módulo que proporcione soporte adecuado a la manipulación de polinomios de grados positivos

menores que 100. El módulo deberá definir el tipo Polinomio, así como las siguientes operaciones:

Solución: polinomios.hpp� �#ifndef polinomio_hpp_#define polinomio_hpp_#include <iostream>#include <array>namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−const double ERROR_PRECISION = 1e-6;const unsigned MAX = 100;typedef std::array<double , MAX> Datos;struct Polinomio {

unsigned mg; // maximo grado de l pol inomioDatos coef; // c o e f i c i e n t e s de l pol inomio ( ind i c e es e l exp . de l a X)

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double evaluar(const Polinomio& a, double x);

22

Page 23: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// Devuelve e l r e su l t ado de eva luar e l pol inomio (a )// para un va l o r de ( x ) e s p e c i f i c a do como parametrovoid derivar(Polinomio& r, const Polinomio& a);// Devuelve un pol inomio ( r ) que cont iene e l r e su l t ado de// c a l c u l a r l a der ivada de l pol inomio (a )void sumar(Polinomio& r, const Polinomio& a, const Polinomio& b);// Devuelve un pol inomio ( r ) que cont iene e l r e su l t ado de// sumar l o s pol inomios (a ) y ( b )void escribir(const Polinomio& a) ;// Muestra en pan t a l l a e l contenido de l pol inomio (a )void leer(Polinomio& a) ;// Lee de t e c l ado e l va l o r de l pol inomio (a )// Lee pares de c o e f i c i e n t e y grado hasta que e l c o e f i c i e n t e sea cero

}#endif� �

Solución: polinomios.cpp� �#include "polinomios.hpp"#include <iostream>#include <cassert>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−// Subprogramas Aux i l i a r e s//−−−−−−−−−−−−−−−−−−−−−−−−−// Valor ab so l u t o de un numeroinline double abs(double a) {

return (a >= 0) ? a : -a;}//−−−−−−−−−−−−−−−−−−−−−−−−−// Dos numeros r e a l e s son i g u a l e s s i l a d i s t anc i a que l o s// separa es l o su f i c i en t emen te pequenyainline bool iguales(double a, double b) {

return abs(a-b) <= ERROR_PRECISION;}//−−−−−−−−−−−−−−−−−−−−−−−−−double potencia(double base , unsigned exp){

double res = 1;for (unsigned i = 0; i < exp; ++i) {

res *= base;}return res;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void inicializar(Polinomio& a){

a.mg = 0;for (unsigned i = 0; i < a.coef.size (); ++i) {

a.coef[i] = 0.0;}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double evaluar(const Polinomio& a, double x){

// Devuelve e l r e su l t ado de eva luar e l pol inomio (a )// para un va l o r de ( x ) e s p e c i f i c a do como parametrodouble res = 0;for (unsigned i = 0; i <= a.mg; ++i) {

res += a.coef[i] * potencia(x, i);}

23

Page 24: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

return res;}void derivar(Polinomio& r, const Polinomio& a){

assert(&r != &a);// Devuelve un pol inomio ( r ) que cont iene e l r e su l t ado de// c a l c u l a r l a der ivada de l pol inomio (a )inicializar(r);for (unsigned i = 1; i <= a.mg; ++i) {

r.coef[i-1] = a.coef[i]*i;}r.mg = a.mg-1;

}void sumar(Polinomio& r, const Polinomio& a, const Polinomio& b){

assert ((&r != &a)&&(&r != &b));// Devuelve un pol inomio ( r ) que cont iene e l r e su l t ado de// sumar l o s pol inomios (a ) y ( b )inicializar(r);if (a.mg >= b.mg) {

r.mg = a.mg;} else {

r.mg = b.mg;}for (unsigned i = 0; i <= r.mg; ++i) {

r.coef[i] = a.coef[i] + b.coef[i];}

}void escribir(const Polinomio& a){

// Muestra en pan t a l l a e l contenido de l pol inomio (a )for (unsigned i = 0; i <= a.mg; ++i) {

if (! iguales(a.coef[i], 0.0)) {cout << (a.coef[i] > 0.0 ? " +" : " ")

<< a.coef[i] << " X^" << i ;}

}}void leer(Polinomio& a){

// Lee de t e c l ado e l va l o r de l pol inomio (a )// Lee pares de c o e f i c i e n t e y grado hasta que e l c o e f i c i e n t e sea ceroinicializar(a);double c;cout << "Introduzca coeficiente [0 -> fin]: ";cin >> c;while ( !cin.fail() && ! iguales(c, 0.0) ) {

unsigned e;cout << "Introduzca exponente: ";cin >> e;if ( ! cin.fail() && (e < a.coef.size ())) {

a.coef[e] = c;if (e > a.mg) {

a.mg = e;}

}cout << "Introduzca coeficiente [0 -> fin]: ";cin >> c;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include "polinomios.hpp"using namespace std;using namespace umalcc;

void escribir(const string& msj , const Polinomio& p){

cout << msj;

24

Page 25: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

escribir(p);cout << endl;

}

int main(){

Polinomio p1 , p2 , p3;leer(p1);escribir("P1: ", p1);cout << "P1(2) = " << evaluar(p1 , 2.0) << endl;derivar(p2 , p1);escribir("P2: ", p2);sumar(p3 , p1 , p2);escribir("P3: ", p3);

}� �Tema 2.2: Tipos Abstractos de Datos

Diseñe e implemente los siguientes TADs, dentro del espacio de nombres umalcc, así como programas deutilización que permitan comprobar su funcionamiento.

1. TAD número complejo que defina los siguientes métodos públicos:

Solución: complejo.hpp� �#ifndef complejos_hpp_#define complejos_hpp_namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−const double ERROR_PRECISION = 1e-6 ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−class Complejo {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Métodos Púb l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Complejo () ; // Constructor por Defecto//−−−−−−−−−−−−−−−−−−−−−−−−−−−−double parte_real () const ;// devue l ve l a par te r e a l d e l numero complejo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−double parte_imag () const ;// devue l ve l a par te imaginaria de l numero complejo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void sumar(const Complejo& a, const Complejo& b) ;// asigna a l numero complejo ( ac tua l ) e l r e su l t ado de// sumar l o s numeros complejos (a ) y ( b ) .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void restar(const Complejo& a, const Complejo& b) ;// asigna a l numero complejo ( ac tua l ) e l r e su l t ado de// r e s t a r l o s numeros complejos (a ) y ( b ) .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void multiplicar(const Complejo& a, const Complejo& b) ;// asigna a l numero complejo ( ac tua l ) e l r e su l t ado de// mu l t i p l i c a r l o s numeros complejos (a ) y ( b ) .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void dividir(const Complejo& a, const Complejo& b) ;// asigna a l numero complejo ( ac tua l ) e l r e su l t ado de// d i v i d i r l o s numeros complejos (a ) y ( b ) .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool igual(const Complejo& b) const ;// Devuelve t rue s i e l numero complejo ( ac tua l ) es// i g u a l a l numero complejo ( b )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir () const ;// muestra en pan t a l l a e l numero complejo ( ac tua l )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer() ;// l e e de t e c l ado e l va l o r de l numero complejo ( ac tua l ) .// l e e l a par te r e a l y l a par te imaginaria de l numero

25

Page 26: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−private:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double real ; // par te r e a l d e l numero complejodouble imag ; // par te imaginaria de l numero complejo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

} ;}#endif� �

Solución: complejo.cpp� �#include "complejos.hpp"#include <iostream>using namespace std ;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Subprogramas Aux i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// cuadrado de un numero (a^2)inline double sq(double a){

return a*a ;}//−−−−−−−−−−−−−−−−−−−−−−−−−// Valor ab so l u t o de un numeroinline double abs(double a){

return (a >= 0) ? a : -a ;}//−−−−−−−−−−−−−−−−−−−−−−−−−// Dos numeros r e a l e s son i g u a l e s s i l a d i s t anc i a que l o s// separa es l o su f i c i en t emen te pequenyainline bool iguales(double a, double b){

return abs(a-b) <= ERROR_PRECISION ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Métodos Púb l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Complejo :: Complejo () // Constructor por Defecto

: real (0.0), imag (0.0) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// devue l ve l a par te r e a l d e l numero complejodouble Complejo :: parte_real () const{

return real ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// devue l ve l a par te imaginaria de l numero complejodouble Complejo :: parte_imag () const{

return imag ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// asigna a l numero complejo ( ac tua l ) e l r e su l t ado de// sumar l o s numeros complejos (a ) y ( b ) .void Complejo ::sumar(const Complejo& a, const Complejo& b){

real = a.real + b.real ;

26

Page 27: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

imag = a.imag + b.imag ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// asigna a l numero complejo ( ac tua l ) e l r e su l t ado de// r e s t a r l o s numeros complejos (a ) y ( b ) .void Complejo :: restar(const Complejo& a, const Complejo& b){

real = a.real - b.real ;imag = a.imag - b.imag ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// asigna a l numero complejo ( ac tua l ) e l r e su l t ado de// mu l t i p l i c a r l o s numeros complejos (a ) y ( b ) .void Complejo :: multiplicar(const Complejo& a, const Complejo& b){

double p_real = (a.real * b.real) - (a.imag * b.imag) ;double p_imag = (a.real * b.imag) + (a.imag * b.real) ;real = p_real;imag = p_imag;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// asigna a l numero complejo ( ac tua l ) e l r e su l t ado de// d i v i d i r l o s numeros complejos (a ) y ( b ) .void Complejo :: dividir(const Complejo& a, const Complejo& b){

double divisor = sq(b.real) + sq(b.imag) ;if (iguales (0.0, divisor )) {

real = 0.0 ;imag = 0.0 ;

} else {double p_real = ((a.real * b.real) + (a.imag * b.imag)) / divisor ;double p_imag = ((a.imag * b.real) - (a.real * b.imag)) / divisor ;real = p_real;imag = p_imag;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve t rue s i e l numero complejo ( ac tua l ) es// i g u a l a l numero complejo ( b )bool Complejo ::igual(const Complejo& b) const{

return iguales(real , b.real) && iguales(imag , b.imag) ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// muestra en pan t a l l a e l numero complejo ( ac tua l )void Complejo :: escribir () const{

cout << "{ " << real << ", " << imag << " }" ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e de t e c l ado e l va l o r de l numero complejo ( ac tua l ) .// l e e l a par te r e a l y l a par te imaginaria de l numerovoid Complejo ::leer(){

cin >> real >> imag ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include "complejos.hpp"using namespace std ;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(Complejo& c){

cout << "Introduzca un numero complejo { real img }: " ;c.leer() ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_suma(const Complejo& c1, const Complejo& c2)

27

Page 28: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{Complejo c0 ;c0.sumar(c1, c2) ;c1.escribir () ;cout <<" + " ;c2.escribir () ;cout <<" = " ;c0.escribir () ;cout << endl ;Complejo aux ;aux.restar(c0 , c2) ;if ( ! c1.igual(aux)) {

cout << "Error en operaciones de suma/resta"<< endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_resta(const Complejo& c1, const Complejo& c2){

Complejo c0 ;c0.restar(c1, c2) ;c1.escribir () ;cout <<" - " ;c2.escribir () ;cout <<" = " ;c0.escribir () ;cout << endl ;Complejo aux ;aux.sumar(c0, c2) ;if ( ! c1.igual(aux)) {

cout << "Error en operaciones de suma/resta"<< endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_mult(const Complejo& c1, const Complejo& c2){

Complejo c0 ;c0.multiplicar(c1 , c2) ;c1.escribir () ;cout <<" * " ;c2.escribir () ;cout <<" = " ;c0.escribir () ;cout << endl ;Complejo aux ;aux.dividir(c0, c2) ;if ( ! c1.igual(aux)) {

cout << "Error en operaciones de mult/div"<< endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_div(const Complejo& c1 , const Complejo& c2){

Complejo c0 ;c0.dividir(c1 , c2) ;c1.escribir () ;cout <<" / " ;c2.escribir () ;cout <<" = " ;c0.escribir () ;cout << endl ;Complejo aux ;aux.multiplicar(c0, c2) ;if ( ! c1.igual(aux)) {

cout << "Error en operaciones de mult/div"<< endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Complejo c1 , c2 ;leer(c1) ;leer(c2) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−prueba_suma(c1, c2) ;

28

Page 29: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

prueba_resta(c1 , c2) ;prueba_mult(c1, c2) ;prueba_div(c1 , c2) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �2. TAD polinomio de grados positivos menores que 100 que defina los siguientes métodos públicos:

Solución: polinomios.hpp� �#ifndef polinomios_hpp_#define polinomios_hpp_#include <array>namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−const double ERROR_PRECISION = 1e-6;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−class Polinomio {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Def in idos automaticamente por e l compilador//−−−−−−−−−−−−−−−−−−−−−−−−−//~Polinomio ( ) ;//Polinomio ( const Polinomio& p ) ;//Polinomio& operator=(const Polinomio& p ) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−Polinomio ();unsigned max_grado () const;// Devuelve e l mayor grado de l pol inomio ac tua l// cuyo c o e f i c i e n t e es d i s t i n t o de cerovoid poner(unsigned e, double c);// Asigna e l c o e f i c i e n t e ( c ) a l termino de grado ( e )// de l pol inomio ac tua ldouble obtener(unsigned e) const;// Devuelve e l c o e f i c i e n t e correspond ien te a l// termino de grado ( e ) de l pol inomio ac tua ldouble evaluar(double x) const;// Devuelve e l r e su l t ado de eva luar e l pol inomio ac tua l// para un va l o r de ( x ) e s p e c i f i c a do como parametrovoid derivar(const Polinomio& a);// Asigna a l pol inomio ac tua l e l r e su l t ado de// c a l c u l a r l a der ivada de l pol inomio (a )void sumar(const Polinomio& a, const Polinomio& b);// Asigna a l pol inomio ac tua l e l r e su l t ado de// sumar l o s pol inomios (a ) y ( b )void escribir () const;// Muestra en pan t a l l a e l contenido de l pol inomio ac tua lvoid leer ();// Lee de t e c l ado e l va l o r de l pol inomio ac tua l// Lee pares de c o e f i c i e n t e y grado hasta que e l c o e f i c i e n t e sea cero//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Ctes y Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−static const unsigned MAX = 100;typedef std::array<double , MAX> Datos;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void inicializar ();//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned mg; // maximo grado de l pol inomioDatos coef; // c o e f i c i e n t e s de l pol inomio ( ind i c e es e l exp de l a X)//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}

29

Page 30: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#endif� �Solución: polinomios.cpp� �

#include "polinomios.hpp"#include <iostream>#include <cassert>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Subprogramas Aux i l i a r e s −−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Valor ab so l u t o de un numeroinline double abs(double a) {

return (a >= 0) ? a : -a;}//−−−−−−−−−−−−−−−−−−−−−−−−−// Dos numeros r e a l e s son i g u a l e s s i l a d i s t anc i a que l o s// separa es l o su f i c i en t emen te pequenyainline bool iguales(double a, double b) {

return abs(a-b) <= ERROR_PRECISION;}//−−−−−−−−−−−−−−−−−−−−−−−−−double potencia(double base , unsigned exp){

double res = 1;for (unsigned i = 0; i < exp; ++i) {

res *= base;}return res;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

Polinomio :: Polinomio (): mg(0), coef()

{inicializar ();

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned Polinomio :: max_grado () const{

return mg;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: poner(unsigned e, double c){

if (e < coef.size ()) {coef[e] = c;if ((e > mg) && !iguales(c, 0.0)) {

mg = e;}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Polinomio :: obtener(unsigned e) const{

double res;if (e < mg) {

res = coef[e];} else {

res = 0.0;}return res;

}

30

Page 31: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Polinomio :: evaluar(double x) const{

double res = 0;for (unsigned i = 0; i <= mg; ++i) {

res += coef[i] * potencia(x, i);}return res;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: derivar(const Polinomio& a){

assert(this != &a);inicializar ();for (unsigned i = 1; i <= a.mg; ++i) {

coef[i-1] = a.coef[i]*i;}mg = a.mg-1;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: sumar(const Polinomio& a, const Polinomio& b){

assert ((this != &a)&&(this != &b));inicializar ();if (a.mg >= b.mg) {

mg = a.mg;} else {

mg = b.mg;}for (unsigned i = 0; i <= mg; ++i) {

coef[i] = a.coef[i] + b.coef[i];}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: escribir () const{

for (unsigned i = 0; i <= mg; ++i) {if (! iguales(coef[i], 0.0)) {

cout << (coef[i] > 0.0 ? " +" : " ")<< coef[i] << " X^" << i ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio ::leer(){

inicializar ();double c;cout << "Introduzca coeficiente [0 -> fin]: ";cin >> c;while ( !cin.fail() && ! iguales(c, 0.0) ) {

unsigned e;cout << "Introduzca exponente: ";cin >> e;if ( ! cin.fail() && (e < coef.size ())) {

coef[e] = c;if (e > mg) {

mg = e;}

}cout << "Introduzca coeficiente [0 -> fin]: ";cin >> c;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: inicializar (){

mg = 0;for (unsigned i = 0; i < coef.size (); ++i) {

coef[i] = 0.0;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �31

Page 32: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: main.cpp� �#include <iostream>#include <string>#include "polinomios.hpp"using namespace std;using namespace umalcc;

void escribir(const string& msj , const Polinomio& p){

cout << msj;p.escribir ();cout << endl;

}

int main(){

Polinomio p1 , p2 , p3;p1.leer ();escribir("P1: ", p1);cout << "P1(2) = " << p1.evaluar (2.0) << endl;p2.derivar(p1);escribir("P2: ", p2);p3.sumar(p1, p2);escribir("P3: ", p3);p1 = p3;escribir("P1: ", p1);

}� �3. Un conjunto de números enteros es una colección de elementos homogéneos (números enteros) sin repetición

y ninguna relación de orden entre ellos (no ordenados y sin repetición). Defina un TAD Conjunto denúmeros enteros que defina los siguientes métodos públicos:

Solución: conjuntos.hpp� �#ifndef conjuntos_hpp_#define conjuntos_hpp_#include <iostream>#include <array>namespace umalcc {

class Conjunto {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Generados automaticamente por e l compilador//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//~Conjunto ( ) ;//Conjunto ( const Conjunto& c ) ;//Conjunto& operator=(const Conjunto& c ) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Conjunto ();// Constructor por Defecto : conjunto vac iovoid clear ();// Elimina todos l o s e lementos de l conjunto ac tua l ( queda vac io )bool es_vacio () const;// Devuelve t rue s i e l conjunto ac tua l e s ta vac iovoid incluir(int e);// Inc luye e l elemento ( e ) en e l conjunto ac tua lvoid eliminar(int e);// Elimina e l elemento ( e ) de l conjunto ac tua lbool pertenece(int e) const;// Devuelve t rue s i e l e lemento ( e ) per tenece a l conjunto ac tua lbool es_subconjunto(const Conjunto& a) const;// Devuelve t rue s i e l conjunto ac tua l es subconjunto de l conjunto (a )void union_conj(const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ac tua l e l r e su l t ado de// l a union de l o s conjuntos (a ) y ( b )void interseccion(const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ac tua l e l r e su l t ado de// l a i n t e r s e c c i on de l o s conjuntos (a ) y ( b )

32

Page 33: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void diferencia(const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ac tua l e l r e su l t ado de// l a d i f e r en c i a de l o s conjuntos (a ) y ( b )void diferencia_simetrica(const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ac tua l e l r e su l t ado de// l a d i f e r en c i a s ime t r i ca de l o s conjuntos (a ) y ( b )void escribir () const;// Muestra en pan t a l l a e l contenido de l conjunto ac tua lvoid leer ();// Lee de t e c l ado e l va l o r de l conjunto actua l ,

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Ctes y Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−static const unsigned MAX = 100;typedef std::array<int , MAX> Datos;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void anyadir(int e) ;void quitar(unsigned i) ;unsigned buscar(int e) const ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned sz; // numero de elementos de l conjuntoDatos dat; // componentes de l conjunto//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

Solución: conjuntos.cpp� �#include "conjuntos.hpp"#include <iostream>#include <array>#include <cassert>using namespace std;namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Conjunto :: Conjunto () : sz(0), dat() {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto ::clear(){

sz = 0;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Conjunto :: es_vacio () const{

return (sz == 0);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: incluir(int e){

if (! pertenece(e)) {anyadir(e);

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: eliminar(int e){

quitar(buscar(e));}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Conjunto :: pertenece(int e) const{

return (buscar(e) < sz);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Conjunto :: es_subconjunto(const Conjunto& a) const

33

Page 34: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{// es subconjunto s i todos l o s e lementos de l conjunto ac tua l// pertenecen tambien a l conjunto e s p e c i f i c a do como parametrounsigned i = 0;while ((i < sz) && a.pertenece(dat[i])) {

++i;}return (i == sz);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: union_conj(const Conjunto& a, const Conjunto& b){

assert ((this != &a)&&(this != &b));clear ();for (unsigned i = 0; i < a.sz; ++i) {

anyadir(a.dat[i]);}for (unsigned i = 0; i < b.sz; ++i) {

incluir(b.dat[i]);}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: interseccion(const Conjunto& a, const Conjunto& b){

assert ((this != &a)&&(this != &b));clear ();for (unsigned i = 0; i < a.sz; ++i) {

if (b.pertenece(a.dat[i])) {anyadir(a.dat[i]);

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: diferencia(const Conjunto& a, const Conjunto& b){

assert ((this != &a)&&(this != &b));clear ();for (unsigned i = 0; i < a.sz; ++i) {

if (! b.pertenece(a.dat[i])) {anyadir(a.dat[i]);

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: diferencia_simetrica(const Conjunto& a, const Conjunto& b){

Conjunto a_b , b_a;a_b.diferencia(a, b);b_a.diferencia(b, a);union_conj(a_b , b_a);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: escribir () const{

cout << "{ ";for (unsigned i = 0; i < sz; ++i) {

cout << dat[i] << " ";}cout << "}";

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto ::leer(){

clear ();int e;cin >> e ;while (e != 0) {

incluir(e);cin >> e ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

34

Page 35: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void Conjunto :: anyadir(int e) {if (sz < dat.size ()) {

dat[sz] = e;++sz;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: quitar(unsigned i) {

// Elimina un elemento asignando e l u l t imo elemento a l a// pos i c ion e s p e c i f i c a daif (i < sz) {

if (i < sz-1) {dat[i] = dat[sz-1];

}--sz;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned Conjunto :: buscar(int e) const {

unsigned i = 0;while ((i < sz)&&(e != dat[i])) {

++i;}return i;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include "conjuntos.hpp"using namespace std;using namespace umalcc;

void escribir(const string& msj , const Conjunto& c){

cout << msj;c.escribir ();cout << endl;

}int main(){

Conjunto c1 , c2 , c3;cout << "Introduzca elementos del conjunto: [0 -> fin]: ";c1.leer ();escribir("C1: ", c1);cout << "Introduzca elementos del conjunto: [0 -> fin]: ";c2.leer ();escribir("C2: ", c2);cout << "Es subconjunto: " << boolalpha << c1.es_subconjunto(c2) << endl;c3.union_conj(c1, c2);escribir("Union: ", c3);c3.interseccion(c1 , c2);escribir("Interseccion: ", c3);c3.diferencia(c1, c2);escribir("Diferencia: ", c3);c3.diferencia_simetrica(c1 , c2);escribir("Diferencia Simetrica: ", c3);

}� �4. TAD matriz matemática de números reales (de dimensiones menores de N ×N) que defina los siguientes

métodos públicos:

Solución: matriz.hpp� �#ifndef matriz_hpp_#define matriz_hpp_

35

Page 36: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#include <array>namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−const double ERROR_PRECISION = 1e-6;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−class Matriz {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Def in idos automaticamente por e l compilador//−−−−−−−−−−−−−−−−−−−−−−−−−//~Matriz ( ) ;//Matriz ( const Matriz& m) ;//Matriz& operator=(const Matriz& m) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−Matriz () ;// Constructor por Defecto : matriz vac ia//−−−−−−−−−−−−−−−−−−−−−−−−−−−−Matriz(unsigned nf , unsigned nc);// Constructor e s p e c i f i c o : crea matriz de ( n f i l s ) x ( nco l s ) con va l o r e s 0//−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned nfils() const ;// Devuelve e l numero de f i l a s de l a matriz a c tua l//−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned ncols() const ;// Devuelve e l numero de columnas de l a matriz ac tua l//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void clear(unsigned nf , unsigned nc);// Elimina todos l o s e lementos de l a matriz ac tua l , y as igna// a l a matriz a c tua l una matriz de ( n f i l s ) x ( nco l s ) con va l o r e s 0//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void poner(unsigned f, unsigned c, double val) ;// PRECOND: (0 <= f && f < n f i l s ( ) && 0 <= c && c < nco l s ( ) )// Asigna e l va l o r ( va l ) a l elemento de l a f i l a ( f )// y columna ( c ) de l a matriz a c tua l//−−−−−−−−−−−−−−−−−−−−−−−−−−−−double obtener(unsigned f, unsigned c) const ;// PRECOND: ( f < n f i l s ( ) && c < nco l s ( ) )// Devuelve e l va l o r de l elemento de l a f i l a ( f )// y columna ( c ) de l a matriz a c tua l//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void sumar(const Matriz& m1, const Matriz& m2);// Asigna a l a matriz a c tua l e l r e su l t ado de// sumar l a s matr ices (a ) y ( b )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void restar(const Matriz& m1, const Matriz& m2);// Asigna a l a matriz a c tua l e l r e su l t ado de// r e s t a r l a s matr ices (a ) y ( b )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void multiplicar(const Matriz& m1 , const Matriz& m2);// Asigna a l a matriz a c tua l e l r e su l t ado de// mu l t i p l i c a r l a s matr ices (a ) y ( b )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir () const;// Muestra en pan t a l l a e l contenido de l a matriz a c tua l//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer ();// Lee de t e c l ado e l va l o r de l a matriz ac tua l ,// Lee n f i l s , nco l s y l o s va l o r e s de l o s e lementos//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Ctes y Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−static const unsigned MAX = 10;typedef std::array<double , MAX> Fila;typedef std::array<Fila , MAX> Datos; // matriz maxima de 10x10//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned nfilas;unsigned ncolumnas;Datos dat;

36

Page 37: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−};

}#endif� �

Solución: matriz.cpp� �#include "matriz.hpp"#include <iostream>#include <iomanip>#include <cassert>using namespace std;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Matriz :: Matriz () : nfilas (0), ncolumnas (0), dat() {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Matriz :: Matriz(unsigned nf , unsigned nc)

: nfilas (0), ncolumnas (0){

if ((nf < dat.size ())&&(nc < dat[0].size ())) {nfilas = nf;ncolumnas = nc;for (unsigned f = 0; f < nf; ++f) {

for (unsigned c = 0; c < nc; ++c) {dat[f][c] = 0.0;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned Matriz ::nfils() const{

return nfilas;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned Matriz ::ncols() const{

return ncolumnas;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: clear(unsigned nf , unsigned nc){

if ((nf < dat.size ())&&(nc < dat[0].size ())) {nfilas = nf;ncolumnas = nc;for (unsigned f = 0; f < nf; ++f) {

for (unsigned c = 0; c < nc; ++c) {dat[f][c] = 0.0;

}}

} else {nfilas = 0;ncolumnas = 0;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: poner(unsigned f, unsigned c, double val){

assert(f < nfils() && c < ncols ());dat[f][c] = val;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Matriz :: obtener(unsigned f, unsigned c) const{

assert(f < nfils() && c < ncols ());return dat[f][c];

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: sumar(const Matriz& m1, const Matriz& m2)

37

Page 38: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{assert ((this != &m1)&&(this != &m2));if ((m1.nfils() != m2.nfils ())||(m1.ncols() != m2.ncols ())) {

clear(0, 0);} else {

nfilas = m1.nfils ();ncolumnas = m1.ncols ();for (unsigned f = 0; f < nfils (); ++f) {

for (unsigned c = 0; c < ncols (); ++c) {poner(f,c, m1.obtener(f,c) + m2.obtener(f,c));

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: restar(const Matriz& m1, const Matriz& m2){

assert ((this != &m1)&&(this != &m2));if ((m1.nfils() != m2.nfils ())||(m1.ncols() != m2.ncols ())) {

clear(0, 0);} else {

nfilas = m1.nfils ();ncolumnas = m1.ncols ();for (unsigned f = 0; f < nfils (); ++f) {

for (unsigned c = 0; c < ncols (); ++c) {poner(f,c, m1.obtener(f,c) - m2.obtener(f,c));

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: multiplicar(const Matriz& m1 , const Matriz& m2){

assert ((this != &m1)&&(this != &m2));if ((m1.ncols() != m2.nfils ())) {

clear(0, 0);} else {

nfilas = m1.nfils ();ncolumnas = m2.ncols ();for (unsigned f = 0; f < nfils (); ++f) {

for (unsigned c = 0; c < ncols (); ++c) {double suma = 0.0;for (unsigned k = 0; k < m1.ncols (); ++k) {

suma += m1.obtener(f,k) * m2.obtener(k,c);}poner(f,c, suma);

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: escribir () const{

cout << std:: setprecision (4);for (unsigned f = 0; f < nfils (); ++f) {

for (unsigned c = 0; c < ncols (); ++c) {cout << std::setw (6) << obtener(f,c) << " ";

}cout << std::endl;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz ::leer(){

unsigned nf , nc;cin >> nf >> nc; // l e e numero de f i l a s y columnasif ((nf > dat.size ())||(nc > dat[0].size ())) {

clear(0, 0);} else {

nfilas = nf;ncolumnas = nc;for (unsigned f = 0; f < nfils (); ++f) {

for (unsigned c = 0; c < ncols (); ++c) {double x;

38

Page 39: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cin >> x; // l e e cada elemento de l a matrizponer(f,c, x);

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include "matriz.hpp"using namespace std;using namespace umalcc;

int main(){

Matriz m1;cout << "Introduzca dimensiones y valores de la matriz: " ;m1.leer ();

Matriz m2;cout << "Introduzca dimensiones y valores de la matriz: " ;m2.leer ();

Matriz m3;m3.sumar(m1, m2);cout << "Suma: " << endl;m3.escribir ();

Matriz m4;m4.restar(m3, m2);cout << "Resta: " << endl;m4.escribir ();

Matriz m5;m5.multiplicar(m1 , m2);cout << "Multiplicacion: " << endl;m5.escribir ();

}� �5. Un TAD Lista de números enteros es una secuencia de elementos homogéneos (números enteros), donde

cada elemento ocupa una determinada posición dentro de la secuencia, de tal forma que se puede accedera cada elemento por la posición donde se encuentra. Así mismo, también es posible insertar y eliminarelementos de la secuencia en la posición indicada, manteniendo el mismo orden posicional de los elementosen la secuencia. Diseñe e implemente el TAD que proporcione los siguientes métodos públicos:

Solución: listaint.hpp� �#ifndef listaint_hpp_#define listaint_hpp_#include <array>namespace umalcc {

class ListaInt {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Métodos Púb l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// ~L i s t a In t ( ) ; // Destructor Automático//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−ListaInt () ;ListaInt(const ListaInt& o) ;ListaInt& operator = (const ListaInt& o) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool llena() const ;

// Devuelve t rue s i e l numero de elementos almacenados// a lcanza l a capacidad maxima de almacenamiento

39

Page 40: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

int size() const ;// Devuelve e l numero de elementos almacenados

void clear() ;// Elimina todos l o s e lementos de l a l i s t a ac tua l ( queda vac ia )

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar(int pos , int dato) ;

// PRECOND: ( ! l l e n a () && pos >= 0 && pos <= s i z e ( ) )// Inse r ta ( dato ) en l a l i s t a ac tua l en l a pos i c ion ( pos )

void eliminar(int pos) ;// PRECOND: ( pos >= 0 && pos < s i z e ( ) )// Elimina de l a l i s t a ac tua l e l e lemento que ocupa l a pos i c ion ( pos )

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int acceder(int pos) const ;

// PRECOND: ( pos >= 0 && pos < s i z e ( ) )// Devuelve e l elemento de l a l i s t a ac tua l que ocupa l a pos i c ion ( pos )

void modificar(int pos , int dato);// PRECOND: ( pos >= 0 && pos < s i z e ( ) )// Asigna ( dato ) a l elemento de l a l i s t a ac tua l que ocupa l a pos i c ion ( pos )

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−private:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Ctes y Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−static const int MAX = 100;typedef std::array<int , MAX> Datos;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void abrir_hueco(int pos) ;void cerrar_hueco(int pos) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int sz; // numero de elementos de l a l i s t aDatos v; // cont iene l o s e lementos de l a l i s t a//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

Solución: listaint.cpp� �#include "listaint.hpp"#include <cassert>namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Métodos Púb l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// L i s t a In t : :~ L i s t a In t ( ) {} // Destructor Automático//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−ListaInt :: ListaInt () : sz(0), v() {} // Constructor por Defecto//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−ListaInt :: ListaInt(const ListaInt& o) // Constructor de Copia

: sz(o.sz), v(){

for (int i = 0; i < sz; ++i) {v[i] = o.v[i] ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−ListaInt& ListaInt :: operator = (const ListaInt& o) // Op. de Asignación{

if (this != &o) {sz = o.sz ;for (int i = 0; i < sz; ++i) {

v[i] = o.v[i] ;}

}return *this ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool ListaInt ::llena() const{

40

Page 41: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

return sz == int(v.size ());}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int ListaInt ::size() const{

return sz ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void ListaInt ::clear(){

sz = 0 ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void ListaInt :: insertar(int pos , int dato){

assert( ! llena () && pos >= 0 && pos <= size ()) ;abrir_hueco(pos) ;v[pos] = dato ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void ListaInt :: eliminar(int pos){

assert(pos >= 0 && pos < size ()) ;cerrar_hueco(pos) ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int ListaInt :: acceder(int pos) const{

assert(pos >= 0 && pos < size ()) ;return v[pos] ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void ListaInt :: modificar(int pos , int dato){

assert(pos >= 0 && pos < size ()) ;v[pos] = dato;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void ListaInt :: abrir_hueco(int pos){

assert(sz < int(v.size ())) ;for (int i = sz; i > pos; --i) {

v[i] = v[i-1];}++sz; // Ahora hay un elemento más

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void ListaInt :: cerrar_hueco(int pos){

assert(sz > 0) ;--sz; // Ahora hay un elemento menosfor (int i = pos; i < sz; ++i) {

v[i] = v[i+1];}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include <cctype>#include <cassert>#include "listaint.hpp"using namespace std ;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_pos(int& pos , int limite){

assert(limite > 0);do {

41

Page 42: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "Introduzca posicion ( < " << limite << " ): " ;cin >> pos;

} while (pos < 0 || pos >= limite );}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_dato(int& dato){

cout << "Introduzca un dato: " ;cin >> dato;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(ListaInt& lista){

int dato ;lista.clear() ;cout << "Introduzca datos (0 -> FIN): " << endl ;cin >> dato ;while ((dato != 0)&&( ! lista.llena ())) {

lista.insertar(lista.size(), dato) ;cin >> dato ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir(const ListaInt& lista){

cout << "Lista: " ;for (int i = 0 ; i < lista.size() ; ++i) {

cout << lista.acceder(i) << " " ;}cout << endl ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void prueba_asg(const ListaInt& lista){

cout << "Constructor de Copia" << endl ;ListaInt lst(lista) ;escribir(lst) ;cout << "Operador de Asignacion" << endl ;lst = lista ;escribir(lst) ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op ;cout << endl ;cout << "X. Fin" << endl ;cout << "A. Leer Lista" << endl ;cout << "B. Borrar Lista" << endl ;cout << "C. Insertar Posicion" << endl ;cout << "D. Eliminar Posicion" << endl ;cout << "E. Acceder Posicion" << endl ;cout << "F. Modificar Posicion" << endl ;cout << "G. Prueba Copia y Asignacion" << endl ;do {

cout << endl << " Opcion: " ;cin >> op ;op = char(toupper(op)) ;

} while (!((op == 'X')||((op >= 'A')&&(op <= 'G')))) ;cout << endl ;return op ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

ListaInt lista ;int dato ;int pos ;char op = ' ' ;do {

op = menu() ;switch (op) {case 'A':

leer(lista) ;

42

Page 43: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

escribir(lista) ;break ;

case 'B':lista.clear() ;escribir(lista) ;break ;

case 'C':if (lista.llena ()) {

cout << "Error: Lista llena" << endl ;} else {

leer_pos(pos , lista.size()+1) ;leer_dato(dato) ;lista.insertar(pos , dato) ;escribir(lista) ;

}break ;

case 'D':if (lista.size() == 0) {

cout << "Error: lista vacia" << endl ;} else {

leer_pos(pos , lista.size ()) ;lista.eliminar(pos) ;escribir(lista) ;

}break ;

case 'E':if (lista.size() == 0) {

cout << "Error: lista vacia" << endl ;} else {

leer_pos(pos , lista.size ()) ;cout << "Lista[" << pos << "]: " << lista.acceder(pos) << endl ;escribir(lista) ;

}break ;

case 'F':if (lista.size() == 0) {

cout << "Error: lista vacia" << endl ;} else {

leer_pos(pos , lista.size ()) ;leer_dato(dato) ;lista.modificar(pos , dato) ;escribir(lista) ;

}break ;

case 'G':prueba_asg(lista) ;break ;

}} while (op != 'X') ;

}� �

43

Page 44: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Tema 3: Gestión de Memoria Dinámica

Tema 3.1: Listas Enlazadas1. Diseñe un módulo (programación modular) que proporcione soporte adecuado a la manipulación de listas

enlazadas en memoria dinámica (véase siguiente figura). El módulo deberá definir el tipo PNodo como unpuntero a un registro en memoria dinámica de tipo Nodo que contiene un enlace al siguiente nodo, asícomo un dato de tipo int. Además, el módulo deberá definir los siguientes subprogramas. Diseñe tambiénun módulo principal que permita comprobar la corrección del módulo lista implementado.

lista: −−→◦ −−−−→◦0

−−−−→◦1

�2

Solución: lista.hpp� �#ifndef lista_hpp_#define lista_hpp_namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Nodo ; // Declaración ade lantada de l t i p o incompleto Nodotypedef Nodo* PNodo ; // Def in i c ión de t i p o Puntero a t i p o incompleto Nodostruct Nodo { // Def in i c ión de l t i p o Nodo

PNodo sig ; // Enlace a l a s i g u i e n t e e s t ruc tu ra dinámicaint dato ; // Dato almacenado en l a l i s t a

} ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void inicializa(PNodo& lista) ;// I n i c i a l i z a ( l i s t a ) a una l i s t a vac ia//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void destruir(PNodo& lista) ;// Destruye todos l o s e lementos de l a l i s t a , l i b e rando// todos l o s nodos de memoria dinamica . ( l i s t a ) queda vac ia//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_principio(PNodo& lista , int dt) ;// Inse r ta un elemento a l p r i n c i p i o de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_final(PNodo& lista , int dt) ;// Inse r ta un elemento a l f i n a l de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo situar(PNodo lista , int pos) ;// Devuelve un puntero a l nodo que se encuentra en l a pos i c ion// indicada por ( pos ) . La pos i c ion cero (0) ind i ca e l primer nodo .// Si e l nodo no ex i s t e , entonces devue l ve NULL//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_pos(PNodo& lista , int pos , int dt) ;// Inse r ta en ( l i s t a ) un elemento en l a pos i c ion indicada por ( pos )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_primero(PNodo& lista) ;// Elimina e l primer elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_ultimo(PNodo& lista) ;// Elimina e l u l t imo elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_pos(PNodo& lista , int pos) ;// Elimina de ( l i s t a ) e l e lemento de l a pos i c ion indicada por ( pos ) ,// s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo duplicar(PNodo lista) ;// Devuelve un puntero a una nueva l i s t a r e su l t ado de dup l i c a r en// memoria dinamica l a l i s t a r e c i b i d a como parametro//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir(PNodo lista) ;// Muestra en pan t a l l a e l contenido de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo leer() ;// Devuelve una l i s t a con l o s numeros l e i d o s de t e c l ado ( en e l mismo// orden que son in t roduc ido s ) hasta que l e a e l numero 0 ( que no es// in t roduc ido )

44

Page 45: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo buscar(PNodo lista , int dt) ;// Devuelve un puntero a l nodo que cont iene e l elemento// i g u a l a ( dt ) . Si no se encuentra , entonces devue l ve NULL//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_ord(PNodo& lista , int dt) ;// Inse r ta un elemento de forma ordenada en ( l i s t a ) , que debe e s t a r ordenada//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_elem(PNodo& lista , int dt) ;// Elimina de ( l i s t a ) e l primer elemento i g u a l a ( dt ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_mayor(PNodo& lista) ;// Elimina e l mayor elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void purgar(PNodo& lista , int dt) ;// Elimina de ( l i s t a ) todos l o s e lementos que sean i g u a l e s a ( dt ) ,// s i e x i s t en//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}#endif� �

Solución: lista.cpp� �#include "lista.hpp"#include <iostream>#include <cstddef>#include <cassert>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// I n i c i a l i z a ( l i s t a ) a una l i s t a vac ia// sera inse r tado en l a l i s t a )void inicializa(PNodo& lista){

lista = NULL ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Destruye todos l o s e lementos de l a l i s t a , l i b e rando// todos l o s nodos de memoria dinamica . ( l i s t a ) queda vac iavoid destruir(PNodo& lista){

while (lista != NULL) {PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento a l p r i n c i p i o de ( l i s t a )void insertar_principio(PNodo& lista , int dt){

PNodo ptr = new Nodo ;ptr->dato = dt ;ptr->sig = lista ;lista = ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento a l f i n a l de ( l i s t a )void insertar_final(PNodo& lista , int dt){

PNodo ptr = new Nodo ;ptr->dato = dt ;ptr->sig = NULL ;if (lista == NULL) {

lista = ptr ;} else {

45

Page 46: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

PNodo act = lista ;while (act->sig != NULL) {

act = act->sig ;}act->sig = ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que se encuentra en l a pos i c ion// indicada por ( pos ) . La pos i c ion cero (0) ind i ca e l primer nodo .// Si e l nodo no ex i s t e , entonces devue l ve NULLPNodo situar(PNodo lista , int pos){

PNodo ptr = lista;while ((ptr != NULL)&&(pos > 0)) {

ptr = ptr->sig;--pos;

}return ptr;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta en ( l i s t a ) un elemento en l a pos i c ion indicada por ( pos )void insertar_pos(PNodo& lista , int pos , int dt){

if (pos < 1) {PNodo ptr = new Nodo ;ptr->dato = dt ;ptr->sig = lista ;lista = ptr ;

} else {PNodo ant = situar(lista , pos - 1);if (ant != NULL) {

PNodo ptr = new Nodo ;ptr->dato = dt ;ptr->sig = ant->sig ;ant->sig = ptr ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l primer elemento de ( l i s t a ) , s i e x i s t evoid eliminar_primero(PNodo& lista){

if (lista != NULL) {PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l u l t imo elemento de ( l i s t a ) , s i e x i s t evoid eliminar_ultimo(PNodo& lista){

if (lista != NULL) {if (lista->sig == NULL) {

delete lista ;lista = NULL ;

} else {PNodo ant = lista ;PNodo act = ant->sig ;while (act->sig != NULL) {

ant = act ;act = act->sig ;

}delete act ;ant->sig = NULL ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) e l e lemento de l a pos i c ion indicada por ( pos ) ,// s i e x i s t evoid eliminar_pos(PNodo& lista , int pos){

46

Page 47: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

if (lista != NULL) {if (pos < 1) {

PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

} else {PNodo ant = situar(lista , pos - 1) ;if ((ant != NULL)&&(ant->sig != NULL)) {

PNodo act = ant->sig ;ant->sig = act->sig ;delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a una nueva l i s t a r e su l t ado de dup l i c a r en// memoria dinamica l a l i s t a r e c i b i d a como parametroPNodo duplicar(PNodo lista){

PNodo nueva = NULL;if (lista != NULL) {

nueva = new Nodo ;nueva->dato = lista->dato ;PNodo u = nueva ;PNodo p = lista->sig ;while (p != NULL) {

u->sig = new Nodo ;u->sig->dato = p->dato ;u = u->sig ;p = p->sig ;

}u->sig = NULL ;

}return nueva;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Muestra en pan t a l l a e l contenido de ( l i s t a )void escribir(PNodo lista){

PNodo ptr = lista;while (ptr != NULL) {

cout << ptr->dato << " " ;ptr = ptr->sig ;

}cout << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve una l i s t a con l o s numeros l e i d o s de t e c l ado ( en e l mismo// orden que son in t roduc ido s ) hasta que l e a e l numero 0 ( que no es// in t roduc ido )PNodo leer(){

PNodo lista = NULL ;int dt ;cin >> dt ;if (dt != 0) {

lista = new Nodo ;lista->dato = dt ;PNodo u = lista ;cin >> dt ;while (dt != 0) {

u->sig = new Nodo ;u->sig->dato = dt ;u = u->sig ;cin >> dt ;

}u->sig = NULL ;

}return lista;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que cont iene e l elemento// i g u a l a ( dt ) . Si no se encuentra , entonces devue l ve NULL

47

Page 48: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

PNodo buscar(PNodo lista , int dt){

PNodo ptr = lista ;while ((ptr != NULL)&&(ptr->dato != dt)) {

ptr = ptr->sig ;}return ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento de forma ordenada en ( l i s t a ) , que debe e s t a r// ordenadavoid insertar_ord(PNodo& lista , int dt){

PNodo ptr = new Nodo ;ptr->dato = dt ;if ((lista == NULL)||(dt < lista->dato)) {

ptr->sig = lista ;lista = ptr ;

} else {PNodo ant = lista ;PNodo act = ant->sig ;while ((act!=NULL)&&(act->dato<=dt)) {

ant = act ;act = act->sig ;

}ptr->sig = ant->sig ;ant->sig = ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) e l primer elemento i g u a l a ( dt ) , s i e x i s t evoid eliminar_elem(PNodo& lista , int dt){

if (lista != NULL) {if (lista->dato == dt) {

PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

} else {PNodo ant = lista ;PNodo act = ant->sig ;while ((act != NULL)&&(act->dato != dt)) {

ant = act ;act = act->sig ;

}if (act != NULL) {

ant->sig = act->sig ;delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l mayor elemento de ( l i s t a ) , s i e x i s t evoid eliminar_mayor(PNodo& lista){

if (lista != NULL) {PNodo ant_may = NULL; // an t e r i o r a l mayorPNodo ptr_may = lista; // apunta a l mayorPNodo ant = lista; // an t e r i o r a l p t rPNodo ptr = lista->sig; // p t r de recor r idowhile (ptr != NULL) {

if (ptr->dato > ptr_may->dato) { // s i es mayorant_may = ant; // a c t u a l i z a r an t e r i o r a l mayorptr_may = ptr; // a c t u a l i z a r e l puntero a l mayor

}ant = ptr; // mover l o s punteros de recor r idoptr = ptr->sig;

}if (ptr_may == lista) {

lista = lista->sig;} else {

ant_may->sig = ptr_may->sig;}

48

Page 49: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

delete ptr_may;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) todos l o s e lementos que sean i g u a l e s a ( dt ) ,// s i e x i s t envoid purgar(PNodo& lista , int dt){

while ((lista != NULL)&&(dt == lista->dato)) {PNodo ptr = lista;lista = lista->sig;delete ptr;

}if (lista != NULL) {

PNodo ant = lista;PNodo act = lista->sig;while (act != NULL) {

if (dt == act->dato) {ant->sig = act->sig;delete act;

} else {ant = act;

}act = ant->sig;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include "lista.hpp"#include <iostream>using namespace std;using namespace umalcc;

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "X. Fin" << endl;cout << "A. Destruir Lista" << endl;cout << "B. Insertar Inicio" << endl;cout << "C. Insertar Final" << endl;cout << "D. Situar Posicion" << endl;cout << "E. Insertar Posicion" << endl;cout << "F. Eliminar Primero" << endl;cout << "G. Eliminar Ultimo" << endl;cout << "H. Eliminar Posicion" << endl;cout << "I. Duplicar" << endl;cout << "J. Escribir" << endl;cout << "K. Leer" << endl;cout << "L. Buscar Elemento" << endl;cout << "M. Insertar Ordenado" << endl;cout << "N. Eliminar Elemento" << endl;cout << "O. Eliminar Mayor" << endl;cout << "P. Purgar" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'X')||((op >= 'A')&&(op <= 'P'))));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(int& dato){

cout << "Introduzca dato: " ;cin >> dato;

}

49

Page 50: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void leer(unsigned& pos){

cout << "Introduzca posicion: " ;cin >> pos;

}void prueba_duplicar(PNodo lista){

PNodo aux = duplicar(lista);cout << "Lista original: " ;escribir(lista);cout << "Lista copia: " ;escribir(aux);destruir(aux);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

PNodo lista;PNodo aux;char op = ' ';int dato;unsigned pos;inicializa(lista);do {

op = menu ();switch (op) {case 'A':

destruir(lista);escribir(lista);break;

case 'B':leer(dato);insertar_principio(lista , dato);escribir(lista);break;

case 'C':leer(dato);insertar_final(lista , dato);escribir(lista);break;

case 'D':leer(pos);aux = situar(lista , pos);if (aux == NULL) {

cout << "Error: posicion erronea" << endl;} else {

cout << "Elemento ["<<pos<<"]: " << aux->dato << endl;}escribir(lista);break;

case 'E':leer(pos);leer(dato);insertar_pos(lista , pos , dato) ;escribir(lista);break;

case 'F':eliminar_primero(lista);escribir(lista);break;

case 'G':eliminar_ultimo(lista);escribir(lista);break;

case 'H':leer(pos);eliminar_pos(lista , pos) ;escribir(lista);break;

case 'I':prueba_duplicar(lista);break;

case 'J':escribir(lista);

50

Page 51: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

break;case 'K':

destruir(lista);cout << "Introduzca elementos (0 -> FIN)" << endl;lista = leer ();escribir(lista);break;

case 'L':leer(dato);aux = buscar(lista , dato);if (aux == NULL) {

cout << "Error: No encontrado" << endl;} else {

cout << "Elemento: " << aux->dato << endl;}escribir(lista);break;

case 'M':leer(dato);insertar_ord(lista , dato);escribir(lista);break;

case 'N':leer(dato);eliminar_elem(lista , dato);escribir(lista);break;

case 'O':eliminar_mayor(lista );escribir(lista);break;

case 'P':leer(dato);purgar(lista , dato);escribir(lista);break;

}} while (op != 'X');destruir(lista);

}� �2. Un conjunto de números enteros es una colección de elementos homogéneos (números enteros) sin repetición

y ninguna relación de orden entre ellos (no ordenados y sin repetición).

Un conjunto de elementos se puede representar mediante una lista enlazada, donde cada nodo contieneun elemento del conjunto. Por ejemplo el conjunto con los elementos {1, 2, 3} puede ser representado porla siguiente lista enlazada:

lista: −−→◦ −−−−→◦1

−−−−→◦2

�3

Diseñe un módulo (programación modular) que proporcione soporte adecuado a la manipulación de con-juntos de números enteros implementados mediante listas enlazadas en memoria dinámica (véase figuraanterior). El módulo deberá definir el tipo Conjunto como un registro con un campo de tipo PNodo, que sedefine como un tipo puntero a un registro en memoria dinámica de tipo Nodo que contiene un enlace al si-guiente nodo, así como un dato de tipo int. Además, el módulo deberá definir los siguientes subprogramas.Diseñe también un módulo principal que permita comprobar la corrección del módulo implementado.

Nota: aunque el orden en el que se encuentran los elementos en el conjunto no es importante, y por lotanto, la opción más simple para incluir elementos en él podría ser “insertar siempre los elementos por elprincipio”, con objeto de prácticar los conceptos de listas enlazadas, en esta práctica, los elementos delconjunto serán insertados (sin repetición) ordenados en la lista enlazada donde se encuentran almacenados.

Solución: conjuntos.hpp� �51

Page 52: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#ifndef conjuntos_hpp_#define conjuntos_hpp_#include <iostream>namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Nodo;typedef Nodo* PNodo;struct Nodo {

PNodo sig;int dato;

};struct Conjunto {

PNodo lista;};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void inicializar(Conjunto& c);// I n i c i a l i z a ( c ) a un conjunto vac iovoid destruir(Conjunto& c);// Destruye todos l o s e lementos de l conjunto , l i b e rando// todos l o s nodos de memoria dinamica . ( c ) queda vac iovoid copiar(Conjunto& d, const Conjunto& o) ;// Copia ( dup l i ca ) e l conjunto (o ) en e l conjunto (d )bool es_vacio(const Conjunto& c) ;// Devuelve t rue s i e l conjunto ( c ) e s ta vac iovoid incluir(Conjunto& c, int e);// Inc luye e l elemento ( e ) en e l conjunto ( c ) ( s in r e p e t i c i on )void eliminar(Conjunto& c, int e);// Elimina e l elemento ( e ) de l conjunto ( c )bool pertenece(const Conjunto& c, int e) ;// Devuelve t rue s i e l e lemento ( e ) per tenece a l conjunto ( c )bool es_subconjunto(const Conjunto& a, const Conjunto& b) ;// Devuelve t rue s i e l conjunto (a ) es subconjunto de l conjunto ( b )void union_conj(Conjunto& c, const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ( c ) e l r e su l t ado de// l a union de l o s conjuntos (a ) y ( b ) ( dup l i ca l o s nodos )void interseccion(Conjunto& c, const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ( c ) e l r e su l t ado de// l a i n t e r s e c c i on de l o s conjuntos (a ) y ( b ) ( dup l i ca l o s nodos )void diferencia(Conjunto& c, const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ( c ) e l r e su l t ado de// l a d i f e r en c i a de l o s conjuntos (a ) y ( b ) ( dup l i ca l o s nodos )void diferencia_simetrica(Conjunto& c, const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ( c ) e l r e su l t ado de// l a d i f e r en c i a s ime t r i ca de l o s conjuntos (a ) y ( b ) ( dup l i ca l o s nodos )void escribir(const Conjunto& c) ;// Muestra en pan t a l l a e l contenido de l conjunto ( c )void leer(Conjunto& c);// Lee de t e c l ado e l va l o r de l conjunto ( c )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}#endif� �

Solución: conjuntos.cpp� �#include "conjuntos.hpp"#include <iostream>#include <array>#include <cassert>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Aux i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que cont iene e l elemento// i g u a l a ( dt ) . Si no se encuentra , entonces devue l ve NULLPNodo buscar_ord(PNodo lst , int dt){

PNodo ptr = lst ;

52

Page 53: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

while ((ptr != NULL)&&(ptr->dato < dt)) {ptr = ptr->sig ;

}if ((ptr != NULL)&&(ptr->dato != dt)) {

ptr = NULL;}

return ptr ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento de forma ordenada en ( l s t ) , que debe e s t a r// ordenada ( s in r e p e t i c i on )void insertar_ord(PNodo& lst , int dt){

if ((lst == NULL) || (dt < lst->dato)) {PNodo aux = new Nodo ;aux->dato = dt ;aux->sig = lst ;lst = aux ;

} else if (dt > lst->dato) {PNodo ant = lst ;PNodo act = ant->sig ;while ((act != NULL) && (act->dato < dt)) {

ant = act ;act = act->sig ;

}if ((act == NULL) || (act->dato != dt)) {

PNodo aux = new Nodo ;aux->dato = dt ;aux->sig = ant->sig ;ant->sig = aux ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l s t ) e l e lemento cuyo dato es i g u a l a ( dt ) , s i e x i s t e// La l i s t a ( l s t ) se encuentra ordenadavoid eliminar_ord(PNodo& lst , int dt){

if (lst != NULL) {if (lst->dato == dt) {

PNodo aux = lst ;lst = lst->sig ;delete aux ;

} else {PNodo ant = lst ;PNodo act = ant->sig ;while ((act != NULL)&&(act->dato < dt)) {

ant = act;act = act->sig;

}if ((act != NULL) && (act->dato == dt)) {

ant->sig = act->sig ;delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a una nueva l s t r e su l t ado de dup l i c a r en// memoria dinamica l a l s t r e c i b i d a como parametroPNodo duplicar(PNodo lst){

PNodo nueva = NULL;if (lst != NULL) {

nueva = new Nodo ;nueva->dato = lst->dato ;PNodo u = nueva ;PNodo p = lst->sig ;while (p != NULL) {

u->sig = new Nodo ;u->sig->dato = p->dato ;u = u->sig ;p = p->sig ;

53

Page 54: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}u->sig = NULL ;

}return nueva;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Destruye todos l o s e lementos de l a l s t , l i b e rando// todos l o s nodos de memoria dinamica . ( l s t ) queda vac iavoid destruir_lista(PNodo& lst){

while (lst != NULL) {PNodo ptr = lst ;lst = lst->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void inicializar(Conjunto& c){

c.lista = NULL;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void destruir(Conjunto& c){

destruir_lista(c.lista);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void copiar(Conjunto& d, const Conjunto& o){

if (d.lista != o.lista) {destruir_lista(d.lista);d.lista = duplicar(o.lista);

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool es_vacio(const Conjunto& c){

return (c.lista == NULL);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void incluir(Conjunto& c, int e){

insertar_ord(c.lista , e); // in s e r t a s in r e p e t i c i on}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar(Conjunto& c, int e){

eliminar_ord(c.lista , e);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool pertenece(const Conjunto& c, int e){

return (buscar_ord(c.lista , e) != NULL);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool es_subconjunto(const Conjunto& a, const Conjunto& b){

PNodo ptr = a.lista ;while ((ptr != NULL)&& pertenece(b, ptr->dato)) {

ptr = ptr->sig ;}return (ptr == NULL);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void union_conj(Conjunto& c, const Conjunto& a, const Conjunto& b)

54

Page 55: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{PNodo lst = duplicar(a.lista );PNodo ptr = b.lista ;while (ptr != NULL) {

insertar_ord(lst , ptr->dato); // in s e r t a s in r e p e t i c i onptr = ptr->sig ;

}destruir_lista(c.lista);c.lista = lst;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void interseccion(Conjunto& c, const Conjunto& a, const Conjunto& b){

PNodo lst = NULL;PNodo ptr = a.lista ;while (ptr != NULL) {

if (pertenece(b, ptr->dato)) {insertar_ord(lst , ptr->dato); // in s e r t a s in r e p e t i c i on

}ptr = ptr->sig ;

}destruir_lista(c.lista);c.lista = lst;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void diferencia(Conjunto& c, const Conjunto& a, const Conjunto& b){

PNodo lst = NULL;PNodo ptr = a.lista ;while (ptr != NULL) {

if ( ! pertenece(b, ptr->dato)) {insertar_ord(lst , ptr->dato); // in s e r t a s in r e p e t i c i on

}ptr = ptr->sig ;

}destruir_lista(c.lista);c.lista = lst;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void diferencia_simetrica(Conjunto& c, const Conjunto& a, const Conjunto& b){

Conjunto a_b , b_a;inicializar(a_b);inicializar(b_a);diferencia(a_b , a, b);diferencia(b_a , b, a);union_conj(c, a_b , b_a);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir(const Conjunto& c){

cout << "{ ";PNodo ptr = c.lista;while (ptr != NULL) {

cout << ptr->dato << " " ;ptr = ptr->sig ;

}cout << "}";

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(Conjunto& c){

destruir(c);int e;cin >> e ;while (e != 0) {

incluir(c, e);cin >> e ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �55

Page 56: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: main.cpp� �#include <iostream>#include <string>#include "conjuntos.hpp"using namespace std;using namespace umalcc;

void escribir(const string& msj , const Conjunto& c){

cout << msj;escribir(c);cout << endl;

}int main(){

Conjunto c1 , c2 , c3;inicializar(c1);inicializar(c2);inicializar(c3);cout << "Introduzca elementos del conjunto: [0 -> fin]: ";leer(c1);escribir("C1: ", c1);cout << "Introduzca elementos del conjunto: [0 -> fin]: ";leer(c2);escribir("C2: ", c2);cout << "Es subconjunto: " << boolalpha << es_subconjunto(c1 , c2) << endl;union_conj(c3 , c1, c2);escribir("Union: ", c3);interseccion(c3 , c1 , c2);escribir("Interseccion: ", c3);diferencia(c3 , c1, c2);escribir("Diferencia: ", c3);diferencia_simetrica(c3 , c1 , c2);escribir("Diferencia Simetrica: ", c3);

}� �3. Diseñe un módulo (programación modular) que proporcione soporte adecuado a la manipulación de listas

doblemente enlazadas en memoria dinámica (véase siguiente figura). El módulo deberá definir el tipoPNodo como un puntero a un registro en memoria dinámica de tipo Nodo que contiene un enlace al siguientenodo, un enlace al nodo anterior, así como un dato de tipo int. Además, el módulo deberá definir lossiguientes subprogramas. Diseñe también un módulo principal que permita comprobar la corrección delmódulo lista implementado.

lista: −−→◦ −−−−−→◦�0

−−−−−→◦←−−−−−◦

1

�←−−−−−◦

2

Solución: listadbl.hpp� �#ifndef listadbl_hpp_#define listadbl_hpp_namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Nodo ; // Declaración ade lantada de l t i p o incompleto Nodotypedef Nodo* PNodo ; // Def in i c ión de t i p o Puntero a t i p o incompleto Nodostruct Nodo { // Def in i c ión de l t i p o Nodo

PNodo sig ; // Enlace a l a s i g u i e n t e e s t ruc tu ra dinámicaPNodo ant ; // Enlace a l a e s t ruc tu ra dinámica an t e r i o rint dato ; // Dato almacenado en l a l i s t a

} ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void inicializa(PNodo& lista) ;// I n i c i a l i z a ( l i s t a ) a una l i s t a vac ia//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void destruir(PNodo& lista) ;// Destruye todos l o s e lementos de l a l i s t a , l i b e rando// todos l o s nodos de memoria dinamica . ( l i s t a ) queda vac ia

56

Page 57: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_principio(PNodo& lista , int dt) ;// Inse r ta un elemento a l p r i n c i p i o de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_final(PNodo& lista , int dt) ;// Inse r ta un elemento a l f i n a l de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo situar(PNodo lista , int pos) ;// Devuelve un puntero a l nodo que se encuentra en l a pos i c ion// indicada por ( pos ) . La pos i c ion cero (0) ind i ca e l primer nodo .// Si e l nodo no ex i s t e , entonces devue l ve NULL//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar(PNodo& lista , int pos , int dt) ;// Inse r ta en ( l i s t a ) un elemento en l a pos i c ion indicada por ( pos )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_primero(PNodo& lista) ;// Elimina e l primer elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_ultimo(PNodo& lista) ;// Elimina e l u l t imo elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar(PNodo& lista , int pos) ;// Elimina de ( l i s t a ) e l e lemento de l a pos i c ion indicada por ( pos ) ,// s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo duplicar(PNodo lista) ;// Devuelve un puntero a una nueva l i s t a r e su l t ado de dup l i c a r en// memoria dinamica l a l i s t a r e c i b i d a como parametro//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir(PNodo lista) ;// Muestra en pan t a l l a e l contenido de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo leer() ;// Devuelve una l i s t a con l o s numeros l e i d o s de t e c l ado ( en e l mismo// orden que son in t roduc ido s ) hasta que l e a e l numero 0 ( que no es// in t roduc ido )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo buscar(PNodo lista , int dt) ;// Devuelve un puntero a l nodo que cont iene e l elemento// i g u a l a ( dt ) . Si no se encuentra , entonces devue l ve NULL//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_ord(PNodo& lista , int dt) ;// Inse r ta un elemento de forma ordenada en ( l i s t a ) , que debe e s t a r ordenada//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_elem(PNodo& lista , int dt) ;// Elimina de ( l i s t a ) e l primer elemento i g u a l a ( dt ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_mayor(PNodo& lista) ;// Elimina e l mayor elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void purgar(PNodo& lista , int dt) ;// Elimina de ( l i s t a ) todos l o s e lementos que sean i g u a l e s a ( dt ) ,// s i e x i s t en//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}#endif� �

Solución: listadbl.cpp� �#include "listadbl.hpp"#include <iostream>#include <cstddef>#include <cassert>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Aux i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

57

Page 58: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void insertar_nodo(PNodo& ptr , PNodo ant , int dt){

// Crea e l nodo con e l va l o r de l dato , e l va l o r de l campo// ' s i g ' apuntando a l nodo apuntado por ' p t r ' , e l va l o r// de l campo ' ant ' apuntando a l nodo apuntado por ' ant ' y// hace que ' p t r ' apunte a e s t e nuevo nodo . Tambien hace// que e l an t e r i o r de l s i g u i e n t e apunte a e s t e nodoPNodo aux = new Nodo ;aux->dato = dt ;aux->ant = ant ;aux->sig = ptr ;ptr = aux ;if (aux->sig != NULL) {

aux->sig->ant = aux;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_nodo(PNodo& ptr){

// hace que ' p t r ' apunte a l nodo s i g u i e n t e a l que apunta// actualmente , y hace que e l an t e r i o r de e s t e nodo// s i g u i e n t e apunte a l an t e r i o r a l nodo de p t r . Finalmente// l i b e r a e l nodo a l que ' p t r ' apuntaba in i c i a lmen t eassert(ptr != NULL);PNodo aux = ptr;ptr = ptr->sig;if (ptr != NULL) {

ptr->ant = aux->ant;}delete aux;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// I n i c i a l i z a ( l i s t a ) a una l i s t a vac ia// sera inse r tado en l a l i s t a )void inicializa(PNodo& lista){

lista = NULL ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Destruye todos l o s e lementos de l a l i s t a , l i b e rando// todos l o s nodos de memoria dinamica . ( l i s t a ) queda vac iavoid destruir(PNodo& lista){

while (lista != NULL) {PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento a l p r i n c i p i o de ( l i s t a )void insertar_principio(PNodo& lista , int dt){

insertar_nodo(lista , NULL , dt);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento a l f i n a l de ( l i s t a )void insertar_final(PNodo& lista , int dt){

if (lista == NULL) {insertar_nodo(lista , NULL , dt);

} else {PNodo ant = lista;while (ant->sig != NULL) {

ant = ant->sig;}insertar_nodo(ant->sig , ant , dt);

}

58

Page 59: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que se encuentra en l a pos i c ion// indicada por ( pos ) . La pos i c ion cero (0) ind i ca e l primer nodo .// Si e l nodo no ex i s t e , entonces devue l ve NULLPNodo situar(PNodo lista , int pos){

PNodo ptr = lista;while ((ptr != NULL)&&(pos > 0)) {

ptr = ptr->sig;--pos;

}return ptr;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta en ( l i s t a ) un elemento en l a pos i c ion indicada por ( pos )void insertar(PNodo& lista , int pos , int dt){

if (pos < 1) {insertar_nodo(lista , NULL , dt);

} else {PNodo ant = situar(lista , pos - 1);if (ant != NULL) {

insertar_nodo(ant->sig , ant , dt);}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l primer elemento de ( l i s t a ) , s i e x i s t evoid eliminar_primero(PNodo& lista){

if (lista != NULL) {eliminar_nodo(lista) ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l u l t imo elemento de ( l i s t a ) , s i e x i s t evoid eliminar_ultimo(PNodo& lista){

if (lista != NULL) {if (lista->sig == NULL) {

eliminar_nodo(lista) ;} else {

PNodo act = lista->sig ;while (act->sig != NULL) {

act = act->sig;}eliminar_nodo(act->ant->sig) ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) e l e lemento de l a pos i c ion indicada por ( pos ) ,// s i e x i s t evoid eliminar(PNodo& lista , int pos){

if (lista != NULL) {if (pos < 1) {

eliminar_nodo(lista) ;} else {

PNodo act = situar(lista , pos) ;if (act != NULL) {

eliminar_nodo(act->ant->sig) ;}

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a una nueva l i s t a r e su l t ado de dup l i c a r en// memoria dinamica l a l i s t a r e c i b i d a como parametroPNodo duplicar(PNodo lista){

PNodo nueva = NULL;if (lista != NULL) {

59

Page 60: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

insertar_nodo(nueva , NULL , lista->dato) ;PNodo u = nueva ;PNodo p = lista->sig ;while (p != NULL) {

insertar_nodo(u->sig , u, p->dato) ;u = u->sig ;p = p->sig ;

}}return nueva;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Muestra en pan t a l l a e l contenido de ( l i s t a )void escribir(PNodo lista){

PNodo ptr = lista;while (ptr != NULL) {

cout << ptr->dato << " " ;ptr = ptr->sig ;

}cout << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve una l i s t a con l o s numeros l e i d o s de t e c l ado ( en e l mismo// orden que son in t roduc ido s ) hasta que l e a e l numero 0 ( que no es// in t roduc ido )PNodo leer(){

PNodo lista = NULL;int dt ;cin >> dt ;if (dt != 0) {

insertar_nodo(lista , NULL , dt) ;PNodo u = lista ;cin >> dt ;while (dt != 0) {

insertar_nodo(u->sig , u, dt) ;u = u->sig ;cin >> dt ;

}}return lista;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que cont iene e l elemento// i g u a l a ( dt ) . Si no se encuentra , entonces devue l ve NULLPNodo buscar(PNodo lista , int dt){

PNodo ptr = lista ;while ((ptr != NULL)&&(ptr->dato != dt)) {

ptr = ptr->sig ;}return ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento de forma ordenada en ( l i s t a ) , que debe e s t a r// ordenadavoid insertar_ord(PNodo& lista , int dt){

if ((lista == NULL)||(dt < lista->dato )){insertar_nodo(lista , NULL , dt) ;

} else {PNodo ant = lista ;PNodo act = ant->sig ;while ((act!=NULL)&&(act->dato<=dt)){

ant = act ;act = act->sig ;

}insertar_nodo(ant->sig , ant , dt) ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) e l primer elemento i g u a l a ( dt ) , s i e x i s t evoid eliminar_elem(PNodo& lista , int dt)

60

Page 61: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{if (lista != NULL) {

if (lista->dato == dt) {eliminar_nodo(lista );

} else {PNodo act = lista->sig ;while ((act != NULL)&&(act->dato != dt)) {

act = act->sig;}if (act != NULL) {

eliminar_nodo(act->ant->sig);}

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l mayor elemento de ( l i s t a ) , s i e x i s t evoid eliminar_mayor(PNodo& lista){

if (lista != NULL) {PNodo ptr_may = lista; // apunta a l mayorPNodo ptr = lista->sig; // p t r de recor r idowhile (ptr != NULL) {

if (ptr->dato > ptr_may->dato) { // s i es mayorptr_may = ptr; // a c t u a l i z a r e l puntero a l mayor

}ptr = ptr->sig; // mover l o s punteros de recor r ido

}if (ptr_may == lista) {

eliminar_nodo(lista ); // e l iminar e l primero} else {

eliminar_nodo(ptr_may->ant->sig); // e l iminar un nodo s i g u i e n t e}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) todos l o s e lementos que sean i g u a l e s a ( dt ) ,// s i e x i s t envoid purgar(PNodo& lista , int dt){

while ((lista != NULL)&&(dt == lista->dato)) {eliminar_nodo(lista );

}if (lista != NULL) {

PNodo ant = lista;PNodo act = lista->sig;while (act != NULL) {

if (dt == act->dato) {eliminar_nodo(ant->sig);

} else {ant = act;

}act = ant->sig;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include "listadbl.hpp"#include <iostream>using namespace std;using namespace umalcc;

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "X. Fin" << endl;cout << "A. Destruir Lista" << endl;

61

Page 62: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "B. Insertar Inicio" << endl;cout << "C. Insertar Final" << endl;cout << "D. Situar Posicion" << endl;cout << "E. Insertar Posicion" << endl;cout << "F. Eliminar Primero" << endl;cout << "G. Eliminar Ultimo" << endl;cout << "H. Eliminar Posicion" << endl;cout << "I. Duplicar" << endl;cout << "J. Escribir" << endl;cout << "K. Leer" << endl;cout << "L. Buscar Elemento" << endl;cout << "M. Insertar Ordenado" << endl;cout << "N. Eliminar Elemento" << endl;cout << "O. Eliminar Mayor" << endl;cout << "P. Purgar" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'X')||((op >= 'A')&&(op <= 'P'))));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(int& dato){

cout << "Introduzca dato: " ;cin >> dato;

}void leer(unsigned& pos){

cout << "Introduzca posicion: " ;cin >> pos;

}void prueba_duplicar(PNodo lista){

PNodo aux = duplicar(lista);cout << "Lista original: " ;escribir(lista);cout << "Lista copia: " ;escribir(aux);destruir(aux);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

PNodo lista;PNodo aux;char op = ' ';int dato;unsigned pos;inicializa(lista);do {

op = menu ();switch (op) {case 'A':

destruir(lista);escribir(lista);break;

case 'B':leer(dato);insertar_principio(lista , dato);escribir(lista);break;

case 'C':leer(dato);insertar_final(lista , dato);escribir(lista);break;

case 'D':leer(pos);aux = situar(lista , pos);if (aux == NULL) {

cout << "Error: posicion erronea" << endl;

62

Page 63: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

} else {cout << "Elemento ["<<pos<<"]: " << aux->dato << endl;

}escribir(lista);break;

case 'E':leer(pos);leer(dato);insertar(lista , pos , dato) ;escribir(lista);break;

case 'F':eliminar_primero(lista);escribir(lista);break;

case 'G':eliminar_ultimo(lista);escribir(lista);break;

case 'H':leer(pos);eliminar(lista , pos) ;escribir(lista);break;

case 'I':prueba_duplicar(lista);break;

case 'J':escribir(lista);break;

case 'K':destruir(lista);cout << "Introduzca elementos (0 -> FIN)" << endl;lista = leer ();escribir(lista);break;

case 'L':leer(dato);aux = buscar(lista , dato);if (aux == NULL) {

cout << "Error: No encontrado" << endl;} else {

cout << "Elemento: " << aux->dato << endl;}escribir(lista);break;

case 'M':leer(dato);insertar_ord(lista , dato);escribir(lista);break;

case 'N':leer(dato);eliminar_elem(lista , dato);escribir(lista);break;

case 'O':eliminar_mayor(lista );escribir(lista);break;

case 'P':leer(dato);purgar(lista , dato);escribir(lista);break;

}} while (op != 'X');destruir(lista);

}� �

63

Page 64: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Tema 3.2: Abstracción en la Gestión de Memoria Dinámica1. Un polinomio en x de grado arbitrario se puede representar mediante una lista enlazada, donde cada nodo

contiene el coeficiente y el exponente de un término del polinomio, y donde los coeficientes con valor cero(0) no serán almacenados. Por ejemplo el polinomio 25x − 14x5 puede ser representado por la siguientelista enlazada:

lista: −−→◦ −−−−→◦251

�-145

Diseñe e implemente el TAD polinomio que defina los siguientes métodos públicos, así como un programapara comprobar su funcionamiento:

Solución: polinomios.hpp� �#ifndef polinomios_hpp_#define polinomios_hpp_namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−const double ERROR_PRECISION = 1e-6;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−class Polinomio {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−˜ Polinomio ();// DestructorPolinomio ();// Constructor por DefectoPolinomio(const Polinomio& p);// Constructor de copiaPolinomio& operator=(const Polinomio& p);// Operador de Asignacionint max_grado () const;// Devuelve e l mayor grado de l pol inomio ac tua l// cuyo c o e f i c i e n t e es d i s t i n t o de cerovoid poner(int e, double c);// Asigna e l c o e f i c i e n t e ( c ) a l termino de grado ( e )// de l pol inomio ac tua ldouble obtener(int e) const;// Devuelve e l c o e f i c i e n t e correspond ien te a l// termino de grado ( e ) de l pol inomio ac tua ldouble evaluar(double x) const;// Devuelve e l r e su l t ado de eva luar e l pol inomio ac tua l// para un va l o r de ( x ) e s p e c i f i c a do como parametrovoid derivar(const Polinomio& a);// Asigna a l pol inomio ac tua l e l r e su l t ado de// c a l c u l a r l a der ivada de l pol inomio (a )void sumar(const Polinomio& a, const Polinomio& b);// Asigna a l pol inomio ac tua l e l r e su l t ado de// sumar l o s pol inomios (a ) y ( b )void escribir () const;// Muestra en pan t a l l a e l contenido de l pol inomio ac tua lvoid leer ();// Lee de t e c l ado e l va l o r de l pol inomio ac tua l// Lee pares de c o e f i c i e n t e y grado hasta que e l c o e f i c i e n t e sea cero//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Nodo;typedef Nodo* PNodo;struct Dato {

int exp;double coef;

};

64

Page 65: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

struct Nodo {PNodo sig;Dato dato;

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo buscar_ord(PNodo lst , int exp) const ;void insertar_ord(PNodo& lst , const Dato& dt) const ;void eliminar_ord(PNodo& lst , int exp) const ;PNodo duplicar(PNodo lst) const ;void destruir(PNodo& lst) const ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int mg;PNodo lista;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

Solución: polinomios.cpp� �#include "polinomios.hpp"#include <iostream>#include <cassert>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Aux i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Valor ab so l u t o de un numeroinline double abs(double a) {

return (a >= 0) ? a : -a;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Dos numeros r e a l e s son i g u a l e s s i l a d i s t anc i a que l o s// separa es l o su f i c i en t emen te pequenyainline bool iguales(double a, double b) {

return abs(a-b) <= ERROR_PRECISION;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double potencia(double base , int exp){

double res = 1;for (int i = 0; i < exp; ++i) {

res *= base;}return res;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Polinomio :: ˜ Polinomio () { destruir(lista ); }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Polinomio :: Polinomio () : mg(0), lista () {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Polinomio :: Polinomio(const Polinomio& o)

: mg(o.mg), lista(duplicar(o.lista)) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Polinomio& Polinomio :: operator=(const Polinomio& o){

if (this != &o) {

65

Page 66: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

destruir(lista);mg = o.mg;lista = duplicar(o.lista);

}return *this;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int Polinomio :: max_grado () const{

return mg;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: poner(int e, double c){

// Si e l c o e f i c i e n t e es i g u a l a cero , entonces se debe// e l iminar e l elemento correspond ien te a ese exponente s i es// que e x i s t e . En otro caso , s i ya es taba almacenado , se// reemplaza su va l o r . En otro caso , se i n s e r t a ordenado por// exponente .if (iguales(c, 0.0)) {

if (e <= mg) {eliminar_ord(lista , e);

}} else {

Dato d = { e, c } ;insertar_ord(lista , d); // i n s e r t a r s in r e p e t i c i onif (e > mg) {

mg = e;}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Polinomio :: obtener(int e) const{

// Si e l e lemento no es ta en l a l i s t a entonces su va l o r es cerodouble res = 0.0;if (e <= mg) {

PNodo ptr = buscar_ord(lista , e);if (ptr != NULL) {

res = ptr->dato.coef;}

}return res;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Polinomio :: evaluar(double x) const{

double res = 0.0;PNodo ptr = lista;while (ptr != NULL) {

res += ptr->dato.coef * potencia(x, ptr->dato.exp);ptr = ptr->sig ;

}return res;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: derivar(const Polinomio& a){

PNodo lst = NULL;PNodo ptr = a.lista;while (ptr != NULL) {

if (ptr->dato.exp > 0) {Dato d = { ptr->dato.exp - 1, ptr->dato.coef * ptr->dato.exp } ;insertar_ord(lst , d) ;

}ptr = ptr->sig ;

}destruir(lista);lista = lst;mg = a.mg - 1;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: sumar(const Polinomio& a, const Polinomio& b){

66

Page 67: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// Para sumar dos pol inomios , consideramos e l hecho de que// ambas l i s t a s se encuentran ordenadas . Se suman l o s// elementos con i g u a l exponente , y se copian l o s de// exponentes d i s t i n t o s .PNodo lst = NULL;PNodo p1 = a.lista;PNodo p2 = b.lista;while ((p1 != NULL)&&(p2 != NULL)) {

if (p1->dato.exp == p2->dato.exp) {if ( ! iguales (0.0, p1->dato.coef + p2->dato.coef)) {

Dato d = { p1->dato.exp , p1->dato.coef + p2->dato.coef } ;insertar_ord(lst , d);

}p1 = p1->sig;p2 = p2->sig;

} else if (p1->dato.exp < p2->dato.exp) {insertar_ord(lst , p1->dato);p1 = p1->sig;

} else {assert(p1->dato.exp > p2->dato.exp);insertar_ord(lst , p2->dato);p2 = p2->sig;

}}while (p1 != NULL) {

insertar_ord(lst , p1->dato);p1 = p1->sig;

}while (p2 != NULL) {

insertar_ord(lst , p2->dato);p2 = p2->sig;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−destruir(lista);lista = lst;if (a.mg > b.mg) {

mg = a.mg;} else {

mg = b.mg;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio :: escribir () const{

PNodo ptr = lista;while (ptr != NULL) {

assert(! iguales(ptr->dato.coef , 0.0));cout << (ptr->dato.coef > 0.0 ? " +" : " ")

<< ptr->dato.coef << " X^" << ptr->dato.exp ;ptr = ptr->sig ;

}cout << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Polinomio ::leer(){

destruir(lista);mg = 0;double c;cout << "Introduzca coeficiente [0 -> fin]: ";cin >> c;while ( !cin.fail() && ! iguales(c, 0.0) ) {

unsigned e;cout << "Introduzca exponente: ";cin >> e;if ( ! cin.fail() ) {

poner(e, c);}cout << "Introduzca coeficiente [0 -> fin]: ";cin >> c;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Aux i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

67

Page 68: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que cont iene e l exponente de l elemento// i g u a l a ( exp ) . Si no se encuentra , entonces devue l ve NULLPolinomio :: PNodo Polinomio :: buscar_ord(PNodo lst , int exp) const{

PNodo ptr = lst ;while ((ptr != NULL)&&(ptr->dato.exp < exp)) {

ptr = ptr->sig ;}if ((ptr != NULL)&&(ptr->dato.exp != exp)) {

ptr = NULL;}return ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento de forma ordenada en ( l s t ) , que debe e s t a r// ordenada ( s in r e p e t i c i on )void Polinomio :: insertar_ord(PNodo& lst , const Dato& dt) const{

if ((lst == NULL) || (dt.exp < lst->dato.exp)) {PNodo aux = new Nodo ;aux->dato = dt ;aux->sig = lst ;lst = aux ;

} else if (dt.exp == lst->dato.exp) {lst->dato.coef = dt.coef;

} else {PNodo ant = lst ;PNodo act = ant->sig ;while ((act != NULL) && (act->dato.exp < dt.exp)) {

ant = act ;act = act->sig ;

}if ((act != NULL) && (act->dato.exp == dt.exp)) {

act->dato.coef = dt.coef;} else {

PNodo aux = new Nodo ;aux->dato = dt ;aux->sig = ant->sig ;ant->sig = aux ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l s t ) e l e lemento cuyo exp es i g u a l a ( exp ) , s i e x i s t e// La l i s t a ( l s t ) se encuentra ordenadavoid Polinomio :: eliminar_ord(PNodo& lst , int exp) const{

if (lst != NULL) {if (lst->dato.exp == exp) {

PNodo aux = lst ;lst = lst->sig ;delete aux ;

} else if (lst->dato.exp < exp) {PNodo ant = lst ;PNodo act = ant->sig ;while ((act != NULL)&&(act->dato.exp < exp)) {

ant = act;act = act->sig;

}if ((act != NULL) && (act->dato.exp == exp)) {

ant->sig = act->sig ;delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a una nueva l s t r e su l t ado de dup l i c a r en// memoria dinamica l a l s t r e c i b i d a como parametroPolinomio :: PNodo Polinomio :: duplicar(PNodo lst) const{

PNodo nueva = NULL;if (lst != NULL) {

68

Page 69: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

nueva = new Nodo ;nueva->dato = lst->dato ;PNodo u = nueva ;PNodo p = lst->sig ;while (p != NULL) {

u->sig = new Nodo ;u->sig->dato = p->dato ;u = u->sig ;p = p->sig ;

}u->sig = NULL ;

}return nueva;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Destruye todos l o s e lementos de l a l s t , l i b e rando// todos l o s nodos de memoria dinamica . ( l s t ) queda vac iavoid Polinomio :: destruir(PNodo& lst) const{

while (lst != NULL) {PNodo ptr = lst ;lst = lst->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include "polinomios.hpp"using namespace std;using namespace umalcc;

void escribir(const string& msj , const Polinomio& p){

cout << msj;p.escribir ();cout << endl;

}

int main(){

Polinomio p1 , p2 , p3;p1.leer ();escribir("P1: ", p1);cout << "P1(2) = " << p1.evaluar (2.0) << endl;p2.derivar(p1);escribir("P2: ", p2);p3.sumar(p1, p2);escribir("P3: ", p3);p1 = p3;escribir("P1: ", p1);

}� �2. Un conjunto de números enteros es una colección de elementos homogéneos (números enteros) sin repetición

y ninguna relación de orden entre ellos (no ordenados y sin repetición).Un conjunto de elementos se puede representar mediante una lista enlazada, donde cada nodo contieneun elemento del conjunto. Por ejemplo el conjunto con los elementos {1, 2, 3} puede ser representado porla siguiente lista enlazada:

lista: −−→◦ −−−−→◦1

−−−−→◦2

�3

Diseñe e implemente el siguiente TAD conjunto de números enteros que defina los siguientes métodospúblicos, así como un programa para comprobar su funcionamiento:

69

Page 70: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: conjuntos.hpp� �#ifndef conjuntos_hpp_#define conjuntos_hpp_#include <iostream>namespace umalcc {

class Conjunto {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−˜ Conjunto ();// DestructorConjunto(const Conjunto& c);// Constructor de CopiaConjunto& operator=(const Conjunto& c);// Operador de AsignacionConjunto ();// Constructor por Defecto : conjunto vac iovoid clear ();// Elimina todos l o s e lementos de l conjunto ac tua l ( queda vac io )bool es_vacio () const;// Devuelve t rue s i e l conjunto ac tua l e s ta vac iovoid incluir(int e);// Inc luye e l elemento ( e ) en e l conjunto ac tua lvoid eliminar(int e);// Elimina e l elemento ( e ) de l conjunto ac tua lbool pertenece(int e) const;// Devuelve t rue s i e l e lemento ( e ) per tenece a l conjunto ac tua lbool es_subconjunto(const Conjunto& a) const;// Devuelve t rue s i e l conjunto ac tua l es subconjunto de l conjunto (a )void union_conj(const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ac tua l e l r e su l t ado de// l a union de l o s conjuntos (a ) y ( b )void interseccion(const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ac tua l e l r e su l t ado de// l a i n t e r s e c c i on de l o s conjuntos (a ) y ( b )void diferencia(const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ac tua l e l r e su l t ado de// l a d i f e r en c i a de l o s conjuntos (a ) y ( b )void diferencia_simetrica(const Conjunto& a, const Conjunto& b);// Asigna a l conjunto ac tua l e l r e su l t ado de// l a d i f e r en c i a s ime t r i ca de l o s conjuntos (a ) y ( b )void escribir () const;// Muestra en pan t a l l a e l contenido de l conjunto ac tua lvoid leer ();// Lee de t e c l ado e l va l o r de l conjunto actua l ,

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Ctes y Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Nodo;typedef Nodo* PNodo;struct Nodo {

PNodo sig;int dato;

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo buscar_ord(PNodo lst , int dt) const ;void insertar_ord(PNodo& lst , int dt) const ;void eliminar_ord(PNodo& lst , int dt) const ;PNodo duplicar(PNodo lst) const ;void destruir(PNodo& lst) const ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo lista; // componentes de l conjunto//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}

70

Page 71: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#endif� �Solución: conjuntos.cpp� �

#include "conjuntos.hpp"#include <iostream>#include <array>#include <cassert>using namespace std;namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Conjunto :: ˜ Conjunto () { destruir(lista); }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Conjunto :: Conjunto () : lista () {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Conjunto :: Conjunto(const Conjunto& o)

: lista(duplicar(o.lista )) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Conjunto& Conjunto :: operator=(const Conjunto& o){

if (this != &o) {destruir(lista);lista = duplicar(o.lista);

}return *this;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto ::clear(){

destruir(lista);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Conjunto :: es_vacio () const{

return (lista == NULL);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: incluir(int e){

insertar_ord(lista , e); // in s e r t a s in r e p e t i c i on}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: eliminar(int e){

eliminar_ord(lista , e);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Conjunto :: pertenece(int e) const{

return (buscar_ord(lista , e) != NULL);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Conjunto :: es_subconjunto(const Conjunto& a) const{

// es subconjunto s i todos l o s e lementos de l conjunto ac tua l// pertenecen tambien a l conjunto e s p e c i f i c a do como parametroPNodo ptr = lista ;while ((ptr != NULL)&& a.pertenece(ptr->dato)) {

ptr = ptr->sig ;}return (ptr == NULL);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: union_conj(const Conjunto& a, const Conjunto& b){

PNodo lst = duplicar(a.lista );PNodo ptr = b.lista ;while (ptr != NULL) {

insertar_ord(lst , ptr->dato); // in s e r t a s in r e p e t i c i onptr = ptr->sig ;

}

71

Page 72: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

destruir(lista);lista = lst;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: interseccion(const Conjunto& a, const Conjunto& b){

PNodo lst = NULL;PNodo ptr = a.lista ;while (ptr != NULL) {

if (b.pertenece(ptr->dato)) {insertar_ord(lst , ptr->dato); // in s e r t a s in r e p e t i c i on

}ptr = ptr->sig ;

}destruir(lista);lista = lst;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: diferencia(const Conjunto& a, const Conjunto& b){

PNodo lst = NULL;PNodo ptr = a.lista ;while (ptr != NULL) {

if ( ! b.pertenece(ptr->dato)) {insertar_ord(lst , ptr->dato); // in s e r t a s in r e p e t i c i on

}ptr = ptr->sig ;

}destruir(lista);lista = lst;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: diferencia_simetrica(const Conjunto& a, const Conjunto& b){

Conjunto a_b , b_a;a_b.diferencia(a, b);b_a.diferencia(b, a);union_conj(a_b , b_a);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto :: escribir () const{

cout << "{ ";PNodo ptr = lista;while (ptr != NULL) {

cout << ptr->dato << " " ;ptr = ptr->sig ;

}cout << "}";

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Conjunto ::leer(){

clear ();int e;cin >> e ;while (e != 0) {

incluir(e);cin >> e ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Aux i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que cont iene e l elemento// i g u a l a ( dt ) . Si no se encuentra , entonces devue l ve NULLConjunto :: PNodo Conjunto :: buscar_ord(PNodo lst , int dt) const{

PNodo ptr = lst ;while ((ptr != NULL)&&(ptr->dato < dt)) {

ptr = ptr->sig ;}if ((ptr != NULL)&&(ptr->dato != dt)) {

ptr = NULL;

72

Page 73: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}

return ptr ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento de forma ordenada en ( l s t ) , que debe e s t a r// ordenada ( s in r e p e t i c i on )void Conjunto :: insertar_ord(PNodo& lst , int dt) const{

if ((lst == NULL) || (dt < lst->dato)) {PNodo aux = new Nodo ;aux->dato = dt ;aux->sig = lst ;lst = aux ;

} else if (dt > lst->dato) {PNodo ant = lst ;PNodo act = ant->sig ;while ((act != NULL) && (act->dato < dt)) {

ant = act ;act = act->sig ;

}if ((act == NULL) || (act->dato != dt)) {

PNodo aux = new Nodo ;aux->dato = dt ;aux->sig = ant->sig ;ant->sig = aux ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l s t ) e l e lemento cuyo dato es i g u a l a ( dt ) , s i e x i s t e// La l i s t a ( l s t ) se encuentra ordenadavoid Conjunto :: eliminar_ord(PNodo& lst , int dt) const{

if (lst != NULL) {if (lst->dato == dt) {

PNodo aux = lst ;lst = lst->sig ;delete aux ;

} else {PNodo ant = lst ;PNodo act = ant->sig ;while ((act != NULL)&&(act->dato < dt)) {

ant = act;act = act->sig;

}if ((act != NULL) && (act->dato == dt)) {

ant->sig = act->sig ;delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a una nueva l s t r e su l t ado de dup l i c a r en// memoria dinamica l a l s t r e c i b i d a como parametroConjunto :: PNodo Conjunto :: duplicar(PNodo lst) const{

PNodo nueva = NULL;if (lst != NULL) {

nueva = new Nodo ;nueva->dato = lst->dato ;PNodo u = nueva ;PNodo p = lst->sig ;while (p != NULL) {

u->sig = new Nodo ;u->sig->dato = p->dato ;u = u->sig ;p = p->sig ;

}u->sig = NULL ;

}return nueva;

}

73

Page 74: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Destruye todos l o s e lementos de l a l s t , l i b e rando// todos l o s nodos de memoria dinamica . ( l s t ) queda vac iavoid Conjunto :: destruir(PNodo& lst) const{

while (lst != NULL) {PNodo ptr = lst ;lst = lst->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include "conjuntos.hpp"using namespace std;using namespace umalcc;

void escribir(const string& msj , const Conjunto& c){

cout << msj;c.escribir ();cout << endl;

}int main(){

Conjunto c1 , c2 , c3;cout << "Introduzca elementos del conjunto: [0 -> fin]: ";c1.leer ();escribir("C1: ", c1);cout << "Introduzca elementos del conjunto: [0 -> fin]: ";c2.leer ();escribir("C2: ", c2);cout << "Es subconjunto: " << boolalpha << c1.es_subconjunto(c2) << endl;c3.union_conj(c1, c2);escribir("Union: ", c3);c3.interseccion(c1 , c2);escribir("Interseccion: ", c3);c3.diferencia(c1, c2);escribir("Diferencia: ", c3);c3.diferencia_simetrica(c1 , c2);escribir("Diferencia Simetrica: ", c3);

}� �3. Hay muchas aplicaciones en las que se deben almacenar en la memoria matrices de grandes dimensiones. Si

la mayoría de los elementos de la matriz son ceros, ésta, en lugar de almacenarse en un array bidimensional,se puede representar más eficientemente utilizando listas enlazadas donde los elementos nulos y filas nulasno serán almacenadas.

Así, defina la clase MatrizDispersa en el espacio de nombres umalcc_aux que represente dicha abstraccióny proporcione las siguientes operaciones:

Utilice la siguiente estructura para implementar la matriz dispersa, donde hay una lista enlazada ordenada(ascendentemente por número de fila) para acceder por filas, y a partir de un determinado nodo fila, sepuede acceder a la lista enlazada ordenada (ascendentemente por número de columna) donde se encuentranlos elementos pertenecientes a dicha fila y a la columna especificada en el nodo cuyo valor es distinto decero. Por ejemplo, la siguiente figura representa la siguiente matriz:

74

Page 75: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

0

2

3

0 40 1 60 3 90

0 50 2 75

1 67 2 83

4

4

nfil

ncol

filas

40 60 0 900 0 0 050 0 75 00 67 83 0

con las siguientes especificaciones adicionales:

El método obtener permite conocer el valor de un determinado elemento de la matriz especificadopor su fila y columna correspondiente. En caso de que dicho elemento no esté almacenado, entoncessu valor es cero.

El método poner permite asignar un determinado valor a un determinado elemento de la matrizespecificado por su fila y columna correspondiente.Solo se almacenarán los elementos de valor distinto de cero, considerando que si un elemento noestá almacenado, es que su valor es cero. Si una fila no tiene elementos distintos de cero, el nodocorrespondiente a dicha fila no será almacenado.Si el valor a almacenar es distinto de cero, si el elemento ya existe, se reemplazará su valor, en otrocaso se añadirá a la estructura.Si el valor a almacenar es cero, habrá que eliminar dicho elemento de la estructura si es que existe.Si como consecuencia de ello, la fila queda sin elementos, habrá que eliminar el nodo correspondientede dicha lista.

Solución: matdisp.hpp� �#ifndef matdisp_hpp_#define matdisp_hpp_namespace umalcc_aux {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−const double ERROR_PRECISION = 1e-6;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−class MatrizDispersa {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−˜ MatrizDispersa ();// DestructorMatrizDispersa ();// Constructor por Defecto : matriz vac iaMatrizDispersa(int nfils , int ncols );// Constructor e s p e c i f i c o : crea matriz de ( n f i l s ) x ( nco l s ) con va l o r e s 0MatrizDispersa(const MatrizDispersa& m);// Constructor de copiaMatrizDispersa& operator=(const MatrizDispersa& m);// Operador de Asignacionvoid clear(int nfils , int ncols);// Elimina todos l o s e lementos de l a matriz ac tua l , y as igna// a l a matriz a c tua l una matriz de ( n f i l s ) x ( nco l s ) con va l o r e s 0int nfils () const;// Devuelve e l numero de f i l a s de l a matriz a c tua lint ncols () const;// Devuelve e l numero de columnas de l a matriz ac tua lvoid poner(int f, int c, double val);// PRECOND: (0 <= f && f < n f i l s ( ) && 0 <= c && c < nco l s ( ) )// Asigna e l va l o r ( va l ) a l elemento de l a f i l a ( f )// y columna ( c ) de l a matriz a c tua ldouble obtener(int f, int c) const;// PRECOND: ( f < n f i l s ( ) && c < nco l s ( ) )// Devuelve e l va l o r de l elemento de l a f i l a ( f )// y columna ( c ) de l a matriz a c tua l//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

75

Page 76: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Elem ;typedef Elem* PElem;struct Elem {

PElem sig;int columna;double valor;

};struct Fila ;typedef Fila* PFila;struct Fila {

PFila sig;int fila;PElem elems;

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void destruir(PElem& lista) const ;PElem duplicar(PElem lista) const ;PElem buscar_ord(PElem lista , int c) const ;void insertar_ord(PElem& lista , int c, PElem& elem) const ;void eliminar_ord(PElem& lista , int c) const ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void destruir(PFila& lista) const ;PFila duplicar(PFila lista) const ;PFila buscar_ord(PFila lista , int f) const ;void insertar_ord(PFila& lista , int f, PFila& elem) const ;void eliminar_ord(PFila& lista , int f) const ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar(int f, int c) ;void insertar(int f, int c, double val) ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int nfilas;int ncolumnas;PFila filas;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

Solución: matdisp.cpp� �#include "matdisp.hpp"#include <cstddef>#include <cassert>using namespace std;using namespace umalcc_aux;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−// Valor ab so l u t o de un numeroinline double abs(double a){

return (a >= 0) ? a : -a;}//−−−−−−−−−−−−−−−−−−−−−−−−−// Dos numeros r e a l e s son i g u a l e s s i l a d i s t anc i a que l o s// separa es l o su f i c i en t emen te pequenyainline bool iguales(double a, double b){

return abs(a-b) <= ERROR_PRECISION;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

76

Page 77: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc_aux {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Elem −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void MatrizDispersa :: destruir(PElem& lista) const{

while (lista != NULL) {PElem ptr = lista ;lista = lista->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa ::PElem MatrizDispersa :: duplicar(PElem lista) const{

PElem nueva = NULL;if (lista != NULL) {

nueva = new Elem ;nueva->columna = lista->columna ;nueva->valor = lista->valor ;PElem u = nueva ;PElem p = lista->sig ;while (p != NULL) {

u->sig = new Elem ;u->sig->columna = p->columna ;u->sig->valor = p->valor ;u = u->sig ;p = p->sig ;

}u->sig = NULL ;

}return nueva;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa ::PElem MatrizDispersa :: buscar_ord(PElem lista , int c) const{

PElem ptr = lista ;while ((ptr != NULL) && (ptr->columna < c)) {

ptr = ptr->sig ;}if ((ptr != NULL) && (ptr->columna != c)) {

ptr = NULL;}return ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// devue l ve e l puntero a l nodo que ha creado (o a l que ya e x i s t i a )void MatrizDispersa :: insertar_ord(PElem& lista , int c, PElem& elem) const{

if ((lista == NULL) || (c < lista->columna )){elem = new Elem ;elem->columna = c ;elem->valor = 0.0 ;elem->sig = lista ;lista = elem ;

} else if (c == lista->columna) {elem = lista;

} else {PElem ant = lista ;PElem act = ant->sig ;while ((act != NULL) && (act->columna < c)) {

ant = act ;act = act->sig ;

}if ((act == NULL) || (act->columna != c)) {

elem = new Elem ;elem->columna = c ;elem->valor = 0.0 ;elem->sig = ant->sig ;ant->sig = elem ;

} else {

77

Page 78: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

elem = ant->sig;}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void MatrizDispersa :: eliminar_ord(PElem& lista , int c) const{

if (lista != NULL) {if (lista->columna == c) {

PElem aux = lista ;lista = lista->sig ;delete aux ;

} else {PElem ant = lista ;PElem act = ant->sig ;while ((act != NULL)&&(act->columna < c)) {

ant = act;act = act->sig;

}if ((act != NULL)&&(act->columna == c)) {

ant->sig = act->sig ;delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Fi la −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void MatrizDispersa :: destruir(PFila& lista) const{

while (lista != NULL) {PFila ptr = lista ;lista = lista->sig ;destruir(ptr->elems);delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa ::PFila MatrizDispersa :: duplicar(PFila lista) const{

PFila nueva = NULL;if (lista != NULL) {

nueva = new Fila ;nueva->fila = lista->fila ;nueva->elems = duplicar(lista->elems) ;PFila u = nueva ;PFila p = lista->sig ;while (p != NULL) {

u->sig = new Fila ;u->sig->fila = p->fila ;u->sig->elems = duplicar(p->elems) ;u = u->sig ;p = p->sig ;

}u->sig = NULL ;

}return nueva;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa ::PFila MatrizDispersa :: buscar_ord(PFila lista , int f) const{

PFila ptr = lista ;while ((ptr != NULL) && (ptr->fila < f)) {

ptr = ptr->sig ;}if ((ptr != NULL) && (ptr->fila != f)) {

ptr = NULL;}return ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// devue l ve e l puntero a l nodo que ha creado (o a l que ya e x i s t i a )void MatrizDispersa :: insertar_ord(PFila& lista , int f, PFila& elem) const

78

Page 79: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{if ((lista == NULL) || (f < lista->fila )){

elem = new Fila ;elem->fila = f ;elem->elems = NULL ;elem->sig = lista ;lista = elem ;

} else if (f == lista->fila) {elem = lista;

} else {PFila ant = lista ;PFila act = ant->sig ;while ((act != NULL) && (act->fila < f)) {

ant = act ;act = act->sig ;

}if ((act == NULL) || (act->fila != f)) {

elem = new Fila ;elem->fila = f ;elem->elems = NULL ;elem->sig = ant->sig ;ant->sig = elem ;

} else {elem = ant->sig;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void MatrizDispersa :: eliminar_ord(PFila& lista , int f) const{

if (lista != NULL) {if (lista->fila == f) {

PFila aux = lista ;lista = lista->sig ;destruir(aux->elems);delete aux ;

} else {PFila ant = lista ;PFila act = ant->sig ;while ((act != NULL)&&(act->fila < f)) {

ant = act;act = act->sig;

}if ((act != NULL)&&(act->fila == f)) {

ant->sig = act->sig ;destruir(act->elems);delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// e l imina e l elemento [ f ] [ c ] s i e x i s t e .// s i f i l a vacia , entonces e l imina f i l avoid MatrizDispersa :: eliminar(int f, int c){

assert(f < nfils() && c < ncols ());PFila fil = buscar_ord(filas , f);if (fil != NULL) {

eliminar_ord(fil->elems , c);if (fil->elems == NULL) {

eliminar_ord(filas , f); // aqui hace recor r ido dob l e}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// i n s e r t a r elemento [ f ] [ c ] . Si no e x i s t e f i l a , l a crea// s i ya e x i s t e e l elemento , s u s t i t u y e e l va lor , en// otro caso , i n s e r t a e l e lementovoid MatrizDispersa :: insertar(int f, int c, double val){

assert(f < nfils() && c < ncols ());

79

Page 80: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

PFila fil;insertar_ord(filas , f, fil);PElem elem;insertar_ord(fil->elems , c, elem);elem->valor = val;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− MatrizDispersa −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa :: ˜ MatrizDispersa () { destruir(filas ); }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa :: MatrizDispersa () : nfilas (0), ncolumnas (0), filas(NULL) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa :: MatrizDispersa(int nf, int nc)

: nfilas(nf), ncolumnas(nc), filas(NULL) {}//−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa :: MatrizDispersa(const MatrizDispersa& m)

: nfilas(m.nfilas), ncolumnas(m.ncolumnas), filas(duplicar(m.filas)) {}//−−−−−−−−−−−−−−−−−−−−−−−−−MatrizDispersa& MatrizDispersa :: operator=(const MatrizDispersa& m){

if (this != &m) {destruir(filas);nfilas = m.nfilas;ncolumnas = m.ncolumnas;filas = duplicar(m.filas);

}return *this;

}//−−−−−−−−−−−−−−−−−−−−−−−−−void MatrizDispersa :: clear(int nf , int nc){

destruir(filas);nfilas = nf;ncolumnas = nc;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−int MatrizDispersa ::nfils () const{

return nfilas;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−int MatrizDispersa ::ncols () const{

return ncolumnas;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// poner un va l o r en [ f ] [ c ] , s i v a l es cero , entonces l o e l iminavoid MatrizDispersa :: poner(int f, int c, double val){

assert(f < nfils() && c < ncols ());if (iguales(val , 0.0)) {

eliminar(f,c);} else {

insertar(f,c, val);}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−// busca e l elemento , s i no e x i s t e , entonces va l o r cero// en otro caso , devue l ve e l va l o r de l elementodouble MatrizDispersa :: obtener(int f, int c) const{

assert(f < nfils() && c < ncols ());double res = 0.0;PFila fil = buscar_ord(filas , f);if (fil != NULL) {

PElem elem = buscar_ord(fil->elems , c);if (elem != NULL) {

res = elem->valor;}

}return res;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

80

Page 81: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}� �4. Se debe diseñar e implementar el tipo abstracto de datos Matriz de números reales en el espacio de nombre

umalcc, junto con las operaciones necesarias para su gestión y tratamiento. Utilice para su implementaciónla clase MatrizDispersa realizada en el ejercicio anterior.

Solución: matriz.hpp� �#ifndef matriz_hpp_#define matriz_hpp_#include "matdisp.hpp"namespace umalcc {

class Matriz {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// ~Matriz ( ) ;// DestructorMatriz ();// Constructor por Defecto : matriz vac iaMatriz(int nfils , int ncols );// Constructor e s p e c i f i c o : crea matriz de ( n f i l s ) x ( nco l s ) con va l o r e s 0// Matriz ( const Matriz& m) ;// Constructor de copia// Matriz& operator=(const Matriz& m) ;// Operador de Asignacionvoid clear(int nfils , int ncols);// Elimina todos l o s e lementos de l a matriz ac tua l , y as igna// a l a matriz a c tua l una matriz de ( n f i l s ) x ( nco l s ) con va l o r e s 0int nfils () const;// Devuelve e l numero de f i l a s de l a matriz a c tua lint ncols () const;// Devuelve e l numero de columnas de l a matriz ac tua lvoid poner(int f, int c, double val);// PRECOND: (0 <= f && f < n f i l s ( ) && 0 <= c && c < nco l s ( ) )// Asigna e l va l o r ( va l ) a l elemento de l a f i l a ( f )// y columna ( c ) de l a matriz a c tua ldouble obtener(int f, int c) const;// PRECOND: ( f < n f i l s ( ) && c < nco l s ( ) )// Devuelve e l va l o r de l elemento de l a f i l a ( f )// y columna ( c ) de l a matriz a c tua lvoid sumar(const Matriz& a, const Matriz& b);// Asigna a l a matriz a c tua l e l r e su l t ado de// sumar l a s matr ices (a ) y ( b )void restar(const Matriz& a, const Matriz& b);// Asigna a l a matriz a c tua l e l r e su l t ado de// r e s t a r l a s matr ices (a ) y ( b )void multiplicar(const Matriz& a, const Matriz& b);// Asigna a l a matriz a c tua l e l r e su l t ado de// mu l t i p l i c a r l a s matr ices (a ) y ( b )void escribir () const;// Muestra en pan t a l l a e l contenido de l a matriz a c tua lvoid leer ();// Lee de t e c l ado e l va l o r de l a matriz ac tua l ,// Lee n f i l s , nco l s y l o s va l o r e s de l o s e lementos//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−umalcc_aux :: MatrizDispersa base;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

Solución: matriz.cpp� �#include "matriz.hpp"#include <iostream>

81

Page 82: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#include <iomanip>#include <cassert>#include "matdisp.hpp"using namespace std;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Generados automaticamente por e l compilador//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// ~Matriz ( ) ; // Destructor// Matriz ( const Matriz& m) ; // Constructor de copia// Matriz& operator=(const Matriz& m) ; // Operador de Asignacion//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Matriz :: Matriz () : base() {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Matriz :: Matriz(int nf, int nc) : base(nf , nc) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int Matriz ::nfils () const{

return base.nfils ();}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−int Matriz ::ncols () const{

return base.ncols ();}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: clear(int nf , int nc){

base.clear(nf, nc);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: poner(int f, int c, double val){

assert(f < nfils() && c < ncols ());base.poner(f, c, val);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Matriz :: obtener(int f, int c) const{

assert(f < nfils() && c < ncols ());return base.obtener(f, c);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: sumar(const Matriz& m1, const Matriz& m2){

assert ((this != &m1)&&(this != &m2));if ((m1.nfils() != m2.nfils ())||(m1.ncols() != m2.ncols ())) {

clear(0, 0);} else {

clear(m1.nfils(), m1.ncols ());for (int f = 0; f < nfils (); ++f) {

for (int c = 0; c < ncols (); ++c) {poner(f,c, m1.obtener(f,c) + m2.obtener(f,c));

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: restar(const Matriz& m1, const Matriz& m2){

assert ((this != &m1)&&(this != &m2));if ((m1.nfils() != m2.nfils ())||(m1.ncols() != m2.ncols ())) {

clear(0, 0);} else {

clear(m1.nfils(), m1.ncols ());for (int f = 0; f < nfils (); ++f) {

for (int c = 0; c < ncols (); ++c) {poner(f,c, m1.obtener(f,c) - m2.obtener(f,c));

}}

82

Page 83: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: multiplicar(const Matriz& m1 , const Matriz& m2){

assert ((this != &m1)&&(this != &m2));if ((m1.ncols() != m2.nfils ())) {

clear(0, 0);} else {

clear(m1.nfils(), m2.ncols ());for (int f = 0; f < nfils (); ++f) {

for (int c = 0; c < ncols (); ++c) {double suma = 0.0;for (int k = 0; k < m1.ncols (); ++k) {

suma += m1.obtener(f,k) * m2.obtener(k,c);}poner(f,c, suma);

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz :: escribir () const{

cout << std:: setprecision (4);for (int f = 0; f < nfils (); ++f) {

for (int c = 0; c < ncols (); ++c) {cout << std::setw (6) << obtener(f,c) << " ";

}cout << std::endl;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Matriz ::leer(){

int nf, nc;cin >> nf >> nc; // l e e numero de f i l a s y columnasclear(nf , nc);for (int f = 0; f < nfils (); ++f) {

for (int c = 0; c < ncols (); ++c) {double x;cin >> x; // l e e cada elemento de l a matrizponer(f,c, x);

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �5. Implemente un programa principal que permita comprobar el funcionamiento del tipo abstracto de datos

Matriz definido previamente.

Solución: main.cpp� �#include <iostream>#include "matriz.hpp"using namespace std;using namespace umalcc;

int main(){

Matriz m1;cout << "Introduzca dimensiones y valores de la matriz: " ;m1.leer ();

Matriz m2;cout << "Introduzca dimensiones y valores de la matriz: " ;m2.leer ();

Matriz m3;m3.sumar(m1, m2);cout << "Suma: " << endl;m3.escribir ();

83

Page 84: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Matriz m4;m4.restar(m3, m2);cout << "Resta: " << endl;m4.escribir ();

Matriz m5;m5.multiplicar(m1 , m2);cout << "Multiplicacion: " << endl;m5.escribir ();

}� �6. Se dispone de un procesador con varias etapas, y de unas determinadas tareas que se ejecutarán pasando

sucesivamente por todas las etapas del procesador, desde la primera hasta la última. Como el procesadordispone de varias etapas, es posible que esté procesando simultáneamente diferentes tareas. Por tanto,una tarea sólo podrá pasar a la siguiente etapa si ésta se encuentra libre. La siguiente figura muestra unprocesador con cuatro etapas y dos tareas, la tarea T1 va ejecutándose por la etapa e2 y la tarea T2 vaejecutándose por la etapa e4.

procesador

e1 e3 e4e2

t1 t2

Se debe diseñar la estructura de datos necesaria para representar la información del estado del procesadoren cada momento. Para ello, se sigue el esquema mostrado en la siguiente figura. Como se puede observarcada etapa se representa con dos elementos, una lista de nodos intermedios con tantos nodos como réplicas(véase más adelante) haya de la etapa (en el ejemplo sólo se muestra una réplica por cada etapa) y loscorrespondientes nodos de etapa. Cada nodo de etapa contendrá su identificador, el número de la tareaque está ejecutando (un número cero indica que está libre, es decir, no está ejecutando ninguna tarea),y un puntero al primer nodo de la lista de nodos intermedios de la siguiente etapa. También se puedeobservar que la tarea T1 se está ejecutando en la etapa 2 y la tarea T2 se está ejecutando en la etapa 4.

0

1

1

2

0

3

2

4procesador

Es posible que en un determinado momento interese ampliar la potencia de una determinada etapa. Paraello, se replicará dicha etapa haciendo tantos duplicados de la misma como se desee. Así mismo, es posibleque interese reducir la potencia de una determinada etapa, para ello se eliminarán réplicas de la misma.

Defina el TAD Procesador que implemente la estructura de datos especificada anteriormente, y que propor-cione los siguientes métodos públicos, así mismo, también se deberá implementar un programa principalque permita su utilización:

a) ElConstructor recibe el número de etapas que tiene un determinado procesador, y crea la estructurabase de étapas sin replicación y todas en estado inicial libre, como se muestra en la siguiente figurapara un procesador de 4 etapas:

0

1

0

2

0

3

0

4procesador

b) El Destructor libera todos los recursos asociados al objeto que está siendo destruido.

c) El método Mostrar muestra en pantalla la estructura interna de un procesador. Por ejemplo, parala figura anterior:

Etapa: 1Replica: libreReplica: libre

Etapa: 2Replica: tarea 1Replica: tarea 2

Etapa: 3

84

Page 85: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Replica: libreEtapa: 4

Replica: libre

d) Un métodoReplicar, que se usará para ampliar la potencia de una determinada etapa del procesadoractual. Recibe como parámetros el identificador de la etapa a replicar y el número de réplicas quedeseamos añadir. Las réplicas añadidas tendrán el estado inicial libre (no tienen asignadas la ejecuciónde ninguna tarea).Las réplicas se añadirán a la estructura añadiendo (en cualquier posición SALVO AL PRINCIPIO)nodos a la lista de nodos intermedios correspondiente a la etapa y nodos de etapa apuntados desde losnodos intermedios añadidos. Como se puede observar, todas las réplicas añadidas deben apuntar alprimer nodo intermedio de la etapa siguiente (salvo en la última etapa). La siguiente figura muestrael resultado de añadir dos réplicas de la etapa 2 a la figura anterior:

0

1

1

2

0

3

2

4

0

2

0

2

procesador

La siguiente figura muestra el resultado de añadir una réplica de la etapa 1 a la figura anterior:

0

1

1

2

0

3

2

4

0

2

0

2

0

1

procesador

e) Un método para Compactar que se usará para disminuir el número de réplicas de una etapa delprocesador actual. Para ello, recibe como parámetro el identificador de la etapa a compactar yelimina todas las réplicas de dicha etapa cuyo estado sea libre (no esté ejecutando ninguna tarea).Al compactar etapas habrá que tener en cuenta que:

De cada etapa deberá quedar al menos una réplica.Las réplicas que estén ejecutando alguna tarea no pueden ser eliminadas.No se podrá liberar la memoria ocupada por el primer nodo de la lista de nodos intermedios deuna etapa (pues sirve de enlace entre una etapa y la siguiente). En caso de que la compactaciónrequiera eliminar la primera réplica de una etapa (porque esté libre), el puntero al nodo deetapa del primer nodo de la lista de nodos intermedios pasará a apuntar a un nodo de etapa quepermanezca tras la compactación. Por ejemplo, para la siguiente figura:

0

1

0

2

0

3

0

4

2

2

1

2

0

1

procesador

la siguiente figura es el resultado de compactar la etapa 2 de la figura anterior:

85

Page 86: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

0

1

0

3

0

4

2

2

1

2

0

1

procesador

f ) El método AvanzarEvaluacion intenta avanzar una tarea de una determinada etapa a la siguiente.Para ello, recibe como parámetro el número de tarea (distinto de cero) que pretende avanzar a lasiguiente etapa.

Si la tarea es nueva, buscará una réplica libre de la primera etapa del procesador. Si no hayréplicas libres en esta primera etapa, entonces lanzará una excepción.Si la tarea se está ejecutando en la última etapa del procesador, entonces la tarea habrá terminadosu ejecución, y su número desaparecerá de la estructura.En otro caso, intenta avanzar la tarea desde la réplica de la etapa en que se encuentra ejecutándosehasta alguna réplica libre de la siguiente etapa. Si no hay ninguna réplica libre de la siguienteetapa, entonces lanzará una excepción.

g) Así mismo, también deberá ser posible realizar la copia y asignación (duplicación) de la estructurade datos que representa a un determinado procesador.

Solución: procesador.hpp� �#ifndef procesador_hpp_#define procesador_hpp_namespace umalcc {

class Procesador {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−˜ Procesador ();Procesador ();Procesador(unsigned n_etapas );Procesador(const Procesador& o);Procesador& operator=(const Procesador& o);void mostrar () const;void replicar(unsigned id_etapa , unsigned n, bool& ok);void compactar(unsigned id_etapa , bool& ok);void avanzar_evaluacion(unsigned tarea , bool& ok);//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Ctes y Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−static const unsigned REPLICA_LIBRE = 0;//−−−−−−−−−−−−−−−−−−−−−−−−−struct Nodo;typedef Nodo* PNodo;struct Etapa;typedef Etapa* PEtapa;struct Nodo {

PEtapa et;PNodo sig;//−−−−−−−−−−−−−−−−−−−−−Nodo(PEtapa e, PNodo s) ;

};struct Etapa {

unsigned id_etapa;unsigned tarea;PNodo sig;//−−−−−−−−−−−−−−−−−−−−−Etapa(unsigned i, unsigned t, PNodo s) ;

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

86

Page 87: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void destruir ();void destruir(PNodo& lista);void duplicar(const Procesador& o);void duplicar_resto(const Procesador& o);void duplicar_base(const Procesador& o);void duplicar(PNodo& lista , PNodo origen , PNodo sig);PNodo buscar(unsigned id_etapa) const;void mostrar(PNodo lista) const;PNodo buscar_tarea(PNodo lista , unsigned tarea) const;PNodo buscar_tarea(unsigned tarea) const;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo proc;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

Solución: procesador.cpp� �#include "procesador.hpp"#include <iostream>#include <cassert>using namespace std;using namespace umalcc;namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Procesador ::Nodo::Nodo(PEtapa e, PNodo s) : et(e), sig(s) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Procesador ::Etapa:: Etapa(unsigned i, unsigned t, PNodo s)

: id_etapa(i), tarea(t), sig(s) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Procesador :: ˜ Procesador (){

destruir ();}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Procesador :: Procesador () : proc(NULL) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// crea un procesador con 'n ' etapas s imp les ( s in r e p l i c a s )Procesador :: Procesador(unsigned n_etapas)

: proc(NULL){

if (n_etapas > 0) {proc = new Nodo(new Etapa(1, REPLICA_LIBRE , NULL), NULL);PNodo u = proc;for (unsigned i = 2; i <= n_etapas; ++i) {

u->et->sig = new Nodo(new Etapa(i, REPLICA_LIBRE , NULL), NULL);u = u->et->sig;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// copia ( dup l i ca ) un procesadorProcesador :: Procesador(const Procesador& o)

: proc(NULL){

duplicar(o);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// asigna ( dup l i ca ) un procesadorProcesador& Procesador :: operator=(const Procesador& o){

if (this != &o) {duplicar(o);

}return *this;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// crea n r e p l i c a s de una etapavoid Procesador :: replicar(unsigned id_etapa , unsigned n, bool& ok){

87

Page 88: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

PNodo ptr = buscar(id_etapa );if (ptr == NULL) {

ok = false;} else {

ok = true;// In s e r t a r n etapas con i d e n t i f i c a d o r ' id_etapa ' a l i n i c i o de// ptr−>sig , donde e l s i g u i e n t e de cada etapa es i g u a l a l// s i g u i e n t e de l a etapa i n i c i a lfor (unsigned i = 0; i < n; ++i) {

ptr->sig = new Nodo(new Etapa(id_etapa , REPLICA_LIBRE ,ptr->et->sig),

ptr->sig);}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// compacta l a s r e p l i c a s l i b r e s de una etapavoid Procesador :: compactar(unsigned id_etapa , bool& ok){

PNodo ptr = buscar(id_etapa );if (ptr == NULL) {

ok = false;} else {

ok = true;// e l iminar a pa r t i r d e l segundoPNodo ant = ptr;PNodo act = ptr->sig;while (act != NULL) {

if (act->et->tarea == REPLICA_LIBRE) {ant->sig = act->sig;delete act->et;delete act;

} else {ant = act;

}act = ant->sig;

}// comprobar e l primeroif ((ptr->sig != NULL)&&(ptr->et->tarea == REPLICA_LIBRE )) {

delete ptr->et;ptr->et = ptr->sig->et;act = ptr->sig;ptr->sig = act->sig;delete act;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// des t ruye una l i s t a de nodos intermediosvoid Procesador :: destruir(PNodo& lista){

while (lista != NULL) {PNodo aux = lista;lista = lista->sig;delete aux->et;delete aux;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// des t ruye un procesadorvoid Procesador :: destruir (){

while (proc != NULL) {assert(proc->et != NULL);PNodo aux = proc;proc = proc->et->sig;destruir(aux);

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// dup l i ca una l i s t a de nodos intermedios y sus e tapas asoc iadas// (a pa r t i r d e l segundo nodo )void Procesador :: duplicar(PNodo& lista , PNodo origen , PNodo sig){

88

Page 89: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

if (origen != NULL) {PNodo ou = origen;lista = new Nodo(new Etapa(ou->et->id_etapa , ou->et->tarea , sig), NULL);PNodo u = lista;ou = ou->sig;while (ou != NULL) {

u->sig = new Nodo(new Etapa(ou->et->id_etapa , ou->et->tarea , sig), NULL);u = u->sig;ou = ou->sig;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// dup l i ca l a s l i s t a s de nodos intermedios y sus e tapas asoc iadas// (a pa r t i r d e l segundo nodo ) para todas l a s e tapas de l procesadorvoid Procesador :: duplicar_resto(const Procesador& o){

PNodo ptr_o = o.proc;PNodo ptr = proc;while (ptr != NULL) {

duplicar(ptr->sig , ptr_o->sig , ptr->et->sig);ptr = ptr->et->sig;ptr_o = ptr_o->et->sig;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// dup l i ca l a s e tapas base de l procesadorvoid Procesador :: duplicar_base(const Procesador& o){

if (o.proc != NULL) {PNodo ou = o.proc;proc = new Nodo(new Etapa(ou->et->id_etapa , ou->et->tarea , NULL), NULL);PNodo u = proc;ou = ou->et->sig;while (ou != NULL) {

u->et->sig = new Nodo(new Etapa(ou->et->id_etapa , ou->et->tarea , NULL), NULL);u = u->et->sig;ou = ou->et->sig;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// dup l i ca un procesadorvoid Procesador :: duplicar(const Procesador& o){

destruir ();if (o.proc != NULL) {

duplicar_base(o);duplicar_resto(o);

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// busca una etapa en e l procesadorProcesador ::PNodo Procesador :: buscar(unsigned id_etapa) const{

PNodo ptr = proc;while ((ptr != NULL)&&(id_etapa != ptr->et->id_etapa )) {

ptr = ptr->et->sig;}return ptr;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// muestra una l i s t a de r e p l i c a s de una etapavoid Procesador :: mostrar(PNodo lista) const{

if (lista != NULL) {cout << "Etapa: " << lista->et->id_etapa << endl;PNodo ptr = lista;while (ptr != NULL) {

cout << " Replica: ";if (ptr->et->tarea == REPLICA_LIBRE) {

cout << "libre";} else {

cout << "tarea " << ptr->et->tarea;

89

Page 90: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}cout << endl;ptr = ptr->sig;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// muestra l a l i s t a de etapas y sus r e p l i c a svoid Procesador :: mostrar () const{

cout << "--------------" << endl;PNodo ptr = proc;while (ptr != NULL) {

mostrar(ptr);cout << "--------------" << endl;ptr = ptr->et->sig;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// busca una tarea en l a l i s t a de r e p l i c a s de una etapaProcesador ::PNodo Procesador :: buscar_tarea(PNodo lista , unsigned t) const{

PNodo ptr = lista;while ((ptr != NULL)&&(t != ptr->et->tarea)) {

ptr = ptr->sig;}return ptr;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// busca una tarea en e l procesadorProcesador ::PNodo Procesador :: buscar_tarea(unsigned t) const{

PNodo ptr = proc;PNodo pnodo = buscar_tarea(ptr , t);while ((ptr != NULL)&&(pnodo == NULL)) {

ptr = ptr->et->sig;pnodo = buscar_tarea(ptr , t);

}return pnodo;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// avanza l a eva luac ion de una determinada tareavoid Procesador :: avanzar_evaluacion(unsigned t, bool& ok){

assert(t != REPLICA_LIBRE );ok = true;PNodo orig = buscar_tarea(t);if (orig == NULL) {

PNodo dest = buscar_tarea(proc , REPLICA_LIBRE );if (dest == NULL) {

ok = false; // No hay r e p l i c a l i b r e} else {

dest->et->tarea = t;}

} else if (orig->et->sig == NULL) {orig->et->tarea = REPLICA_LIBRE;

} else {PNodo dest = buscar_tarea(orig->et->sig , REPLICA_LIBRE );if (dest == NULL) {

ok = false; // No hay r e p l i c a l i b r e}dest->et->tarea = t;orig->et->tarea = REPLICA_LIBRE;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �7. Diseñe un programa que permita utilizar el TAD especificado en el ejercicio anterior.

Solución: main.cpp� �90

Page 91: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#include <iostream>#include <string>#include "procesador.hpp"using namespace std;using namespace umalcc;

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "X. Fin" << endl;cout << "A. Crear Procesador" << endl;cout << "B. Replicar Etapa" << endl;cout << "C. Compactar Etapa" << endl;cout << "D. Avanzar Evaluacion" << endl;cout << "E. Copiar y Asignar Procesador" << endl;cout << "F. Mostrar" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'X')||((op >= 'A')&&(op <= 'F'))));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_num_etapa(unsigned& num_et){

cout << "Introduzca numero de etapas: ";cin >> num_et;

}void leer_etapa(unsigned& etapa){

cout << "Introduzca etapa: ";cin >> etapa;

}void leer_num_repl(unsigned& n){

cout << "Introduzca numero de replicas: ";cin >> n;

}void leer_tarea(unsigned& tarea){

cout << "Introduzca tarea: ";cin >> tarea;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void crear_procesador(Procesador& p){

unsigned ne;leer_num_etapa(ne);p = Procesador(ne);

}void replicar_etapa(Procesador& p){

unsigned e, n;bool ok;leer_etapa(e);leer_num_repl(n);p.replicar(e, n, ok);if (! ok) {

cout << "Error al replicar la etapa: " << e << endl;}

}void compactar_etapa(Procesador& p){

unsigned e;bool ok;leer_etapa(e);p.compactar(e, ok);if (! ok) {

cout << "Error al compactar la etapa: " << e << endl;

91

Page 92: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}}void avanzar_evaluacion(Procesador& p){

unsigned t;bool ok;leer_tarea(t);p.avanzar_evaluacion(t, ok);if (! ok) {

cout << "Error al avanzar la evaluacion de la tarea: " << t << endl;}

}void copiar_asig(Procesador& p){

Procesador copia = p;p = copia;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Procesador p;char op = ' ';do {

op = menu ();switch (op) {case 'A':

crear_procesador(p);break;

case 'B':replicar_etapa(p);break;

case 'C':compactar_etapa(p);break;

case 'D':avanzar_evaluacion(p);break;

case 'E':copiar_asig(p);break;

case 'F':p.mostrar ();break;

}} while (op != 'X');

}� �

92

Page 93: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Tema 4: Introducción a la Programación Orientada a Objetos1. Para calcular los sueldos de cada empleado de una factoría, se diseña la siguiente jerarquía de clases

polimórficas:

AgVentas

AgVentas_A AgVentas_B

Empleado

Directivo

Directivo_A Directivo_B

Factoria

La clase polimórfica Empleado representa un empleado general de una factoría, tiene un constructorque permite crear un objeto con el nombre (string) del empleado recibido como parámetro, yproporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• sueldo(): calcula y devuelve el sueldo del empleado. En caso de no tener información suficiente

para calcular el sueldo, entonces devolverá 0.• nombre(): devuelve el nombre del objeto empleado actual.

La clase polimórfica AgVentas representa un agente de ventas general, empleado de una factoría,tiene un constructor que permite crear un objeto con el nombre (string) del empleado recibidocomo parámetro, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• borrar_ventas(): reinicia a cero la cantidad total de ventas que acumula este agente de ventas.• anyadir_ventas(x): permite añadir una cantidad de euros recibida como parámetro a la canti-

dad total de ventas que acumula este agente de ventas.• ventas(): devuelve la cantidad total de ventas que acumula este agente de ventas.

La clase polimórfica AgVentas_A representa un agente de ventas de clase A, empleado de una factoría,tiene un constructor que permite crear un objeto con el nombre (string) del empleado recibido comoparámetro, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• sueldo(): redefine este método para calcular y devolver el sueldo de este tipo de agente de

ventas, según la siguiente ecuación:

sueldo = 2000.0 +10.0× total_ventas

100.0

La clase polimórfica AgVentas_B representa un agente de ventas de clase B, empleado de una factoría,tiene un constructor que permite crear un objeto con el nombre (string) del empleado recibido comoparámetro, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• sueldo(): redefine este método para calcular y devolver el sueldo de este tipo de agente de

ventas, según la siguiente ecuación:

sueldo = 1000.0 +5.0× total_ventas

100.0

La clase polimórfica Directivo representa un directivo general, empleado de una factoría, tieneun constructor que permite crear un objeto con el nombre (string) del empleado recibido comoparámetro, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.La clase polimórfica Directivo_A representa un directivo de clase A, empleado de una factoría, tieneun constructor que permite crear un objeto con el nombre (string) del empleado recibido comoparámetro, y proporciona los siguientes métodos públicos virtuales:

93

Page 94: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• sueldo(): redefine este método para calcular y devolver el sueldo de este tipo de directivos,según la siguiente ecuación:

sueldo = 5000.0

La clase polimórfica Directivo_B representa un directivo de clase B, empleado de una factoría, tieneun constructor que permite crear un objeto con el nombre (string) del empleado recibido comoparámetro, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• sueldo(): redefine este método para calcular y devolver el sueldo de este tipo de directivos,

según la siguiente ecuación:sueldo = 3000.0

La clase polimórfica Factoria representa una factoría con un máximo de 100 empleados, su construc-tor por defecto permite crear un nuevo objeto de clase Factoria sin ningún empleado, y proporcionalos siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• anyadir_empleado(e, ok): intenta añadir el empleado que recibe como primer parámetro (deentrada) a la lista de empleados de la factoría actual. Si la operación es posible o no, entoncesdevuelve true o false, respectivamente, en el segundo parámetro (de salida).

• sueldos(): muestra en pantalla tanto el nombre como el sueldo de cada empleado de la factoría.Finalmente, el programa principal creará un objeto de la clase Factoria, le añadirá empleados(Directivo_A, Directivo_B, AgVentas_A y AgVentas_B) y ventas acumuladas a los agentes de ven-tas, y calculará sus sueldos. Así mismo, tambien probará que la clonación de la factoría funcionaadecuadamente.

Solución: empleado.hpp� �#ifndef empleado_hpp__#define empleado_hpp__#include <string>namespace umalcc {

class Empleado {std:: string nmb;

public:Empleado(const std:: string& n);virtual ˜ Empleado ();virtual Empleado* clone () const;virtual double sueldo () const;virtual std:: string nombre () const;

protected:Empleado(const Empleado& o);

private:Empleado& operator=(const Empleado& o);

};}#endif� �

Solución: empleado.cpp� �#include "empleado.hpp"#include <string>using namespace std;namespace umalcc {

Empleado :: Empleado(const string& n): nmb(n) {}

Empleado :: ˜ Empleado () {}Empleado* Empleado ::clone () const{

return new Empleado(*this);}double Empleado :: sueldo () const{

return 0;}string Empleado :: nombre () const

94

Page 95: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{return nmb;

}Empleado :: Empleado(const Empleado& o)

: nmb(o.nmb) {}}� �

Solución: directivo.hpp� �#ifndef directivo_hpp__#define directivo_hpp__#include <string>#include "empleado.hpp"namespace umalcc {

class Directivo : public Empleado {public:

Directivo(const std:: string& n);virtual ˜ Directivo ();virtual Directivo* clone() const;

protected:Directivo(const Directivo& o);

private:Directivo& operator=(const Directivo& o);

};}#endif� �

Solución: directivo.cpp� �#include "directivo.hpp"#include <string>using namespace std;namespace umalcc {

Directivo :: Directivo(const string& n): Empleado(n) {}

Directivo :: ˜ Directivo () {}Directivo* Directivo :: clone() const{

return new Directivo(*this);}Directivo :: Directivo(const Directivo& o)

: Empleado(o) {}}� �

Solución: directivo_a.hpp� �#ifndef directivo_a_hpp__#define directivo_a_hpp__#include <string>#include "directivo.hpp"namespace umalcc {

class Directivo_A : public Directivo {public:

Directivo_A(const std:: string& n);virtual ˜ Directivo_A ();virtual Directivo_A* clone () const;virtual double sueldo () const;

protected:Directivo_A(const Directivo_A& o);

private:Directivo_A& operator=(const Directivo_A& o);

};}#endif� �

Solución: directivo_a.cpp� �#include "directivo_a.hpp"#include <string>

95

Page 96: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

using namespace std;namespace {

const double SUELDO_FIJO = 5000.0;}namespace umalcc {

Directivo_A :: Directivo_A(const string& n): Directivo(n) {}

Directivo_A :: ˜ Directivo_A () {}Directivo_A* Directivo_A :: clone() const{

return new Directivo_A(*this);}double Directivo_A :: sueldo () const{

return SUELDO_FIJO;}Directivo_A :: Directivo_A(const Directivo_A& o)

: Directivo(o) {}}� �

Solución: directivo_b.hpp� �#ifndef directivo_b_hpp__#define directivo_b_hpp__#include <string>#include "directivo.hpp"namespace umalcc {

class Directivo_B : public Directivo {public:

Directivo_B(const std:: string& n);virtual ˜ Directivo_B ();virtual Directivo_B* clone () const;virtual double sueldo () const;

protected:Directivo_B(const Directivo_B& o);

private:Directivo_B& operator=(const Directivo_B& o);

};}#endif� �

Solución: directivo_b.cpp� �#include "directivo_b.hpp"#include <string>using namespace std;namespace {

const double SUELDO_FIJO = 3000.0;}namespace umalcc {

Directivo_B :: Directivo_B(const string& n): Directivo(n) {}

Directivo_B :: ˜ Directivo_B () {}Directivo_B* Directivo_B :: clone() const{

return new Directivo_B(*this);}double Directivo_B :: sueldo () const{

return SUELDO_FIJO;}Directivo_B :: Directivo_B(const Directivo_B& o)

: Directivo(o) {}}� �

Solución: agventas.hpp� �#ifndef agventas_hpp__#define agventas_hpp__#include <string>

96

Page 97: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#include "empleado.hpp"namespace umalcc {

class AgVentas : public Empleado {double v;

public:AgVentas(const std:: string& n);virtual ˜ AgVentas ();virtual AgVentas* clone () const;virtual void borrar_ventas ();virtual void anyadir_ventas(double x);virtual double ventas () const;

protected:AgVentas(const AgVentas& o);

private:AgVentas& operator=(const AgVentas& o);

};}#endif� �

Solución: agventas.cpp� �#include "agventas.hpp"#include <string>using namespace std;namespace umalcc {

AgVentas :: AgVentas(const string& n): Empleado(n), v(0) {}

AgVentas :: ˜ AgVentas () {}AgVentas* AgVentas ::clone () const{

return new AgVentas(*this);}void AgVentas :: borrar_ventas (){

v = 0;}void AgVentas :: anyadir_ventas(double x){

v += x;}double AgVentas :: ventas () const{

return v;}AgVentas :: AgVentas(const AgVentas& o)

: Empleado(o), v(o.v) {}}� �

Solución: agventas_a.hpp� �#ifndef agventas_a_hpp__#define agventas_a_hpp__#include <string>#include "agventas.hpp"namespace umalcc {

class AgVentas_A : public AgVentas {public:

AgVentas_A(const std:: string& n);virtual ˜ AgVentas_A ();virtual AgVentas_A* clone() const;virtual double sueldo () const;

protected:AgVentas_A(const AgVentas_A& o);

private:AgVentas_A& operator=(const AgVentas_A& o);

};}#endif� �

97

Page 98: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: agventas_a.cpp� �#include "agventas_a.hpp"#include <string>using namespace std;namespace {

const double SUELDO_FIJO = 2000.0;const double PORCENTAJE = 10.0;

}namespace umalcc {

AgVentas_A :: AgVentas_A(const string& n): AgVentas(n) {}

AgVentas_A :: ˜ AgVentas_A () {}AgVentas_A* AgVentas_A ::clone () const{

return new AgVentas_A(*this);}double AgVentas_A :: sueldo () const{

double s = SUELDO_FIJO + PORCENTAJE * ventas () / 100.0;return s;

}AgVentas_A :: AgVentas_A(const AgVentas_A& o)

: AgVentas(o) {}}� �

Solución: agventas_b.hpp� �#ifndef agventas_b_hpp__#define agventas_b_hpp__#include <string>#include "agventas.hpp"namespace umalcc {

class AgVentas_B : public AgVentas {public:

AgVentas_B(const std:: string& n);virtual ˜ AgVentas_B ();virtual AgVentas_B* clone() const;virtual double sueldo () const;

protected:AgVentas_B(const AgVentas_B& o);

private:AgVentas_B& operator=(const AgVentas_B& o);

};}#endif� �

Solución: agventas_b.cpp� �#include "agventas_b.hpp"#include <string>using namespace std;namespace {

const double SUELDO_FIJO = 1000.0;const double PORCENTAJE = 5.0;

}namespace umalcc {

AgVentas_B :: AgVentas_B(const string& n): AgVentas(n) {}

AgVentas_B :: ˜ AgVentas_B () {}AgVentas_B* AgVentas_B ::clone () const{

return new AgVentas_B(*this);}double AgVentas_B :: sueldo () const{

double s = SUELDO_FIJO + PORCENTAJE * ventas () / 100.0;return s;

}AgVentas_B :: AgVentas_B(const AgVentas_B& o)

: AgVentas(o) {}}� �

98

Page 99: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: factoria.hpp� �#ifndef factoria_hpp__#define factoria_hpp__#include <array>#include "empleado.hpp"namespace umalcc {

class Factoria {static const int MAX_EMPL = 100;typedef std::array<Empleado*, MAX_EMPL> AEmpl;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned ne;AEmpl empl;

public:Factoria ();virtual ˜ Factoria ();virtual Factoria* clone () const;virtual void anyadir_empleado(Empleado* e, bool& ok);virtual void sueldos () const;

protected:Factoria(const Factoria& o);

private:Factoria& operator=(const Factoria& o);

};}#endif� �

Solución: factoria.cpp� �#include "factoria.hpp"#include <iostream>using namespace std;namespace umalcc {

Factoria :: Factoria (): ne(0), empl() {}

Factoria :: ˜ Factoria (){

for (unsigned i = 0; i < ne; ++i) {delete empl[i];

}}Factoria* Factoria ::clone () const{

return new Factoria(*this);}void Factoria :: anyadir_empleado(Empleado* e, bool& ok){

ok = (ne < empl.size ())&&(e != NULL);if (ok) {

empl[ne] = e;++ne;

}}void Factoria :: sueldos () const{

for (unsigned i = 0; i < ne; ++i) {cout << empl[i]->nombre () << ": "

<< empl[i]->sueldo () << endl;}

}Factoria :: Factoria(const Factoria& o)

: ne(o.ne), empl() {for (unsigned i = 0; i < ne; ++i) {

empl[i] = o.empl[i]->clone ();}

}}� �

Solución: main.cpp� �#include <iostream>#include <string>

99

Page 100: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#include "empleado.hpp"#include "directivo.hpp"#include "directivo_a.hpp"#include "directivo_b.hpp"#include "agventas.hpp"#include "agventas_a.hpp"#include "agventas_b.hpp"#include "factoria.hpp"using namespace std;using namespace umalcc;

void nuevo_directivo(Factoria* f, const string& n, const string& clase){

bool ok = false;Empleado* e = NULL;if (f != NULL) {

if (clase == "A") {e = new Directivo_A(n);

} else if (clase == "B") {e = new Directivo_B(n);

}f->anyadir_empleado(e, ok);

}if (!ok) {

cout << "Error al añadir: " << n << endl;delete e;

}}

void nuevo_aventas(Factoria* f, const string& n, const string& clase , double v){

bool ok = false;AgVentas* e = NULL;if (f != NULL) {

if (clase == "A") {e = new AgVentas_A(n);e->anyadir_ventas(v);

} else if (clase == "B") {e = new AgVentas_B(n);e->anyadir_ventas(v);

}f->anyadir_empleado(e, ok);

}if (!ok) {

cout << "Error al añadir: " << n << endl;delete e;

}}int main(){

Factoria* f = new Factoria;nuevo_directivo(f, "Ana", "A");nuevo_directivo(f, "Beatriz", "B");nuevo_aventas(f, "Alicia", "A", 100);nuevo_aventas(f, "Eva", "A", 200);nuevo_aventas(f, "Pepe", "B", 200);nuevo_aventas(f, "Ricardo", "B", 400);nuevo_aventas(f, "María", "A", 600);nuevo_aventas(f, "Lola", "B", 400);Factoria* copia = f->clone ();f->sueldos ();delete f;cout << "------------------------------" << endl;copia->sueldos ();delete copia;

}� �2. Se desea implementar una jerarquía de elementos gráficos como la de la siguiente figura:

100

Page 101: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

ElementoGrafico

CuadradoPunto Linea

LineaVertical LineaHorizontal

La clase polimórfica ElementoGrafico representa un elemento gráfico que puede imprimirse porpantalla. Tiene un constructor por defecto que permite crear el objeto y proporciona los siguientesmétodos públicos virtuales:

• clonar(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• pintar() pinta el objeto gráfico en pantalla. En esta clase, simplemente escribe la palabra ERROR

en pantalla. Las clases derivadas deberán redefinir este método para escribir correctamente elelemento gráfico específico por pantalla.

La clase polimórfica Punto representa a un elemento gráfico especializado, en concreto a un punto(carácter ’.’), que puede imprimirse en pantalla. Suministra un constructor por defecto para crearel objeto, además de los siguientes métodos públicos virtuales:

• clonar(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• pintar(): escribe un carácter punto (’.’) y un salto de línea en pantalla.

La clase polimórfica Linea representa a un elemento gráfico especializado, en concreto una línea, quepuede imprimirse en pantalla. Suministra un constructor por defecto para crear la línea e inicializarlacon longitud cero y un constructor extendido que inicializa la línea con una determinada longitud.Además, suministra los siguientes métodos públicos virtuales:

• clonar(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• pintar(): pinta una línea en pantalla. Las clases derivadas deberán redefinir este método paraescribir una línea específica por pantalla.

• consultar_longitud(): devuelve la longitud de la línea actual.• cambiar_longitud(lng): almacena el nuevo valor de la longitud de la línea actual recibida como

parámetro.

La clase polimórfica LineaHorizontal representa a un elemento gráfico especializado, en concretouna línea horizontal, que puede imprimirse en pantalla (como una secuencia de caracteres ’-’).Suministra un constructor por defecto para crear la línea e inicializarla con longitud cero y unconstructor extendido que inicializa la línea con una determinada longitud. Además, suministra lossiguientes métodos públicos virtuales:

• clonar(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• pintar(): pinta una línea horizontal en pantalla de la longitud almacenada en su estado: sedeben escribir en pantalla tantos caracteres ’-’ como indique su longitud, seguidos por un saltode línea.

La clase polimórfica LineaVertical representa a un elemento gráfico especializado, en concreto unalínea vertical, que puede imprimirse en pantalla (como una secuencia de caracteres ’|’ dispuestosverticalmente, es decir, separados por un ’\n’). Suministra un constructor por defecto para crearla línea e inicializarla con longitud cero y un constructor extendido que inicializa la línea con unadeterminada longitud. Además, suministra los siguientes métodos públicos virtuales:

• clonar(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• pintar(): pinta una línea vertical en pantalla de la longitud almacenada en su estado: se debenescribir en pantalla tantos caracteres ’|’ seguidos de saltos de línea como indique su longitud.

101

Page 102: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

La clase polimórfica Cuadrado representa a un elemento gráfico especializado, en concreto un cuadra-do, que puede imprimirse en pantalla (empleando caracteres |, ’-’, ’ ’ y ’\n’ dispuestos en pantallade manera que simulen los lados de un cuadrado). Suministra un constructor por defecto para crearel cuadrado e inicializar su lado a cero y un constructor extendido que inicializa el cuadrado con undeterminado tamaño de lado. Además, suministra los siguientes métodos públicos virtuales:

• clonar(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• pintar(): pinta un cuadrado en pantalla empleando los caracteres |, ’-’, ’ ’ y ’\n’.• consultar_lado(): devuelve la longitud del lado del cuadrado actual.• cambiar_lado(lng): almacena el nuevo valor de la longitud del lado del cuadrado actual recibidacomo parámetro.

Desarrolle un programa principal que declare un array de objetos polimórficos de las distintas clasespolimórficas (Punto, LineaHorizontal, LineaVertical y Cuadrado) de la jerarquía de ElementoGraficoy los escriba en pantalla invocando al método virtual pintar().

Solución: elemento_grafico.hpp� �#ifndef elemento_grafico_hpp__#define elemento_grafico_hpp__

namespace umalcc{class ElementoGrafico {public:

ElementoGrafico ();virtual ˜ ElementoGrafico ();virtual void pintar () const;virtual ElementoGrafico* clonar () const;

protected:ElementoGrafico(const ElementoGrafico &o);

private:ElementoGrafico & operator=(const ElementoGrafico &o);

};}#endif� �

Solución: elemento_grafico.cpp� �#include "elemento_grafico.hpp"

namespace umalcc {ElementoGrafico :: ElementoGrafico () {}

ElementoGrafico :: ˜ ElementoGrafico () {}

void ElementoGrafico :: pintar () const {}

ElementoGrafico* ElementoGrafico :: clonar () const{

return new ElementoGrafico(*this);}

ElementoGrafico :: ElementoGrafico(const ElementoGrafico &o) { (void)o; }}� �

Solución: punto.hpp� �#ifndef punto_hpp__#define punto_hpp__

#include "elemento_grafico.hpp"

namespace umalcc{class Punto : public ElementoGrafico{public:

Punto ();virtual ˜ Punto ();virtual void pintar () const;virtual Punto* clonar () const;

102

Page 103: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

protected:Punto(const Punto &o);

private:Punto & operator=(const Punto &o);

};}#endif� �

Solución: punto.cpp� �#include "punto.hpp"#include <iostream>

using namespace std;

namespace umalcc{Punto :: Punto() : ElementoGrafico () {}

Punto :: ˜ Punto() {}

void Punto:: pintar () const{

cout << "." << endl;}

Punto* Punto:: clonar () const{

return new Punto(*this);}

Punto :: Punto(const Punto &o) : ElementoGrafico(o) {}}� �

Solución: linea.hpp� �#ifndef linea_hpp__#define linea_hpp__

#include "elemento_grafico.hpp"

namespace umalcc{class Linea : public ElementoGrafico {public:

Linea ();Linea(unsigned l);virtual ˜ Linea ();virtual unsigned consultar_longitud () const;virtual void cambiar_longitud(unsigned l);virtual Linea* clonar () const;

protected:Linea(const Linea &o);

private:unsigned longitud;//−−Linea & operator=(const Linea &o);

};}#endif� �

Solución: linea.cpp� �#include "linea.hpp"

namespace umalcc{Linea :: Linea() : ElementoGrafico (), longitud (0) {}

Linea :: Linea(unsigned l) : ElementoGrafico (), longitud(l) {}

Linea :: ˜ Linea() {}

103

Page 104: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

unsigned Linea:: consultar_longitud () const{

return longitud;}

void Linea:: cambiar_longitud(unsigned l){

longitud = l;}

Linea* Linea:: clonar () const{

return new Linea(*this);}

Linea :: Linea(const Linea &o) : ElementoGrafico(o), longitud(o.longitud) {}}� �

Solución: linea_horizontal.hpp� �#ifndef linea_horizontal_hpp__#define linea_horizontal_hpp__

#include "linea.hpp"

namespace umalcc{class LineaHorizontal : public Linea {public:

LineaHorizontal ();LineaHorizontal(unsigned l);virtual ˜ LineaHorizontal ();virtual void pintar () const;virtual LineaHorizontal* clonar () const;

protected:LineaHorizontal(const LineaHorizontal &o);

private:LineaHorizontal & operator=(const LineaHorizontal &o);

};}#endif� �

Solución: linea_horizontal.cpp� �#include "linea_horizontal.hpp"#include <iostream>

using namespace std;

namespace umalcc{LineaHorizontal :: LineaHorizontal () : Linea() {}

LineaHorizontal :: LineaHorizontal(unsigned l) : Linea(l) {}

LineaHorizontal :: ˜ LineaHorizontal () {}

void LineaHorizontal :: pintar () const{

for (unsigned i = 0; i < consultar_longitud (); i++) {cout << "-";

}cout << endl;

}

LineaHorizontal* LineaHorizontal :: clonar () const{

return new LineaHorizontal(*this);}

LineaHorizontal :: LineaHorizontal(const LineaHorizontal &o): Linea(o) {}}� �

104

Page 105: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: linea_vertical.hpp� �#ifndef linea_vertical_hpp__#define linea_vertical_hpp__

#include "linea.hpp"

namespace umalcc{class LineaVertical : public Linea {public:

LineaVertical ();LineaVertical(unsigned l);virtual ˜ LineaVertical ();virtual void pintar () const;virtual LineaVertical* clonar () const;

protected:LineaVertical(const LineaVertical &o);

private:LineaVertical & operator=(const LineaVertical &o);

};}#endif� �

Solución: linea_vertical.cpp� �#include "linea_vertical.hpp"#include <iostream>

using namespace std;

namespace umalcc{LineaVertical :: LineaVertical () : Linea () {}

LineaVertical :: LineaVertical(unsigned l) : Linea(l) {}

LineaVertical :: ˜ LineaVertical () {}

void LineaVertical :: pintar () const{

for (unsigned i = 0; i < consultar_longitud (); i++){cout << "|" << endl;

}}

LineaVertical* LineaVertical :: clonar () const{

return new LineaVertical(*this);}

LineaVertical :: LineaVertical(const LineaVertical &o) : Linea(o) {}}� �

Solución: cuadrado.hpp� �#ifndef cuadrado_hpp__#define cuadrado_hpp__

#include "elemento_grafico.hpp"

namespace umalcc{class Cuadrado : public ElementoGrafico {public:

Cuadrado ();Cuadrado(unsigned l);virtual ˜ Cuadrado ();virtual unsigned consultar_lado () const;virtual void asignar_lado(unsigned l);virtual void pintar () const;virtual Cuadrado* clonar () const;

protected:Cuadrado(const Cuadrado &o);

private:

105

Page 106: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

unsigned lado;//−−Cuadrado & operator=(const Cuadrado &o);

};}#endif� �

Solución: cuadrado.cpp� �#include "cuadrado.hpp"#include <iostream>

using namespace std;

namespace umalcc{Cuadrado :: Cuadrado () : ElementoGrafico (), lado (0) {}

Cuadrado :: Cuadrado(unsigned l) : ElementoGrafico (), lado(l) {}

Cuadrado :: ˜ Cuadrado () {}

void Cuadrado :: asignar_lado(unsigned l){

lado = l;}

unsigned Cuadrado :: consultar_lado () const{

return lado;}

void Cuadrado :: pintar () const{

// lado super io rfor (unsigned i = 0; i < lado; i++){

cout << "-";}cout << endl;// lados l a t e r a l e sfor (unsigned i = 0; i < lado - 2; i++){

cout << "|";for (unsigned j = 0; j < lado - 2; j++){

cout << " ";}cout << "|" << endl;

}// lado i n f e r i o rfor (unsigned i = 0; i < lado; i++){

cout << "-";}cout << endl;

}

Cuadrado* Cuadrado :: clonar () const{

return new Cuadrado(*this);}

Cuadrado :: Cuadrado(const Cuadrado &o) : ElementoGrafico(o), lado(o.lado) {}}� �

Solución: main.cpp� �#include "elemento_grafico.hpp"#include "punto.hpp"#include "linea_horizontal.hpp"#include "linea_vertical.hpp"#include "cuadrado.hpp"#include <iostream>#include <array>

using namespace std;

106

Page 107: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

using namespace umalcc;

const int MAX = 4;typedef array<ElementoGrafico*, MAX> AEGraficos;

int main(){

AEGraficos lista;

lista[0] = new Punto;lista[1] = new LineaHorizontal (10);lista[2] = new LineaVertical (5);lista[3] = new Cuadrado (6);

for (unsigned i = 0; i < lista.size (); i++){lista[i]->pintar ();

}

for (unsigned i = 0; i < lista.size (); i++){delete lista[i];

}

}� �3. Se desea simular el comportamiento de una serie de vehículos, por lo que se establece la siguiente jerarquía

de clases:

Vehiculo

BicicletaAutomovil

Todo objeto de la clase base polimórfica Vehiculo debe guardar en su estado la siguiente informacióny definir el siguiente constructor:

• ident: identificador del vehículo (cadena de caracteres).• distancia: la distancia recorrida por el vehículo con respecto al punto de partida (origen) delmismo (unsigned).

• Vehiculo(i): inicializa el identificador del vehículo con i y su distancia a cero.Además, el comportamiento de los objetos Vehículo queda definido por los siguientes métodos pú-blicos virtuales:

• id(): devuelve el indentificador del vehículo• consultar_dist(): devuelve un unsigned con la distancia recorrida por el vehículo• estacionar(): establece la distancia recorrida por el vehículo en 0 (origen)• tiene_energia(): indica si el vehículo tiene energía (función lógica). Debe devolver siempretrue

• mover(): incrementa en 1 el valor de la distancia recorrida por el vehículo.• clone(): devuelve un puntero a un objeto Vehiculo, copia del vehículo actual

Además, la clase Vehículo proporciona a sus clases derivadas los siguientes métodos protected,para poder manipular adecuadamente su estado interno:

• mover(x): incrementa en x el valor de la distancia recorrida por el vehículo.La clase derivada polimórfica Automovil añade los siguientes atributos y define el siguiente construc-tor:

• DPL: constante simbólica static, de tipo unsigned, que indica la distancia que el automóvilrecorre por litro de combustible (= 50).

• deposito: atributo unsigned que guarda el número de litros de combustible del depósito delautomóvil.

107

Page 108: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

• Automovil(i): inicializa el identificador del automóvil a i, su distancia a 0 y su deposito a 0.

Además, el comportamiento de los objetos Automovil queda definido por los siguientes métodospúblicos virtuales:

• tiene_energia(): redefine el método de la clase base, devolviendo true si la cantidad almace-nada en el deposito es mayor que 0.

• mover(): redefine el método de la clase base, de tal forma que si el automóvil tiene energía,entonces se mueve una distancia igual al valor de DPL, es decir, se incrementa la distancia recorridaactual sumándole a la misma el valor almacenado en la constante miembro DPL.

• repostar(ltr): incrementa la cantidad de combustible almacenada en el deposito del automóvilen ltr litros.

• clone(): devuelve un puntero a un objeto Automovil, copia del automóvil actual.

La clase derivada polimórfica Bicicleta añade los siguientes atributos y define el siguiente construc-tor:

• NUM_PLATOS: constante simbólica static, de tipo unsigned, indicando el número de platos quetiene la bicicleta.

• plato: un unsigned que indica el plato que tiene puesto en este momento la bicicleta (a mayortamaño de plato, mayor será su desplazamiento cuando la bicicleta se mueva).

• Bicicleta(i): inicializa el identificador de la bicicleta a i, su distancia a 0 y su plato a 0.

Además, el comportamiento de los objetos Bicicleta queda definido por los siguientes métodospúblicos virtuales:

• mover(): redefine el método de la clase base, de tal forma que la bicicleta se mueve una distanciaigual al valor de plato + 1, es decir, se incrementa la distancia recorrida actual sumándole a lamisma el valor de plato + 1.

• cambiar(): cambia el valor del plato, sumándole 1 y aplicando posteriormente % NUM_PLATOS(el valor del plato siempre estará entre 0 y NUM_PLATOS - 1).

• clone(): devuelve un puntero a un objeto Bicicleta, copia de la bicicleta actual.

El programa principal debe definir el tipo Vehiculos como un tipo array de NUM_VEHICULOS = 4punteros a objetos de la clase Vehiculo.

Implementar el procedimiento viajar(v, d, t), que recibe un puntero a un objeto de la claseVehiculo, un unsigned con la distancia total a recorrer por el vehículo, y devuelve, a través de unparámetro de salida el tiempo (“minutos”) que el vehículo ha tardado en llegar a su destino (si hatenido energía suficiente para llegar). Este algoritmo debe proceder de la siguiente manera:

a) Estacionar el vehículo (es decir, inicializar la distancia recorrida a 0).b) Inicializar el tiempo a 0.c) Mientras que el vehículo tenga energía y su distancia recorrida sea menor que la distancia

solicitada, el vehículo debe moverse (para ello, el procedimiento debe invocar la función miembromover() del objeto Vehiculo) y tiempo se incrementa en 1.

Implementar el programa principal (main), con las siguientes características:

• Declara un array mis_vehiculos de tipo Vehiculos.• Crea un objeto Automovil, con identificador "5555JJJ" y 50 litros de gasolina y pone mis_vehiculos[0]apuntando a él.

• Crea un objeto Bicicleta, con identificador "6666JJJ" y pone mis_vehiculos[1] apuntandoa él.

• Crea un objeto Bicicleta, con identificador "7777JJJ", cambia su plato y pone mis_vehiculos[2]apuntando a él.

• Crea un objeto Bicicleta, con identificador "8888JJJ", cambia su plato dos veces y ponemis_vehiculos[3] apuntando a él.

• Para todos los vehiculos que se encuentran en mis_vehiculos, debe calcular el tiempo de dura-ción del viaje para una distancia recorrida de destino 1000 invocando al procedimiento viajary, en caso de que el vehículo tuviera energía suficiente, escribe ese tiempo por pantalla (en casocontrario, se indica con un mensaje por pantalla: El vehículo x no ha podido llegar a sudestino por falta de energía)

• Un ejemplo de ejecución podría ser:

108

Page 109: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

El vehículo 5555JJJ no ha podido llegar a su destino por falta de energíaTiempo vehículo 6666JJJ: 1000 minutosTiempo vehículo 7777JJJ: 500 minutosTiempo vehículo 8888JJJ: 334 minutos

Solución: vehiculo.hpp� �#ifndef vehiculo_hpp__#define vehiculo_hpp__#include <string>namespace umalcc {

class Vehiculo {public:

Vehiculo(const std:: string& i);virtual ˜ Vehiculo ();virtual std:: string id() const;virtual unsigned consultar_dist () const;virtual void estacionar ();virtual bool tiene_energia () const;virtual void mover ();virtual Vehiculo* clone () const;

protected:virtual void mover(unsigned x);

private:Vehiculo& operator=(const Vehiculo&);//−−−− Atr i bu tos −−−−std:: string ident;unsigned distancia;

};}#endif� �

Solución: vehiculo.cpp� �#include "vehiculo.hpp"

namespace umalcc {Vehiculo :: ˜ Vehiculo () {}

Vehiculo :: Vehiculo(const std:: string& i): ident(i), distancia (0) {}

std:: string Vehiculo ::id() const{

return ident;}

unsigned Vehiculo :: consultar_dist () const{

return distancia;}

void Vehiculo :: estacionar (){

distancia = 0 ;}

bool Vehiculo :: tiene_energia () const{

return true;}

void Vehiculo ::mover(){

++distancia ;}

void Vehiculo ::mover(unsigned x){

distancia += x ;}

109

Page 110: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Vehiculo* Vehiculo ::clone () const{

return new Vehiculo(*this) ;}

}� �Solución: automovil.hpp� �

#ifndef automovil_hpp__#define automovil_hpp__#include "vehiculo.hpp"#include <string>namespace umalcc {

class Automovil : public Vehiculo {public:

Automovil(const std:: string& i) ;virtual ˜ Automovil () ;virtual bool tiene_energia () const;virtual void mover () ;virtual void repostar(unsigned litros) ;virtual Automovil* clone() const ;

private:static const unsigned DPL = 50;//−−−− Atr i bu tos −−−−unsigned deposito ;

};}#endif� �

Solución: automovil.cpp� �#include "automovil.hpp"

namespace umalcc {Automovil :: ˜ Automovil () {}

Automovil :: Automovil(const std:: string& i): Vehiculo(i), deposito (0) {}

bool Automovil :: tiene_energia () const{

return deposito > 0;}

void Automovil :: mover(){

if (tiene_energia ()) {Vehiculo :: mover(DPL) ;--deposito ;

}}

void Automovil :: repostar(unsigned litros){

deposito += litros ;}

Automovil* Automovil :: clone() const{

return new Automovil(*this) ;}

}� �Solución: bicicleta.hpp� �

#ifndef bicicleta_hpp__#define bicicleta_hpp__#include "vehiculo.hpp"#include <string>namespace umalcc {

110

Page 111: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

class Bicicleta : public Vehiculo {public:

Bicicleta(const std:: string& i) ;virtual ˜ Bicicleta () ;virtual void mover () ;virtual void cambiar () ;virtual Bicicleta* clone() const ;

private:static const unsigned NUM_PLATOS = 3;//−−−− Atr i bu tos −−−−unsigned plato ;

};}#endif� �

Solución: bicicleta.cpp� �#include "bicicleta.hpp"

namespace umalcc {Bicicleta :: ˜ Bicicleta () {}

Bicicleta :: Bicicleta(const std:: string& i): Vehiculo(i), plato (0) {}

void Bicicleta :: mover(){

Vehiculo :: mover(plato + 1) ;}

void Bicicleta :: cambiar (){

plato = (plato + 1) % NUM_PLATOS ;}

Bicicleta* Bicicleta :: clone() const{

return new Bicicleta(*this) ;}

}� �Solución: main.cpp� �

#include "vehiculo.hpp"#include "automovil.hpp"#include "bicicleta.hpp"#include <iostream>#include <array>

using namespace std;using namespace umalcc;

const unsigned NUM_VEHICULOS = 4;const unsigned DIST_DESTINO = 1000;

typedef array<Vehiculo*, NUM_VEHICULOS> Vehiculos;

void viajar(Vehiculo* v, unsigned destino , unsigned &tiempo){

tiempo = 0;v->estacionar ();while (v->tiene_energia () && v->consultar_dist () < destino) {

tiempo++;v->mover ();

}}

int main(){

Vehiculos mis_vehiculos;array<unsigned , NUM_VEHICULOS> tiempos;Bicicleta* una_bici;

111

Page 112: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Automovil* un_coche;

// Un coche con 10 l i t r o s de ga so l i naun_coche = new Automovil("5555 JJJ");un_coche->repostar (10);mis_vehiculos[0] = un_coche;

// Bic i s con d i s t i n t o s p l a t o suna_bici = new Bicicleta("6666 JJJ");mis_vehiculos[1] = una_bici;una_bici = new Bicicleta("7777 JJJ");una_bici->cambiar (); // Cambio e l p l a t o de mi segunda b i c imis_vehiculos[2] = una_bici;una_bici = new Bicicleta("8888 JJJ");una_bici->cambiar (); // Cambio e l p l a t o de mi segunda b i c iuna_bici->cambiar (); // Cambio e l p l a t o de mi segunda b i c imis_vehiculos[3] = una_bici;

for (unsigned i = 0; i < mis_vehiculos.size (); ++i) {viajar(mis_vehiculos[i], DIST_DESTINO , tiempos[i]);

}

for (unsigned i = 0; i < mis_vehiculos.size (); i++) {if (mis_vehiculos[i]->consultar_dist () >= DIST_DESTINO) {

cout << "Tiempo vehículo " << mis_vehiculos[i]->id() << ": "<< tiempos[i]<< " minutos " << endl;

} else {cout << "El vehículo " << mis_vehiculos[i]->id()

<< " no ha podido llegar a su destino por falta de energía"<< endl;

}}

for (unsigned i = 0; i < mis_vehiculos.size (); i++) {delete mis_vehiculos[i];

}

}� �4. Dada la jerarquía de clases de Vehiculo del ejercicio anterior, se debe desarrollar la clase no-polimórfica

Parking para gestionar un parking con un máximo de MAX = 100 vehículos (de cualquier tipo) estacionadosen él.

Los objetos de la clase Parking deben almacenar en su estado la siguiente información:

• MAX: constante simbólica static con el máximo (= 100) de vehículos que pueden estacionarseen el parking.

• parking: un array de MAX punteros a objetos de la clase Vehiculo.• n_v: número de vehículos estacionados en el parking.

Además, la clase Parking debe suministrar los siguientes métodos, constructores, etc. públicos:

• Parking(): inicializa el número de vehículos estacionados en el parking a 0.• Parking(otro_parking): constructor de copia de la clase: copia (clona) todos los vehículosestacionados en otro_parking al parking actual.

• ~Parking(): destructor de la clase: libera todos los vehículos almacenados en el parking (losdestruye).

• operator=(otro_parking): operador de asignación para la clase Parking.• anyadir(v, ok): recibe como parámetro de entrada v, un puntero a un objeto de la claseVehiculo. Si hay espacio en el parking para estacionar un nuevo vehículo, entonces v se añade alfinal de la lista de vehículos estacionados en el parking y el número de vehículos estacionados seincrementa en 1; finalmente, se debe invocar al método de estacionar sobre este nuevo vehículoestacionado (para que su distancia recorrida se ponga a 0); ok debe ponerse a true en ese caso.Si no hay espacio para estacionar en el parking, se devuelve false a través de ok.

• mostrar(): muestra por pantalla los identificadores de todos los vehículos estacionados en elparking.

112

Page 113: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

• extraer(id): busca en la lista de vehículos almacenados en el parking el vehículo con idenfifi-cador id. Si lo encuentra, debe extraer el vehículo del parking y devolver un puntero al objetovehículo extraído. Si no lo encuentra, entonces devuelve NULL.

Se aconseja, además, implementar los siguientes métodos privados de la clase Parking:• buscar(id): devuelve la posición del array parking que contiene un puntero apuntando alvehículo con identificador id, si éste está estacionado en el parking. Si no, devuelve una posiciónfuera de rango (por ejemplo, el n_v).

• copiar(otro_parking): copia todo el estado de otro_parking (esto es, clona todos los vehículosalmacenados en él y copia su n_v) en el objeto actual. Nota: deben clonarse todos los vehículosdel objeto otro_parking para que el parking actual trabaje con copias de los mismos.

• destruir(): destruye todos los vehículos almacenados en el parking.Debe implementarse un programa principal que declare un objeto de la clase Parking y “pruebe”toda su funcionalidad: añada vehículos de distinto tipo (vehículos genéricos, automóviles y bicicletas)al parking, los muestre, los extraiga, haga una copia completa del parking, etc.

Solución: parking.hpp� �#ifndef parking_hpp_#define parking_hpp_#include "vehiculo.hpp"#include <array>#include <string>namespace umalcc {

class Parking { // CLASE NO−POLIMORFICApublic:

˜ Parking ();Parking ();Parking(const Parking& o);Parking& operator=(const Parking& o);void mostrar () const;void anyadir(Vehiculo* v, bool& ok);Vehiculo* extraer(const std:: string& id);

private:static const int MAX = 100;typedef std::array<Vehiculo*, MAX> Park;//−−int buscar(const std:: string& id) const;void destruir ();void copiar(const Parking& o);//−−int n_v;Park parking;

};}#endif� �

Solución: parking.cpp� �#include "parking.hpp"#include <iostream>using namespace std;namespace umalcc {

Parking :: ˜ Parking () { destruir (); }Parking :: Parking () : n_v(0), parking () {}Parking :: Parking(const Parking& o)

: n_v(), parking () { copiar(o); }Parking& Parking :: operator=(const Parking& o) {

if (this != &o) {destruir ();copiar(o);

}return *this;

}void Parking :: anyadir(Vehiculo* v, bool& ok) {

ok = ((v != NULL)&&(n_v < MAX ));if (ok) {

v->estacionar ();parking[n_v] = v;

113

Page 114: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

++n_v;}

}void Parking :: destruir () {

for (int i = 0; i < n_v; ++i) {delete parking[i];

}n_v = 0;

}void Parking :: mostrar () const {

for (int i = 0; i < n_v; ++i) {cout << parking[i]->id() << endl;

}}Vehiculo* Parking :: extraer(const std:: string& id) {

Vehiculo* v = NULL;int i = buscar(id);if (i < n_v) {

v = parking[i];--n_v;parking[i] = parking[n_v];v->mover ();

}return v;

}int Parking :: buscar(const std:: string& id) const {

int i = 0;while ((i < n_v)&&(id != parking[i]->id())) {

++i;}return i;

}void Parking :: copiar(const Parking& o) {

n_v = o.n_v;for (int i = 0; i < o.n_v; ++i) {

parking[i] = o.parking[i]->clone ();}

}}� �

Solución: main.cpp� �#include "vehiculo.hpp"#include "bicicleta.hpp"#include "automovil.hpp"#include "parking.hpp"#include <iostream>using namespace std;using namespace umalcc;

void anyadir_vehiculo(Parking& park , Vehiculo* v){

if (v != NULL) {bool ok;park.anyadir(v, ok);if (!ok) {

delete v;}

}}int main(){

Parking park;Automovil* a1 = new Automovil("A1");Bicicleta* b1 = new Bicicleta("B1");Vehiculo* a2 = new Automovil("A2");anyadir_vehiculo(park , a1);anyadir_vehiculo(park , b1);anyadir_vehiculo(park , a2);Parking aux = park;Vehiculo* v = aux.extraer("A1");if (v != NULL) {

cout << "Vehiculo: " << v->id() << endl;

114

Page 115: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

v->mover ();}aux.mostrar ();park.mostrar ();delete v;

}� �5. Se dispone de una clase base de tipo Robot, encargado, de forma general, de ensamblar piezas en un

determinado objeto. En este ejercicio, se pretende construir un “Androide”, y se dispone de robots especia-lizados (clases derivadas de Robot) en el ensamblaje de cada una de las piezas que componen el Androidefinal, tal como la cabeza, el tronco, los brazos y las piernas. Además, también se dispone de un robot quepermite ensamblar la identificación de cada androide ensamblado.

Robot

RPiernasRBrazosRTroncoRCabezaRIdent

En este primer ejercicio, el soporte donde ensamblar el androide es un simple string, donde se pueden irañadiendo las piezas que ensambla cada robot. Así, con objeto de simplificar el proceso y enfocar en losconceptos de POO (herencia, polimorfismo y vinculación dinamica), cada robot especializado ensamblauna determinada pieza, representada por el caracter de su inicial: C, T, B, P, de una forma muy simpleen el objeto a construir, añadiendo simplemente el carácter que representa a la pieza al objeto de tipostring. Por ejemplo, los dos primeros androides completamente ensamblados serían dos string con losvalores "ID1:CTBP" e "ID2:CTBP", considerando que cada identificación irá incrementando el valor de unnúmero de serie (contador).

La clase polimórfica Robot representa un robot general de ensamblaje, tiene un constructor pordefecto que permite crear un objeto, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• ensamblar(o, ok): recibe el objeto que se está ensamblando, de tipo string, como parámetrode entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación deensamblaje se ha realizado correctamente. Las clases derivadas deberán redefinir este métodopara ensamblar las piezas adecuadamente en el objeto recibido como parámetro.

La clase polimórfica RIdent representa un robot especializado en ensamblar la identificación de unandroide (un símbolo inicial de identificación, seguido por un número de serie y del símbolo dos-puntos), tiene un constructor que permite crear un objeto con el símbolo inicial de identificación(string) recibido como parámetro, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• ensamblar(o, ok): recibe el objeto que se está ensamblando, de tipo string, como parámetrode entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación deensamblaje se ha realizado correctamente. Este método asigna la secuencia de identificación (elsímbolo, el número de serie y los dos puntos) al objeto que se está ensamblando, y posteriormenteincrementará el número de serie.

La clase polimórfica RCabeza representa un robot especializado en ensamblar la cabeza de un androide(un carácter C), tiene un constructor por defecto que permite crear un objeto, y proporciona lossiguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• ensamblar(o, ok): recibe el objeto que se está ensamblando, de tipo string, como parámetrode entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación deensamblaje se ha realizado correctamente. Este método añade el símbolo de la cabeza (C) alobjeto que se está ensamblando.

La clase polimórfica RTronco representa un robot especializado en ensamblar el tronco de un androide(un carácter T), tiene un constructor por defecto que permite crear un objeto, y proporciona lossiguientes métodos públicos virtuales:

115

Page 116: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• ensamblar(o, ok): recibe el objeto que se está ensamblando, de tipo string, como parámetro

de entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación deensamblaje se ha realizado correctamente. Este método añade el símbolo del tronco (T) al objetoque se está ensamblando.

La clase polimórfica RBrazos representa un robot especializado en ensamblar los brazos de un an-droide (un carácter B), tiene un constructor por defecto que permite crear un objeto, y proporcionalos siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• ensamblar(o, ok): recibe el objeto que se está ensamblando, de tipo string, como parámetrode entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación deensamblaje se ha realizado correctamente. Este método añade el símbolo de los brazos (B) alobjeto que se está ensamblando.

La clase polimórfica RPiernas representa un robot especializado en ensamblar las piernas de unandroide (un carácter P), tiene un constructor por defecto que permite crear un objeto, y proporcionalos siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• ensamblar(o, ok): recibe el objeto que se está ensamblando, de tipo string, como parámetrode entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación deensamblaje se ha realizado correctamente. Este método añade el símbolo de las piernas (P) alobjeto que se está ensamblando.

Finalmente, el programa principal creará los 5 robots de ensamblaje especializados necesarios, losalmacenará en una cadena de montaje (un array de robots generales) en el siguiente orden (RIdent,RCabeza, RTronco, RBrazos y RPiernas), y ensamblará adecuadamente una determinada cantidadde androides, considerando que cada objeto a ensamblar se va pasando de robot en robot en la cadenade montaje hasta finalizar el ensamblaje completo del androide.

Solución: robot.hpp� �#ifndef robot_hpp_#define robot_hpp_#include <string>namespace umalcc {

class Robot {public:

Robot () ;virtual ˜ Robot () ;virtual Robot* clone() const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:Robot(const Robot& r) ;

private:Robot& operator=(const Robot& o);

};}#endif� �

Solución: robot.cpp� �#include "robot.hpp"#include <string>using namespace std;namespace umalcc {

Robot :: Robot() {}Robot :: ˜ Robot() {}Robot* Robot:: clone() const{

return new Robot(*this);}void Robot:: ensamblar(std:: string& objeto , bool& ok){

ok = false;(void)objeto;

116

Page 117: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}Robot :: Robot(const Robot& r){

(void)r;}

}� �Solución: rident.hpp� �

#ifndef rident_hpp_#define rident_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RIdent : public Robot {std:: string base;unsigned num;

public:RIdent(const std:: string& b) ;virtual ˜ RIdent () ;virtual RIdent* clone() const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RIdent(const RIdent& r) ;

};}#endif� �

Solución: rident.cpp� �#include "rident.hpp"#include <string>using namespace std;namespace {

std:: string num2str(unsigned n){

std:: string s = "";do {

s = char('0' + (n %10)) + s;n = n / 10;

} while (n > 0);return s;

}}namespace umalcc {

RIdent :: RIdent(const std:: string& b) : Robot(), base(b), num(1) {}RIdent :: ˜ RIdent () {}RIdent* RIdent :: clone() const{

return new RIdent(*this);}void RIdent :: ensamblar(std:: string& objeto , bool& ok){

std:: string id = base + num2str(num);objeto = id + ":";++num;ok = true;

}RIdent :: RIdent(const RIdent& r) : Robot(r), base(r.base), num(r.num) {}

}� �Solución: rcabeza.hpp� �

#ifndef rcabeza_hpp_#define rcabeza_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RCabeza : public Robot {public:

117

Page 118: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

RCabeza () ;virtual ˜ RCabeza () ;virtual RCabeza* clone () const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RCabeza(const RCabeza& r) ;

};}#endif� �

Solución: rcabeza.cpp� �#include "rcabeza.hpp"#include <string>using namespace std;namespace umalcc {

RCabeza :: RCabeza () : Robot () {}RCabeza :: ˜ RCabeza () {}RCabeza* RCabeza ::clone () const{

return new RCabeza(*this);}void RCabeza :: ensamblar(std:: string& objeto , bool& ok){

objeto += "C";ok = true;

}RCabeza :: RCabeza(const RCabeza& r) : Robot(r) {}

}� �Solución: rtronco.hpp� �

#ifndef rtronco_hpp_#define rtronco_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RTronco : public Robot {public:

RTronco () ;virtual ˜ RTronco () ;virtual RTronco* clone () const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RTronco(const RTronco& r) ;

};}#endif� �

Solución: rtronco.cpp� �#include "rtronco.hpp"#include <string>using namespace std;namespace umalcc {

RTronco :: RTronco () : Robot () {}RTronco :: ˜ RTronco () {}RTronco* RTronco ::clone () const{

return new RTronco(*this);}void RTronco :: ensamblar(std:: string& objeto , bool& ok){

objeto += "T";ok = true;

}RTronco :: RTronco(const RTronco& r) : Robot(r) {}

}� �118

Page 119: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: rbrazos.hpp� �#ifndef rbrazos_hpp_#define rbrazos_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RBrazos : public Robot {public:

RBrazos () ;virtual ˜ RBrazos () ;virtual RBrazos* clone () const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RBrazos(const RBrazos& r) ;

};}#endif� �

Solución: rbrazos.cpp� �#include "rbrazos.hpp"#include <string>using namespace std;namespace umalcc {

RBrazos :: RBrazos () : Robot () {}RBrazos :: ˜ RBrazos () {}RBrazos* RBrazos ::clone () const{

return new RBrazos(*this);}void RBrazos :: ensamblar(std:: string& objeto , bool& ok){

objeto += "B";ok = true;

}RBrazos :: RBrazos(const RBrazos& r) : Robot(r) {}

}� �Solución: rpiernas.hpp� �

#ifndef rpiernas_hpp_#define rpiernas_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RPiernas : public Robot {public:

RPiernas () ;virtual ˜ RPiernas () ;virtual RPiernas* clone () const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RPiernas(const RPiernas& r) ;

};}#endif� �

Solución: rpiernas.cpp� �#include "rpiernas.hpp"#include <string>using namespace std;namespace umalcc {

RPiernas :: RPiernas () : Robot () {}RPiernas :: ˜ RPiernas () {}RPiernas* RPiernas ::clone () const{

return new RPiernas(*this);}void RPiernas :: ensamblar(std:: string& objeto , bool& ok)

119

Page 120: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{objeto += "P";ok = true;

}RPiernas :: RPiernas(const RPiernas& r) : Robot(r) {}

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include <array>

#include "robot.hpp"#include "rident.hpp"#include "rcabeza.hpp"#include "rtronco.hpp"#include "rbrazos.hpp"#include "rpiernas.hpp"

using namespace std;using namespace umalcc;

const unsigned NANDROIDES = 3;const unsigned NROBOTS = 5;typedef array<Robot*, NROBOTS> CadenaMontaje;typedef array<string , NANDROIDES> Almacen;

int main(){

bool ok = true;CadenaMontaje robot;Almacen almacen;robot[0] = new RIdent("ID");robot[1] = new RCabeza ();robot[2] = new RTronco ();robot[3] = new RBrazos ();robot[4] = new RPiernas ();for (unsigned j = 0; j < almacen.size (); ++j) {

ok = true;std:: string obj;for (unsigned i = 0; ok && (i < robot.size ()); ++i) {

robot[i]->ensamblar(obj , ok);}almacen[j] = obj;

}for (unsigned j = 0; j < almacen.size (); ++j) {

cout << "Androide: " << almacen[j] << endl;}for (unsigned i = 0; i < robot.size (); ++i) {

delete robot[i];}

}� �6. En este segundo ejercicio, se pretende ensamblar un androide un poco más sofisticado, con la siguiente

apariencia en el objeto a construir de tipo string:

ID1o

/|\/ \

considerando que el salto de línea se puede representar con el carácter ’\n’ dentro de un string.

Solución: robot.hpp� �#ifndef robot_hpp_#define robot_hpp_#include <string>namespace umalcc {

120

Page 121: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

class Robot {public:

Robot () ;virtual ˜ Robot () ;virtual Robot* clone() const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:Robot(const Robot& r) ;

private:Robot& operator=(const Robot& o);

};}#endif� �

Solución: robot.cpp� �#include "robot.hpp"#include <string>using namespace std;namespace umalcc {

Robot :: Robot() {}Robot :: ˜ Robot() {}Robot* Robot:: clone() const{

return new Robot(*this);}void Robot:: ensamblar(std:: string& objeto , bool& ok){

ok = false;(void)objeto;

}Robot :: Robot(const Robot& r){

(void)r;}

}� �Solución: rident.hpp� �

#ifndef rident_hpp_#define rident_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RIdent : public Robot {std:: string base;unsigned num;

public:RIdent(const std:: string& b) ;virtual ˜ RIdent () ;virtual RIdent* clone() const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RIdent(const RIdent& r) ;

};}#endif� �

Solución: rident.cpp� �#include "rident.hpp"#include <string>using namespace std;namespace {

std:: string num2str(unsigned n){

std:: string s = "";do {

s = char('0' + (n %10)) + s;n = n / 10;

121

Page 122: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

} while (n > 0);return s;

}}namespace umalcc {

RIdent :: RIdent(const std:: string& b) : Robot(), base(b), num(1) {}RIdent :: ˜ RIdent () {}RIdent* RIdent :: clone() const{

return new RIdent(*this);}void RIdent :: ensamblar(std:: string& objeto , bool& ok){

std:: string id = base + num2str(num);objeto = id + "\n";++num;ok = true;

}RIdent :: RIdent(const RIdent& r) : Robot(r), base(r.base), num(r.num) {}

}� �Solución: rcabeza.hpp� �

#ifndef rcabeza_hpp_#define rcabeza_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RCabeza : public Robot {public:

RCabeza () ;virtual ˜ RCabeza () ;virtual RCabeza* clone () const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RCabeza(const RCabeza& r) ;

};}#endif� �

Solución: rcabeza.cpp� �#include "rcabeza.hpp"#include <string>using namespace std;namespace umalcc {

RCabeza :: RCabeza () : Robot () {}RCabeza :: ˜ RCabeza () {}RCabeza* RCabeza ::clone () const{

return new RCabeza(*this);}void RCabeza :: ensamblar(std:: string& objeto , bool& ok){

objeto += " o \n";ok = true;

}RCabeza :: RCabeza(const RCabeza& r) : Robot(r) {}

}� �Solución: rtronco.hpp� �

#ifndef rtronco_hpp_#define rtronco_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RTronco : public Robot {public:

RTronco () ;

122

Page 123: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

virtual ˜ RTronco () ;virtual RTronco* clone () const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RTronco(const RTronco& r) ;

};}#endif� �

Solución: rtronco.cpp� �#include "rtronco.hpp"#include <string>using namespace std;namespace umalcc {

RTronco :: RTronco () : Robot () {}RTronco :: ˜ RTronco () {}RTronco* RTronco ::clone () const{

return new RTronco(*this);}void RTronco :: ensamblar(std:: string& objeto , bool& ok){

objeto += " | \n";ok = true;

}RTronco :: RTronco(const RTronco& r) : Robot(r) {}

}� �Solución: rbrazos.hpp� �

#ifndef rbrazos_hpp_#define rbrazos_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RBrazos : public Robot {public:

RBrazos () ;virtual ˜ RBrazos () ;virtual RBrazos* clone () const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RBrazos(const RBrazos& r) ;

};}#endif� �

Solución: rbrazos.cpp� �#include "rbrazos.hpp"#include <string>using namespace std;namespace {

unsigned buscar(const string& s, char c){

unsigned i = 0;while ((i < s.size ())&&(c != s[i])) {

++i;}return i;

}}namespace umalcc {

RBrazos :: RBrazos () : Robot () {}RBrazos :: ˜ RBrazos () {}RBrazos* RBrazos ::clone () const{

return new RBrazos(*this);}

123

Page 124: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void RBrazos :: ensamblar(std:: string& objeto , bool& ok){

unsigned p = buscar(objeto , '|');ok = (0 < p && p < objeto.size()-1);if (ok) {

objeto[p-1] = '/';objeto[p+1] = '\\';

}}RBrazos :: RBrazos(const RBrazos& r) : Robot(r) {}

}� �Solución: rpiernas.hpp� �

#ifndef rpiernas_hpp_#define rpiernas_hpp_#include <string>#include "robot.hpp"namespace umalcc {

class RPiernas : public Robot {public:

RPiernas () ;virtual ˜ RPiernas () ;virtual RPiernas* clone () const ;virtual void ensamblar(std:: string& objeto , bool& ok) ;

protected:RPiernas(const RPiernas& r) ;

};}#endif� �

Solución: rpiernas.cpp� �#include "rpiernas.hpp"#include <string>using namespace std;namespace umalcc {

RPiernas :: RPiernas () : Robot () {}RPiernas :: ˜ RPiernas () {}RPiernas* RPiernas ::clone () const{

return new RPiernas(*this);}void RPiernas :: ensamblar(std:: string& objeto , bool& ok){

objeto += "/ \\\n";ok = true;

}RPiernas :: RPiernas(const RPiernas& r) : Robot(r) {}

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include <array>

#include "robot.hpp"#include "rident.hpp"#include "rcabeza.hpp"#include "rtronco.hpp"#include "rbrazos.hpp"#include "rpiernas.hpp"

using namespace std;using namespace umalcc;

const unsigned NANDROIDES = 3;const unsigned NROBOTS = 5;typedef array<Robot*, NROBOTS> CadenaMontaje;

124

Page 125: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

typedef array<string , NANDROIDES> Almacen;

int main(){

bool ok = true;CadenaMontaje robot;Almacen almacen;robot[0] = new RIdent("ID");robot[1] = new RCabeza ();robot[2] = new RTronco ();robot[3] = new RBrazos ();robot[4] = new RPiernas ();for (unsigned j = 0; j < almacen.size (); ++j) {

ok = true;std:: string obj;for (unsigned i = 0; ok && (i < robot.size ()); ++i) {

robot[i]->ensamblar(obj , ok);}almacen[j] = obj;

}for (unsigned j = 0; j < almacen.size (); ++j) {

cout << "Androide: " << almacen[j] << endl;}for (unsigned i = 0; i < robot.size (); ++i) {

delete robot[i];}

}� �7. En este tercer ejercicio, se modifica el objeto a construir para facilitar y flexibilizar la construcción y

ensamblaje de objetos diversos. Así, se define la nueva clase no-polimórfica Objeto2D que permite elensamblaje de piezas (de tipo string) en determinadas posiciones (fila y columna) de un plano-2D (unarray de dos dimensiones donde cada elemento es de tipo char).

Lo robots, ahora, en vez de ensamblar las piezas en un objeto de tipo string, se encargarán de ensamblarlas piezas adecuadas en este Objeto2D, pudiéndose mostrar el resultado final.

ID1o

/|\/ \

La clase no-polimórfica Objeto2D representa una superficie 2D donde es posible ensamblar piezasdiversas (representadas como caracteres en un string) en determinadas posiciones de la superficie,tiene un constructor por defecto que permite crear un objeto, inicializando la superfice vacía, yproporciona los siguientes métodos públicos:

• Tanto el constructor de copia, como el operador de asignación serán generados automáticamentepor el compilador.

• id(i): recibe como parámetro y almacena el identificador asociado al objeto que se está ensam-blando.

• id(): devuelve el identificador que ha sido previamente asignado al objeto actual.• mostrar(): muestra en pantalla tanto el identificador del objeto, como la superficie con las piezas

ensambladas. Es deseable que el tamaño de la zona 2D a mostrar se restrinja al tamaño del objetoensamblado.

• ensamblar_pieza(f, c, p, ok): recibe la fila y columna indicando la posición donde ensamblarla pieza (string) recibida como tercer parámetro, y si todo es correcto, situa cada carácter de lapieza en el sitio especificado. Finalmente, un parámetro ok, de tipo bool, de salida, indicará si laoperación de ensamblaje se ha realizado correctamente. Además, es deseable que vaya registrandoel tamaño del objeto que se está ensamblando.

Solución: objeto2d.hpp� �#ifndef objeto2d_hpp_#define objeto2d_hpp_#include <string>#include <array>

125

Page 126: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

namespace umalcc {class Objeto2D { // CLASE NO−POLIMÓRFICA

static const int NFILS = 10;static const int NCOLS = 30;typedef std::array<char , NCOLS> Fila;typedef std::array<Fila , NFILS> Matriz;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−std:: string ident;unsigned nfils , ncols;Matriz img;

public:˜ Objeto2D () ;Objeto2D () ;//Objeto2D ( const Objeto2D& o) ; // generado automaticamente//Objeto2D& operator=(const Objeto2D& o ) ; // generado automaticamentevoid id(const std:: string& i) ;std:: string id() const ;void ensamblar_pieza(unsigned f, unsigned c,

const std:: string& p, bool& ok) ;void mostrar () const ;

};}#endif� �

Solución: objeto2d.cpp� �#include "objeto2d.hpp"#include <string>#include <array>using namespace std;namespace umalcc {

Objeto2D :: ˜ Objeto2D () {}Objeto2D :: Objeto2D () : ident(), nfils(0), ncols(0), img() {

for (unsigned f = 0; f < img.size (); ++f) {for (unsigned c = 0; c < img[f].size (); ++c) {

img[f][c] = ' ';}

}}void Objeto2D ::id(const std:: string& i){

ident = i;}std:: string Objeto2D ::id() const{

return ident;}void Objeto2D :: ensamblar_pieza(unsigned f, unsigned c,

const std:: string& p, bool& ok){

if (f < img.size() && c < img[f].size() && p.size() > 0) {ok = true;if (f >= nfils) {

nfils = f + 1;}if (c+p.size() > ncols) {

ncols = c + p.size ();if (ncols > img[f].size ()) {

ncols = img[f].size ();}

}for (unsigned j = 0; (j < p.size ())&&(c+j < img[f].size ()); ++j) {

img[f][c+j] = p[j];}

} else {ok = false;

}}void Objeto2D :: mostrar () const {

cout << ident << endl;for (unsigned f = 0; f < nfils; ++f) {

for (unsigned c = 0; c < ncols; ++c) {cout << img[f][c];

126

Page 127: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}cout << endl;

}}

}� �Solución: robot.hpp� �

#ifndef robot_hpp_#define robot_hpp_#include <string>#include "objeto2d.hpp"namespace umalcc {

class Robot {public:

Robot () ;virtual ˜ Robot () ;virtual Robot* clone() const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:Robot(const Robot& r) ;

private:Robot& operator=(const Robot& o);

};}#endif� �

Solución: robot.cpp� �#include "robot.hpp"#include <string>using namespace std;namespace umalcc {

Robot :: Robot() {}Robot :: ˜ Robot() {}Robot* Robot:: clone() const{

return new Robot(*this);}void Robot:: ensamblar(Objeto2D& objeto , bool& ok){

ok = false;(void)objeto;

}Robot :: Robot(const Robot& r){

(void)r;}

}� �Solución: rident.hpp� �

#ifndef rident_hpp_#define rident_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RIdent : public Robot {std:: string base;unsigned num;

public:RIdent(const std:: string& b) ;virtual ˜ RIdent () ;virtual RIdent* clone() const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RIdent(const RIdent& r) ;

};}#endif� �

127

Page 128: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: rident.cpp� �#include "rident.hpp"#include <string>using namespace std;namespace {

std:: string num2str(unsigned n){

std:: string s = "";do {

s = char('0' + (n %10)) + s;n = n / 10;

} while (n > 0);return s;

}}namespace umalcc {

RIdent :: RIdent(const std:: string& b) : Robot(), base(b), num(1) {}RIdent :: ˜ RIdent () {}RIdent* RIdent :: clone() const{

return new RIdent(*this);}void RIdent :: ensamblar(Objeto2D& objeto , bool& ok){

std:: string id = base + num2str(num);objeto.id(id);++num;ok = true;

}RIdent :: RIdent(const RIdent& r) : Robot(r), base(r.base), num(r.num) {}

}� �Solución: rcabeza.hpp� �

#ifndef rcabeza_hpp_#define rcabeza_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RCabeza : public Robot {public:

RCabeza () ;virtual ˜ RCabeza () ;virtual RCabeza* clone () const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RCabeza(const RCabeza& r) ;

};}#endif� �

Solución: rcabeza.cpp� �#include "rcabeza.hpp"#include <string>using namespace std;namespace umalcc {

RCabeza :: RCabeza () : Robot () {}RCabeza :: ˜ RCabeza () {}RCabeza* RCabeza ::clone () const{

return new RCabeza(*this);}void RCabeza :: ensamblar(Objeto2D& objeto , bool& ok){

objeto.ensamblar_pieza (0, 1, "o", ok);}RCabeza :: RCabeza(const RCabeza& r) : Robot(r) {}

}� �128

Page 129: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: rtronco.hpp� �#ifndef rtronco_hpp_#define rtronco_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RTronco : public Robot {public:

RTronco () ;virtual ˜ RTronco () ;virtual RTronco* clone () const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RTronco(const RTronco& r) ;

};}#endif� �

Solución: rtronco.cpp� �#include "rtronco.hpp"#include <string>using namespace std;namespace umalcc {

RTronco :: RTronco () : Robot () {}RTronco :: ˜ RTronco () {}RTronco* RTronco ::clone () const{

return new RTronco(*this);}void RTronco :: ensamblar(Objeto2D& objeto , bool& ok){

objeto.ensamblar_pieza (1, 1, "|", ok);}RTronco :: RTronco(const RTronco& r) : Robot(r) {}

}� �Solución: rbrazos.hpp� �

#ifndef rbrazos_hpp_#define rbrazos_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RBrazos : public Robot {public:

RBrazos () ;virtual ˜ RBrazos () ;virtual RBrazos* clone () const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RBrazos(const RBrazos& r) ;

};}#endif� �

Solución: rbrazos.cpp� �#include "rbrazos.hpp"#include <string>using namespace std;namespace umalcc {

RBrazos :: RBrazos () : Robot () {}RBrazos :: ˜ RBrazos () {}RBrazos* RBrazos ::clone () const{

return new RBrazos(*this);}

129

Page 130: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void RBrazos :: ensamblar(Objeto2D& objeto , bool& ok){

objeto.ensamblar_pieza (1, 0, "/", ok);if (ok) { objeto.ensamblar_pieza (1, 2, "\\", ok); }

}RBrazos :: RBrazos(const RBrazos& r) : Robot(r) {}

}� �Solución: rpiernas.hpp� �

#ifndef rpiernas_hpp_#define rpiernas_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RPiernas : public Robot {public:

RPiernas () ;virtual ˜ RPiernas () ;virtual RPiernas* clone () const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RPiernas(const RPiernas& r) ;

};}#endif� �

Solución: rpiernas.cpp� �#include "rpiernas.hpp"#include <string>using namespace std;namespace umalcc {

RPiernas :: RPiernas () : Robot () {}RPiernas :: ˜ RPiernas () {}RPiernas* RPiernas ::clone () const{

return new RPiernas(*this);}void RPiernas :: ensamblar(Objeto2D& objeto , bool& ok){

objeto.ensamblar_pieza (2, 0, "/", ok);if (ok) { objeto.ensamblar_pieza (2, 2, "\\", ok); }

}RPiernas :: RPiernas(const RPiernas& r) : Robot(r) {}

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include <array>

#include "objeto2d.hpp"#include "robot.hpp"#include "rident.hpp"#include "rcabeza.hpp"#include "rtronco.hpp"#include "rbrazos.hpp"#include "rpiernas.hpp"

using namespace std;using namespace umalcc;

const unsigned NANDROIDES = 3;const unsigned NROBOTS = 5;typedef array<Robot*, NROBOTS> CadenaMontaje;typedef array<Objeto2D , NANDROIDES> Almacen;

130

Page 131: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

int main(){

bool ok = true;CadenaMontaje robot;Almacen almacen;robot[0] = new RIdent("ID");robot[1] = new RCabeza ();robot[2] = new RTronco ();robot[3] = new RBrazos ();robot[4] = new RPiernas ();for (unsigned j = 0; j < almacen.size (); ++j) {

ok = true;Objeto2D obj;for (unsigned i = 0; ok && (i < robot.size ()); ++i) {

robot[i]->ensamblar(obj , ok);}almacen[j] = obj;

}for (unsigned j = 0; j < almacen.size (); ++j) {

cout << "Androide: ";almacen[j].mostrar ();

}for (unsigned i = 0; i < robot.size (); ++i) {

delete robot[i];}

}� �8. En este cuarto ejercicio, se debe definir una nueva clase no-polimórfica denominada Factoria que contiene

una cadena de robots de ensamblaje (en un array), los cuales construyen androides pasándose el Objeto2Dentre ellos a lo largo de la cadena, y finalmente el producto final se almacena en un determinado almacen(array) de Objeto2D. Estos productos finales ya ensamblados pueden ser extraidos para su utilizaciónfuera de la factoría.

La clase no-polimórfica Factoria representa una factoría con un almacen de como máximo 10Objeto2D ensamblados, y una cadena de Robot con los 5 robots de ensamblaje especializados, tieneun constructor que permite crear un objeto con el símbolo inicial de identificación (string) recibidocomo parámetro, de tal forma que todos los androides ensamblados tendrán el mismo símbolo basede identificación y construye los 5 robots especializados en la cadena de ensamblaje. Además, la claseproporciona los siguientes métodos públicos:

• Se debe implementar el constructor de copia y el operador de asignación, que permitan copiarla estructura de datos de la clase.

• construir(ok): si hay espacio en el almacen, entonces ensambla completamente un nuevo an-droide y lo almacena adecuadamente. Si la operación es posible o no, entonces devuelve true ofalse, respectivamente, en el parámetro de salida.

• mostrar_almacen(): muestra en pantalla a todos los androides ensamblados que se encuentranen el almacen.

• obtener_nobjs(): devuelve la cantidad de androides ensamblados que se encuentran en el al-macen.

• extraer(): extrae del almacen y devuelve un Objeto2D con un androide ensamblado que seencuentre en el almacen. Si no hay ningún androide ensamblado en el almacen, entonces devuelveun Objeto2D vacío.

El programa principal creará una factoría, y construirá adecuadamente una determinada cantidad deandroides, que serán almacenados en el almacen de la factoría. Finalmente, extraerá los androidesalmacenados y los mostrara por pantalla.

Solución: objeto2d.hpp� �#ifndef objeto2d_hpp_#define objeto2d_hpp_#include <string>#include <array>namespace umalcc {

class Objeto2D { // CLASE NO−POLIMÓRFICAstatic const int NFILS = 10;static const int NCOLS = 30;

131

Page 132: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

typedef std::array<char , NCOLS> Fila;typedef std::array<Fila , NFILS> Matriz;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−std:: string ident;unsigned nfils , ncols;Matriz img;

public:˜ Objeto2D () ;Objeto2D () ;//Objeto2D ( const Objeto2D& o) ; // generado automaticamente//Objeto2D& operator=(const Objeto2D& o ) ; // generado automaticamentevoid id(const std:: string& i) ;std:: string id() const ;void ensamblar_pieza(unsigned f, unsigned c,

const std:: string& p, bool& ok) ;void mostrar () const ;

};}#endif� �

Solución: objeto2d.cpp� �#include "objeto2d.hpp"#include <string>#include <array>using namespace std;namespace umalcc {

Objeto2D :: ˜ Objeto2D () {}Objeto2D :: Objeto2D () : ident(), nfils(0), ncols(0), img() {

for (unsigned f = 0; f < img.size (); ++f) {for (unsigned c = 0; c < img[f].size (); ++c) {

img[f][c] = ' ';}

}}void Objeto2D ::id(const std:: string& i){

ident = i;}std:: string Objeto2D ::id() const{

return ident;}void Objeto2D :: ensamblar_pieza(unsigned f, unsigned c,

const std:: string& p, bool& ok){

if (f < img.size() && c < img[f].size() && p.size() > 0) {ok = true;if (f >= nfils) {

nfils = f + 1;}if (c+p.size() > ncols) {

ncols = c + p.size ();if (ncols > img[f].size ()) {

ncols = img[f].size ();}

}for (unsigned j = 0; (j < p.size ())&&(c+j < img[f].size ()); ++j) {

img[f][c+j] = p[j];}

} else {ok = false;

}}void Objeto2D :: mostrar () const {

cout << ident << endl;for (unsigned f = 0; f < nfils; ++f) {

for (unsigned c = 0; c < ncols; ++c) {cout << img[f][c];

}cout << endl;

}}

132

Page 133: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}� �Solución: robot.hpp� �

#ifndef robot_hpp_#define robot_hpp_#include <string>#include "objeto2d.hpp"namespace umalcc {

class Robot {public:

Robot () ;virtual ˜ Robot () ;virtual Robot* clone() const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:Robot(const Robot& r) ;

private:Robot& operator=(const Robot& o);

};}#endif� �

Solución: robot.cpp� �#include "robot.hpp"#include <string>using namespace std;namespace umalcc {

Robot :: Robot() {}Robot :: ˜ Robot() {}Robot* Robot:: clone() const{

return new Robot(*this);}void Robot:: ensamblar(Objeto2D& objeto , bool& ok){

ok = false;(void)objeto;

}Robot :: Robot(const Robot& r){

(void)r;}

}� �Solución: rident.hpp� �

#ifndef rident_hpp_#define rident_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RIdent : public Robot {std:: string base;unsigned num;

public:RIdent(const std:: string& b) ;virtual ˜ RIdent () ;virtual RIdent* clone() const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RIdent(const RIdent& r) ;

};}#endif� �

133

Page 134: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: rident.cpp� �#include "rident.hpp"#include <string>using namespace std;namespace {

std:: string num2str(unsigned n){

std:: string s = "";do {

s = char('0' + (n %10)) + s;n = n / 10;

} while (n > 0);return s;

}}namespace umalcc {

RIdent :: RIdent(const std:: string& b) : Robot(), base(b), num(1) {}RIdent :: ˜ RIdent () {}RIdent* RIdent :: clone() const{

return new RIdent(*this);}void RIdent :: ensamblar(Objeto2D& objeto , bool& ok){

std:: string id = base + num2str(num);objeto.id(id);++num;ok = true;

}RIdent :: RIdent(const RIdent& r) : Robot(r), base(r.base), num(r.num) {}

}� �Solución: rcabeza.hpp� �

#ifndef rcabeza_hpp_#define rcabeza_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RCabeza : public Robot {public:

RCabeza () ;virtual ˜ RCabeza () ;virtual RCabeza* clone () const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RCabeza(const RCabeza& r) ;

};}#endif� �

Solución: rcabeza.cpp� �#include "rcabeza.hpp"#include <string>using namespace std;namespace umalcc {

RCabeza :: RCabeza () : Robot () {}RCabeza :: ˜ RCabeza () {}RCabeza* RCabeza ::clone () const{

return new RCabeza(*this);}void RCabeza :: ensamblar(Objeto2D& objeto , bool& ok){

objeto.ensamblar_pieza (0, 1, "o", ok);}RCabeza :: RCabeza(const RCabeza& r) : Robot(r) {}

}� �134

Page 135: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: rtronco.hpp� �#ifndef rtronco_hpp_#define rtronco_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RTronco : public Robot {public:

RTronco () ;virtual ˜ RTronco () ;virtual RTronco* clone () const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RTronco(const RTronco& r) ;

};}#endif� �

Solución: rtronco.cpp� �#include "rtronco.hpp"#include <string>using namespace std;namespace umalcc {

RTronco :: RTronco () : Robot () {}RTronco :: ˜ RTronco () {}RTronco* RTronco ::clone () const{

return new RTronco(*this);}void RTronco :: ensamblar(Objeto2D& objeto , bool& ok){

objeto.ensamblar_pieza (1, 1, "|", ok);}RTronco :: RTronco(const RTronco& r) : Robot(r) {}

}� �Solución: rbrazos.hpp� �

#ifndef rbrazos_hpp_#define rbrazos_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RBrazos : public Robot {public:

RBrazos () ;virtual ˜ RBrazos () ;virtual RBrazos* clone () const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RBrazos(const RBrazos& r) ;

};}#endif� �

Solución: rbrazos.cpp� �#include "rbrazos.hpp"#include <string>using namespace std;namespace umalcc {

RBrazos :: RBrazos () : Robot () {}RBrazos :: ˜ RBrazos () {}RBrazos* RBrazos ::clone () const{

return new RBrazos(*this);}

135

Page 136: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void RBrazos :: ensamblar(Objeto2D& objeto , bool& ok){

objeto.ensamblar_pieza (1, 0, "/", ok);if (ok) { objeto.ensamblar_pieza (1, 2, "\\", ok); }

}RBrazos :: RBrazos(const RBrazos& r) : Robot(r) {}

}� �Solución: rpiernas.hpp� �

#ifndef rpiernas_hpp_#define rpiernas_hpp_#include <string>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class RPiernas : public Robot {public:

RPiernas () ;virtual ˜ RPiernas () ;virtual RPiernas* clone () const ;virtual void ensamblar(Objeto2D& objeto , bool& ok) ;

protected:RPiernas(const RPiernas& r) ;

};}#endif� �

Solución: rpiernas.cpp� �#include "rpiernas.hpp"#include <string>using namespace std;namespace umalcc {

RPiernas :: RPiernas () : Robot () {}RPiernas :: ˜ RPiernas () {}RPiernas* RPiernas ::clone () const{

return new RPiernas(*this);}void RPiernas :: ensamblar(Objeto2D& objeto , bool& ok){

objeto.ensamblar_pieza (2, 0, "/", ok);if (ok) { objeto.ensamblar_pieza (2, 2, "\\", ok); }

}RPiernas :: RPiernas(const RPiernas& r) : Robot(r) {}

}� �Solución: factoria.hpp� �

#ifndef factoria_hpp_#define factoria_hpp_#include <string>#include <array>#include "robot.hpp"#include "objeto2d.hpp"namespace umalcc {

class Factoria { // CLASE NO−POLIMÓRFICAstatic const int NROBOTS = 5;static const int MAX_OBJS = 10;typedef std::array<Robot*, NROBOTS> Robots;typedef std::array<Objeto2D , MAX_OBJS> Almacen;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned nobjs;Almacen almacen;Robots robot;

public:˜ Factoria () ;Factoria(const std:: string& id) ;Factoria(const Factoria& o) ;

136

Page 137: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Factoria& operator=(const Factoria& o);void construir(bool& ok) ;void mostrar_almacen () const ;unsigned obtener_nobjs () const ;Objeto2D extraer () ;

private:void clonar_robots(const Factoria& o) ;void copiar_objs(const Factoria& o) ;void destruir_robots () ;void destruir_almacen () ;

};}#endif� �

Solución: factoria.cpp� �#include "factoria.hpp"#include <string>#include "robot.hpp"#include "rident.hpp"#include "rcabeza.hpp"#include "rtronco.hpp"#include "rbrazos.hpp"#include "rpiernas.hpp"using namespace std;namespace umalcc {

Factoria :: ˜ Factoria (){

destruir_robots ();}Factoria :: Factoria(const std:: string& id) : nobjs(0), almacen(), robot() {

robot[0] = new RIdent(id);robot[1] = new RCabeza ();robot[2] = new RTronco ();robot[3] = new RBrazos ();robot[4] = new RPiernas ();

}Factoria :: Factoria(const Factoria& o) : nobjs(0), almacen(), robot() {

copiar_objs(o);clonar_robots(o);

}Factoria& Factoria :: operator=(const Factoria& o){

if (this != &o) {destruir_robots ();copiar_objs(o);clonar_robots(o);

}return *this;

}void Factoria :: construir(bool& ok){

ok = (nobjs < almacen.size ());if (ok) {

Objeto2D obj;for (unsigned i = 0; ok && (i < robot.size ()); ++i) {

robot[i]->ensamblar(obj , ok);}if (ok) {

almacen[nobjs] = obj;++nobjs;

}}

}void Factoria :: mostrar_almacen () const{

for (unsigned j = 0; j < nobjs; ++j) {almacen[j].mostrar ();

}}unsigned Factoria :: obtener_nobjs () const{

return nobjs;

137

Page 138: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}Objeto2D Factoria :: extraer (){

Objeto2D obj;if (nobjs > 0) {

--nobjs;obj = almacen[nobjs];

}return obj;

}void Factoria :: clonar_robots(const Factoria& o){

for (unsigned i = 0; i < robot.size (); ++i) {robot[i] = o.robot[i]->clone ();

}}void Factoria :: copiar_objs(const Factoria& o){

nobjs = o.nobjs;for (unsigned i = 0; i < nobjs; ++i) {

almacen[i] = o.almacen[i];}

}void Factoria :: destruir_robots (){

for (unsigned i = 0; i < robot.size (); ++i) {delete robot[i];

}}

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include <array>

#include "objeto2d.hpp"#include "factoria.hpp"

using namespace std;using namespace umalcc;

const unsigned NANDROIDES = 3;

int main(){

Factoria factoria("ID");bool ok = true;for (unsigned j = 0; j < NANDROIDES; ++j) {

factoria.construir(ok);if (!ok) {

cout << "Error de construcción" << endl;}

}while (factoria.obtener_nobjs () > 0) {

Objeto2D obj = factoria.extraer ();cout << "Androide: ";obj.mostrar ();

}}� �

138

Page 139: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Tema 5: Colecciones1. Diseñe un programa que utilice el tipo vector de la biblioteca estándar para almacenar las personas de

una agenda, donde por cada persona se almacena el nombre y el teléfono. La agenda se gestiona mediantela siguientes operaciones:

Añadir los datos de una persona a la agenda, de tal forma que si la persona ya existe, entonces seactualiza su número de teléfono, y en otro caso, se añade la nueva persona y su teléfono a la agenda.

Mostrar todos los datos de la agenda.

Mostrar los datos de una determinada persona, a partir de su nombre recibido como parámetro. Encaso de que no exista en la agenda ninguna persona con dicho nombre, entonces se mostrará unmensaje de error.

Borrar los datos de una determinada persona, a partir de su nombre recibido como parámetro. Encaso de que no exista en la agenda ninguna persona con dicho nombre, entonces se mostrará unmensaje de error.

Solución: agenda.hpp� �#ifndef agenda_hpp_#define agenda_hpp_#include <string>#include <vector>namespace umalcc {

class Agenda {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//~Agenda ( ) ; // Generado automáticamente//Agenda ( ) ; // Generado automáticamente//Agenda( const Agenda& o ) ; // Generado automáticamente//Agenda& operator=(const Agenda& o ) ; // Generado automáticamente//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void anyadir(const std:: string& n, const std:: string& t);void mostrar(const std:: string& n, bool& ok) const;void mostrar () const;void borrar(const std:: string& n, bool& ok);//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

private:struct Persona {

std:: string nombre;std:: string tfn;

};typedef std:: vector<Persona> Datos;//−− Atr i bu tos −−−−−−−−−−−−−−−−−Datos ag;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int buscar(const std:: string& n) const;void mostrar(const Persona& p) const;

};}#endif� �

Solución: agenda.cpp� �#include "agenda.hpp"#include <iostream>using namespace std;namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: anyadir(const std:: string& n, const std:: string& t){

int pos = buscar(n);if (0 <= pos && pos < int(ag.size ())) {

ag[pos].tfn = t;} else {

Persona p = { n, t };ag.push_back(p);

}}

139

Page 140: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: mostrar(const std:: string& n, bool& ok) const{

int pos = buscar(n);ok = (0 <= pos && pos < int(ag.size ()));if (ok) {

mostrar(ag[pos]);}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: mostrar () const{

cout << "--------------------" << endl;for (int i = 0; i < int(ag.size ()); ++i) {

mostrar(ag[i]);cout << "--------------------" << endl;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: borrar(const std:: string& n, bool& ok){

int pos = buscar(n);ok = (0 <= pos && pos < int(ag.size ()));if (ok) {

if (pos < int(ag.size ()) - 1) {ag[pos] = ag[ag.size() - 1];

}ag.pop_back ();

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int Agenda :: buscar(const std:: string& n) const{

int i = 0;while ((i < int(ag.size ())) && (ag[i].nombre != n)) {

++i;}return i;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: mostrar(const Persona& p) const{

cout << "Nombre: " << p.nombre << endl;cout << "Teléfono: " << p.tfn << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include <cctype>#include "agenda.hpp"using namespace std;using namespace umalcc;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_nombre(string& nombre){

cout << "Introduza nombre (sin espacios ): ";cin >> nombre;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(string& nombre , string& tfn){

leer_nombre(nombre );cout << "Introduza telefono: ";cin >> tfn;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;

140

Page 141: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << endl;cout << "A. Añadir datos de persona" << endl;cout << "B. Mostrar toda la agenda" << endl;cout << "C. Mostrar datos de persona" << endl;cout << "D. Borrar persona" << endl;cout << "X. Fin" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!(((op >= 'A')&&(op <= 'D'))||(op == 'X')));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Agenda ag;string n, t;bool ok;char op;do {

op = menu ();switch (op) {case 'A':

leer_persona(n, t);ag.anyadir(n, t);break;

case 'B':ag.mostrar ();break;

case 'C':leer_nombre(n);ag.mostrar(n, ok);if (!ok) {

cout << "Error , persona no encontrada" << endl;}break;

case 'D':leer_nombre(n);ag.borrar(n, ok);if (!ok) {

cout << "Error , persona no encontrada" << endl;}break;

}} while (op != 'X');

}� �2. Realice el ejercicio anterior, utilizando el TAD Persona definido en la práctica 7 (agenda-hash), e imple-

mentando el TAD Agenda de la misma práctica con vector en vez de con una lista enlazada.

Solución: persona.hpp� �#ifndef persona_hpp_#define persona_hpp_#include <string>namespace umalcc {

class Persona {public:

˜ Persona () ;// Destruye e l o b j e t o y todos sus recursos asoc iados .

Persona () ;// Construye una persona con nombre y t e l e f o no vac ío .

Persona(const std:: string& n, const std:: string& t) ;// Construye una persona con e l nombre y e l t e l e f o no// segun l o s parametros r e c i b i d o s .

bool error() const;// Devuelve t rue s i e l o b j e t o ac tua l e s ta en es tado erroneo ,// es decir , e l nombre o e l t e l e f o no son vac ío s .

std:: string obtener_nombre () const;// Devuelve e l va l o r de l nombre de l o b j e t o ac tua l .

std:: string obtener_telefono () const;

141

Page 142: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// Devuelve e l va l o r de l t e l e f o no de l o b j e t o ac tua l .private:

std:: string nombre;std:: string telefono;

};}#endif� �

Solución: persona.cpp� �#include "persona.hpp"#include <string>using namespace std;namespace umalcc {

Persona :: ˜ Persona () {}Persona :: Persona () : nombre(), telefono () {}Persona :: Persona(const std:: string& n, const std:: string& t)

: nombre(n), telefono(t) {}bool Persona ::error () const{

return (nombre.size() == 0)||(telefono.size() == 0);}std:: string Persona :: obtener_nombre () const{

return nombre;}std:: string Persona :: obtener_telefono () const{

return telefono;}

}� �Solución: agenda.hpp� �

#ifndef agenda_hpp_#define agenda_hpp_#include "persona.hpp"#include <string>#include <vector>namespace umalcc {

class Agenda {public:

//~Agenda () ;// Destruye e l o b j e t o y todos sus recursos asoc iados .

//Agenda () ;// Construye una agenda vac ia .

//Agenda( const Agenda& o) ;// Construye una agenda como copia de otra agenda

//Agenda& operator=(const Agenda& o) ;// Construye una agenda como copia de otra agenda

void anyadir(const Persona& p);// Si l a persona e s p e c i f i c a da como parametro no es ta en modo// erroneo , s i l a persona ya se encontraba en l a agenda ,// entonces l o s nuevos va l o r e s de l a persona reemplazan a l o s// anter iore s , en otro caso anyade l a persona e s p e c i f i c a da a// l a agenda ac tua l .

Persona buscar(const std:: string& nombre) const;// Busca en l a agenda l a persona cuyo nombre se e s p e c i f i c a// como parametro , y s i l a encuentra , entonces devue l ve un ob j e t o// Persona con l o s va l o r e s de l a persona almacenados . Si no// l a encuentra , entonces devue l ve una persona en es tado de// error .

void eliminar(const std:: string& nombre , bool& ok);// Elimina de l a agenda ac tua l l a persona cuyo nombre se// e s p e c i f i c a como parametro y ok tomara e l va l o r t rue . En caso// de no e x i s t i r , ok tomara e l va l o r f a l s e .

void mostrar () const;// Muestra en pan t a l l a e l contenido completo de l a agenda .

private:typedef std:: vector<Persona> Datos;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned buscar(const Datos& d, const std:: string& nombre) const;

142

Page 143: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−Datos v;

};}#endif� �

Solución: agenda.cpp� �#include "agenda.hpp"#include "persona.hpp"#include <iostream>#include <string>#include <vector>using namespace std;namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//Agenda : :~ Agenda () {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//Agenda : : Agenda () : v () {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//Agenda : : Agenda( const Agenda& o) : v (o . v ) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//Agenda& Agenda : : operator=(const Agenda& o)//{// i f ( t h i s != &o) {// v = o . v ;// }// return ∗ t h i s ;//}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: anyadir(const Persona& p){

if (! p.error ()) {unsigned i = buscar(v, p.obtener_nombre ());if (i < v.size ()) {

v[i] = p;} else {

v.push_back(p);}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Persona Agenda :: buscar(const std:: string& nombre) const{

Persona p;unsigned i = buscar(v, nombre );if (i < v.size ()) {

p = v[i];}return p;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: eliminar(const std:: string& nombre , bool& ok){

unsigned i = buscar(v, nombre );if (i < v.size ()) {

ok = true;if (i < v.size() - 1) {

v[i] = v[v.size() - 1];}v.pop_back ();

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: mostrar () const{

cout << "N_Personas: " << v.size() << endl;for (unsigned i = 0; i < v.size (); ++i) {

cout << "[" << i << "]: "<< v[i].obtener_nombre () << " "

143

Page 144: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

<< v[i].obtener_telefono () << endl ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned Agenda :: buscar(const Datos& d, const std:: string& nombre) const{

unsigned i = 0 ;while ((i < d.size ())&&(nombre != d[i].obtener_nombre ())) {

++i ;}return i ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include <cctype>#include "persona.hpp"#include "agenda.hpp"using namespace std;using namespace umalcc;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_nombre(string& nombre){

cout << "Introduza nombre (sin espacios ): ";cin >> nombre;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(Persona& p){

string nombre , tfn;leer_nombre(nombre );cout << "Introduza telefono: ";cin >> tfn;p = Persona(nombre , tfn);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void mostrar_persona(const Persona& p){

cout << "Nombre: " << p.obtener_nombre () << endl;cout << "telefono: " << p.obtener_telefono () << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "A. Añadir datos de persona" << endl;cout << "B. Mostrar toda la agenda" << endl;cout << "C. Mostrar datos de persona" << endl;cout << "D. Borrar persona" << endl;cout << "X. Fin" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!(((op >= 'A')&&(op <= 'D'))||(op == 'X')));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Agenda ag;Persona p;string n;bool ok;char op;do {

op = menu ();

144

Page 145: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

switch (op) {case 'A':

leer_persona(p);ag.anyadir(p);break;

case 'B':ag.mostrar ();break;

case 'C':leer_nombre(n);p = ag.buscar(n);if (p.error ()) {

cout << "Error , persona no encontrada" << endl;} else {

mostrar_persona(p);}break;

case 'D':leer_nombre(n);ag.eliminar(n, ok);if (!ok) {

cout << "Error , persona no encontrada" << endl;}break;

}} while (op != 'X');

}� �3. Diseñe un programa que lea y almacene en un vector de la biblioteca estándar las ventas realizadas por

unos agentes de ventas. Leerá el nombre y el total de ventas que ha realizado, hasta leer un nombre deagente vacío. Posteriormente se eliminarán del vector aquellos agentes cuyas ventas sean inferiores a lamedia de las ventas realizadas. Finalmente se mostrará el contenido del vector.

Solución� �#include <iostream>#include <vector>#include <string>using namespace std ;

struct Agente {string nombre ;double ventas ;

} ;

typedef vector<Agente> VAgentes ;

void leer (VAgentes& v){

v.clear() ;Agente a ;cout << "Introduzca Nombre: " ;getline(cin , a.nombre) ;while (( ! cin.fail ()) && (a.nombre.size() > 0)) {

cout << "Introduzca Ventas: " ;cin >> a.ventas ;cin.ignore (1000 , '\n') ;v.push_back(a) ;cout << "Introduzca Nombre: " ;getline(cin , a.nombre) ;

}}

double media(const VAgentes& v){

double suma=0.0 ;for (int i = 0 ; i < int(v.size ()) ; ++i) {

suma += v[i].ventas ;}return suma/double(v.size ()) ;

}

145

Page 146: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void purgar(VAgentes& v, double media){

// a l t e r a e l orden s ecuenc i a l de l o s e lementosint i = 0 ;while (i < int(v.size ())) {

if (v[i].ventas < media) {v[i] = v[v.size()-1] ;v.pop_back () ;

} else {++i ;

}}

}

void purgar_ordenado(VAgentes& v, double media){

// mantiene e l orden s ecuenc i a l de l o s e lementosint k = 0 ;while ((k < int(v.size ()))&&(v[k].ventas >= media)) {

++k;}for (int i = k ; i < int(v.size ()) ; ++i) {

if(v[i].ventas >= media) {v[k] = v[i] ;++k ;

}}v.resize(k) ;

}

void imprimir(const VAgentes& v){

for (int i = 0 ; i < int(v.size ()) ; ++i) {cout << v[i].nombre << " " << v[i].ventas << endl ;

}}

int main (){

VAgentes v ;leer(v) ;purgar(v, media(v)) ;imprimir(v) ;

}� �4. Diseñe un programa que lea dos matrices de números reales de tamaños arbitrarios (primero leerá las

dimensiones y posteriormente los elementos de la matriz) y muestre el resultado de multiplicar ambasmatrices. Las matrices se almacenarán en vectores de dos dimensiones (utilizando el tipo vector de labiblioteca estándar).

Solución� �#include <vector>#include <iostream>#include <iomanip>using namespace std ;

typedef vector <double> Fila ;typedef vector <Fila> Matriz ;

void imprimir(const Matriz& m){

for (int f = 0 ; f < int(m.size ()) ; ++f) {for (int c = 0 ; c < int(m[f].size ()) ; ++c) {

cout << setw (10) << setprecision (4)<< m[f][c] << " " ;

}cout << endl ;

}}

void leer(Matriz& m)

146

Page 147: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{int nf, nc ;cout << "Introduzca el numero de filas: " ;cin >> nf ;cout << "Introduzca el numero de columnas: " ;cin >> nc ;m = Matriz(nf, Fila (nc)) ; // copia de l a matriz completacout << "Introduzca los elementos: " << endl ;for (int f = 0 ; f < int(m.size ()) ; ++f) {

for (int c = 0 ; c < int(m[f].size ()) ; ++c) {cin >> m[f][c] ;

}}

}

// otra opción más e f i c i e n t e para l a l e c t u r a de vec t o r e svoid leer_2(Matriz& m){

int nf, nc ;cout << "Introduzca el numero de filas: " ;cin >> nf ;cout << "Introduzca el numero de columnas: " ;cin >> nc ;Matriz aux(nf, Fila (nc)) ;cout << "Introduzca los elementos: " << endl ;for (int f = 0 ; f < int(aux.size ()) ; ++f) {

for (int c = 0 ; c < int(aux[f].size ()) ; ++c) {cin >> aux[f][c] ;

}}m.swap(aux) ; // e v i t a l a copia de l a matriz completa

}

void multiplicar(const Matriz& m1 , const Matriz& m2, Matriz& m3){

m3.clear() ;if ((m1.size() > 0) && (m2.size() > 0) && (m2[0].size() > 0)

&& (m1[0].size() == m2.size ())){Matriz aux(m1.size(), Fila(m2[0].size ())) ;for (int f = 0 ; f < int(aux.size ()) ; ++f) {

for (int c = 0 ; c < int(aux[f].size ()) ; ++c) {double suma = 0.0 ;for (int k = 0 ; k < int(m2.size ()) ; ++k) {

suma += m1[f][k] * m2[k][c] ;}aux[f][c] = suma ;

}}m3.swap(aux) ; // e v i t a l a copia de l a matriz completa

}}

int main(){

Matriz m1, m2, m3 ;leer(m1) ;leer(m2) ;multiplicar(m1, m2, m3) ;if (m3.size() == 0) {

cout << "Error en la multiplicación de Matrices" << endl ;} else {

imprimir(m3) ;}

}� �5. Diseñe un programa que lea una expresión aritmética que contiene llaves {}, paréntesis () y corchetes []

y compruebe si éstos se encuentran correctamente equilibrados o no. Por ejemplo la siguiente expresión3 + 5 ∗ ([4]− 67) + [(7)] se encuentra correctamente equilibrada, donde los posibles casos de error son lossiguientes:

Un símbolo de apertura no se corresponde con su correspondiente símbolo de cierre. Por ejemplo:3 + 5 ∗ ([4]− 67] + [(7)]

147

Page 148: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Para un determinado símbolo de apertura, no existe el correspondiente símbolo de cierre. Por ejemplo:(3 + 5 ∗ ([4]− 67 + [(7)])

Para un determinado símbolo de cierre, no existe el correspondiente símbolo de apertura. Por ejemplo:(3 + 5 ∗ [4]− 67) + [(7)])

Solución: pila_char.hpp� �#ifndef pila_char_hpp_#define pila_char_hpp_#include <vector>namespace umalcc {

class PilaChar {public:

typedef char TipoElem;˜ PilaChar ();PilaChar ();PilaChar(const PilaChar& o);PilaChar& operator=(const PilaChar& o);void push(const TipoElem& val);TipoElem top() const;void pop ();bool empty() const;

private:std:: vector<TipoElem> v;

} ;}#endif� �

Solución: pila_char.cpp� �#include "pila_char.hpp"namespace umalcc {

PilaChar :: ˜ PilaChar () {}PilaChar :: PilaChar () : v() {}PilaChar :: PilaChar(const PilaChar& o) : v(o.v) {}PilaChar& PilaChar :: operator=(const PilaChar& o) {

v = o.v;return *this;

}void PilaChar ::push(const TipoElem& val) {

v.push_back(val);}PilaChar :: TipoElem PilaChar ::top() const {

TipoElem r = TipoElem ();if (v.size() > 0) {

r = v[v.size()-1];}return r;

}void PilaChar ::pop() {

if (v.size() > 0) {v.pop_back ();

}}bool PilaChar ::empty() const {

return v.size() == 0;}

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include "pila_char.hpp"using namespace std;using namespace umalcc;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−const int CORRECTO = 0;const int NO_CORRESPONDE = 1;const int FALTA_APERTURA = 2;

148

Page 149: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

const int FALTA_CIERRE = 3;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_expr(string& exp){

cout << "Introduzca la expresión aritmética: ";cin >> ws;getline(cin , exp);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool es_apertura(char c){

return (c == '(' || c == '[' || c == '{');}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool es_cierre(char c){

return (c == ')' || c == ']' || c == '}');}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool corresponde(char a, char c){

bool ok = false;switch (a) {case '(': ok = (c == ')'); break;case '[': ok = (c == ']'); break;case '{': ok = (c == '}'); break;}return ok;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int esta_balanceado(const string& exp){

PilaChar p;int ok = CORRECTO;for (int i = 0; (ok == CORRECTO) && (i < int(exp.size ())); ++i) {

if (es_apertura(exp[i])) {p.push(exp[i]);

} else if (es_cierre(exp[i])) {if (p.empty ()) {

ok = FALTA_APERTURA;} else if (corresponde(p.top(), exp[i])) {

p.pop ();} else {

ok = NO_CORRESPONDE;}

}}if (ok == CORRECTO && ! p.empty() ) {

ok = FALTA_CIERRE;}return ok;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

string exp;leer_expr(exp);int ok = esta_balanceado(exp);switch (ok) {case CORRECTO:

cout << "Está balanceado" << endl;break;

case NO_CORRESPONDE:cout << "Símbolos no corresponden" << endl;break;

case FALTA_APERTURA:cout << "Falta símbolo de apertura" << endl;break;

case FALTA_CIERRE:cout << "Falta símbolo de cierre" << endl;break;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−� �

149

Page 150: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Prácticas de Laboratorio

Práctica 1: Almacenamiento Persistente de Datos1. Diseñe un programa que gestione una agenda que almacene información sobre personas (nombre y edad),

permita añadir, modificar y eliminar personas desde el teclado, así como mostrar el contenido de la agenda.Adicionalmente, el programa permitirá cargar el contenido de la agenda desde un fichero, así como guardarel contenido de la agenda a un fichero.

Se diseñarán versiones para trabajar con tres formatos de ficheros diferentes (donde los símbolos y ←↩

representan el espacio en blanco y el fin de línea respectivamente):

Opción (A) Opción (B) Opción (C)

nombre_apellidos edad ←↩

nombre_apellidos edad ←↩

· · ·

nombre apellidos ←↩

edad ←↩

nombre apellidos ←↩

edad ←↩

· · ·

nombre apellidos edad ←↩

nombre apellidos edad ←↩

· · ·

Nótese que en la primera opción (A), el nombre de la persona no contiene espacios en blanco, mientrasque en las siguientes opciones (B y C), si es posible que el nombre de la persona contenga espacios enblanco.

El programa mostrará un menú iterativo para poder seleccionar las acciones deseadas por el usuario delprograma, tal como:

Solución (A)� �#include <iostream>#include <fstream>#include <string>#include <array>#include <cctype>using namespace std;using namespace std;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Persona {

string nombre;unsigned edad;

};const unsigned MAX = 100;typedef array<Persona , MAX> APers;struct Agenda {

unsigned nelms;APers elm;

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// I n i c i a l i z a l a agenda a vac iavoid inic_agenda(Agenda& ag){

ag.nelms = 0;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// anyade una persona a l f i n a l de l a agendavoid anyadir_persona(Agenda& ag, const Persona& p, bool& ok){

if (ag.nelms < ag.elm.size ()) {ag.elm[ag.nelms] = p;++ag.nelms;ok = true;

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(Persona& p){

cout << "Introduza nombre (sin espacios ): ";cin >> p.nombre;cout << "Introduza edad: ";

150

Page 151: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cin >> p.edad;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e una persona y l a anyade a l a agenda ( supone l e c t u r a correc ta )void nueva_persona(Agenda& ag){

bool ok;Persona p;leer_persona(p);anyadir_persona(ag, p, ok);if (!ok) {

cout << "Error al introducir la nueva persona" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir_persona(const Persona& p){

cout << "Nombre: " << p.nombre << endl;cout << "Edad: " << p.edad << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// e s c r i b e l a agenda en pan t a l l avoid escribir_agenda(const Agenda& ag){

for (unsigned i = 0; i < ag.nelms; ++i) {cout << "----------------------------------------" << endl;escribir_persona(ag.elm[i]);

}cout << "----------------------------------------" << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// FORMATO DEL FICHERO DE ENTRADA://// <nombre> <edad> <RC>// <nombre> <edad> <RC>// . . .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(ifstream& fich , Persona& p){

fich >> p.nombre >> p.edad;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_agenda(const string& nombre_fich , Agenda& ag, bool& ok){

ifstream fich; // f l u j o de entrada de f i c h e r oPersona p;

fich.open(nombre_fich.c_str ()); // v incu la l a v b l e de f l u j o con e l f i c h e r oif (fich.fail ()) {

ok = false; // error de apertura de l f i c h e r o} else {

ok = true;inic_agenda(ag); // i n i c i a l i z a l a agendaleer_persona(fich , p); // l e e una personawhile (!fich.fail() && ok) { // mientras l e c t u r a correc ta

anyadir_persona(ag, p, ok); // anyade persona a l a agendaleer_persona(fich , p); // l e e otra persona

}ok = ok && fich.eof(); // correc to s i a lcanzado Fin−De−Ficherofich.close (); // c i e r ra l a v incu lac i on

}}void cargar_agenda(Agenda& ag){

bool ok;string nombre_fich;cout << "Introduce el nombre del fichero: ";cin >> nombre_fich;leer_agenda(nombre_fich , ag , ok);if (!ok) {

cout << "Error al cargar el fichero" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

151

Page 152: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// FORMATO DEL FICHERO DE SALIDA://// <nombre> <edad> <RC>// <nombre> <edad> <RC>// . . .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir_persona(ofstream& fich , const Persona& p){

fich << p.nombre << " " << p.edad << endl;}void escribir_agenda(const string& nombre_fich , const Agenda& ag , bool& ok){

ofstream fich; // f l u j o de s a l i d a de f i c h e r o

fich.open(nombre_fich.c_str ()); // v incu la l a v b l e de f l u j o con e l f i c h e r oif (fich.fail ()) {

ok = false; // error de apertura de l f i c h e r o} else {

unsigned i = 0; // Para cada elementowhile ((i < ag.nelms) && (!fich.fail ())) { // mientras f i c h en buen es tado

escribir_persona(fich , ag.elm[i]); // e s c r i b i r persona en f i c h e r o++i;

}ok = ! fich.fail (); // correc to s i f l u j o en buen es tadofich.close (); // c i e r ra l a v incu lac i on

}}void guardar_agenda(const Agenda& ag){

bool ok;string nombre_fich;cout << "Introduce el nombre del fichero: ";cin >> nombre_fich;escribir_agenda(nombre_fich , ag, ok);if (!ok) {

cout << "Error al guardar el fichero" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "C. Cargar Agenda" << endl;cout << "M. Mostrar Agenda" << endl;cout << "N. Nueva Persona" << endl;cout << "G. Guardar Agenda" << endl;cout << "X. Fin" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'C')||(op == 'M')||(op == 'N')||(op == 'G')||(op == 'X')));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Agenda ag;char op;inic_agenda(ag);do {

op = menu ();switch (op) {case 'C':

cargar_agenda(ag);break;

case 'M':escribir_agenda(ag);break;

case 'N':nueva_persona(ag);break;

152

Page 153: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

case 'G':guardar_agenda(ag);break;

}} while (op != 'X');

}� �Solución (B)� �

#include <iostream>#include <fstream>#include <string>#include <array>#include <cctype>using namespace std;using namespace std;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Persona {

string nombre;unsigned edad;

};const unsigned MAX = 100;typedef array<Persona , MAX> APers;struct Agenda {

unsigned nelms;APers elm;

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// I n i c i a l i z a l a agenda a vac iavoid inic_agenda(Agenda& ag){

ag.nelms = 0;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// anyade una persona a l f i n a l de l a agendavoid anyadir_persona(Agenda& ag, const Persona& p, bool& ok){

if (ag.nelms < ag.elm.size ()) {ag.elm[ag.nelms] = p;++ag.nelms;ok = true;

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(Persona& p){

cout << "Introduza nombre (puede tener espacios ): ";cin >> ws; // s a l t a e spac io s y s a l t o s de l i n e agetline(cin , p.nombre ); // l e e una l i n e a completacout << "Introduza edad: ";cin >> p.edad; // l e e l a edad

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e una persona y l a anyade a l a agenda ( supone l e c t u r a correc ta )void nueva_persona(Agenda& ag){

bool ok;Persona p;leer_persona(p);anyadir_persona(ag, p, ok);if (!ok) {

cout << "Error al introducir la nueva persona" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir_persona(const Persona& p){

cout << "Nombre: " << p.nombre << endl;cout << "Edad: " << p.edad << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

153

Page 154: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// e s c r i b e l a agenda en pan t a l l avoid escribir_agenda(const Agenda& ag){

for (unsigned i = 0; i < ag.nelms; ++i) {cout << "----------------------------------------" << endl;escribir_persona(ag.elm[i]);

}cout << "----------------------------------------" << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// FORMATO DEL FICHERO DE ENTRADA://// <nombre> <RC> <edad> <RC>// <nombre> <RC> <edad> <RC>// . . .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(ifstream& fich , Persona& p){

fich >> ws; // s a l t a e spac io s y s a l t o s de l i n e agetline(fich , p.nombre );// l e e una l i n e a completafich >> p.edad; // l e e l a edad

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Otra p o s i b l e implementacion a l t e r n a t i v a// void leer_persona ( i f s t r eam& f i ch , Persona& p)// {// g e t l i n e ( f i ch , p . nombre ) ; // l e e una l i n e a completa// f i c h >> p . edad ; // l e e l a edad// f i c h . ignore (1000 , '\n ' ) ; // e l imina hasta e l s a l t o de l i n e a// }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_agenda(const string& nombre_fich , Agenda& ag, bool& ok){

ifstream fich; // f l u j o de entrada de f i c h e r oPersona p;

fich.open(nombre_fich.c_str ()); // v incu la l a v b l e de f l u j o con e l f i c h e r oif (fich.fail ()) {

ok = false; // error de apertura de l f i c h e r o} else {

ok = true;inic_agenda(ag); // i n i c i a l i z a l a agendaleer_persona(fich , p); // l e e una personawhile (!fich.fail() && ok) { // mientras l e c t u r a correc ta

anyadir_persona(ag, p, ok); // anyade persona a l a agendaleer_persona(fich , p); // l e e otra persona

}ok = ok && fich.eof(); // correc to s i a lcanzado Fin−De−Ficherofich.close (); // c i e r ra l a v incu lac i on

}}void cargar_agenda(Agenda& ag){

bool ok;string nombre_fich;cout << "Introduce el nombre del fichero: ";cin >> nombre_fich;leer_agenda(nombre_fich , ag , ok);if (!ok) {

cout << "Error al cargar el fichero" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// FORMATO DEL FICHERO DE SALIDA://// <nombre> <RC> <edad> <RC>// <nombre> <RC> <edad> <RC>// . . .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir_persona(ofstream& fich , const Persona& p){

fich << p.nombre << endl << p.edad << endl;}void escribir_agenda(const string& nombre_fich , const Agenda& ag , bool& ok)

154

Page 155: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

{ofstream fich; // f l u j o de s a l i d a de f i c h e r o

fich.open(nombre_fich.c_str ()); // v incu la l a v b l e de f l u j o con e l f i c h e r oif (fich.fail ()) {

ok = false; // error de apertura de l f i c h e r o} else {

unsigned i = 0; // Para cada elementowhile ((i < ag.nelms) && (!fich.fail ())) { // mientras f i c h en buen es tado

escribir_persona(fich , ag.elm[i]); // e s c r i b i r persona en f i c h e r o++i;

}ok = ! fich.fail (); // correc to s i f l u j o en buen es tadofich.close (); // c i e r ra l a v incu lac i on

}}void guardar_agenda(const Agenda& ag){

bool ok;string nombre_fich;cout << "Introduce el nombre del fichero: ";cin >> nombre_fich;escribir_agenda(nombre_fich , ag, ok);if (!ok) {

cout << "Error al guardar el fichero" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "C. Cargar Agenda" << endl;cout << "M. Mostrar Agenda" << endl;cout << "N. Nueva Persona" << endl;cout << "G. Guardar Agenda" << endl;cout << "X. Fin" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'C')||(op == 'M')||(op == 'N')||(op == 'G')||(op == 'X')));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Agenda ag;char op;inic_agenda(ag);do {

op = menu ();switch (op) {case 'C':

cargar_agenda(ag);break;

case 'M':escribir_agenda(ag);break;

case 'N':nueva_persona(ag);break;

case 'G':guardar_agenda(ag);break;

}} while (op != 'X');

}� �Solución (C)� �

#include <iostream>

155

Page 156: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#include <fstream>#include <string>#include <array>#include <cctype>using namespace std;using namespace std;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Persona {

string nombre;unsigned edad;

};const unsigned MAX = 100;typedef array<Persona , MAX> APers;struct Agenda {

unsigned nelms;APers elm;

};//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// I n i c i a l i z a l a agenda a vac iavoid inic_agenda(Agenda& ag){

ag.nelms = 0;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// anyade una persona a l f i n a l de l a agendavoid anyadir_persona(Agenda& ag, const Persona& p, bool& ok){

if (ag.nelms < ag.elm.size ()) {ag.elm[ag.nelms] = p;++ag.nelms;ok = true;

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(Persona& p){

cout << "Introduza nombre (puede tener espacios ): ";cin >> ws; // s a l t a e spac io s y s a l t o s de l i n e agetline(cin , p.nombre ); // l e e una l i n e a completacout << "Introduza edad: ";cin >> p.edad; // l e e l a edad

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// l e e una persona y l a anyade a l a agenda ( s i l e c t u r a correc ta )void nueva_persona(Agenda& ag){

bool ok;Persona p;leer_persona(p);anyadir_persona(ag, p, ok);if (!ok) {

cout << "Error al introducir la nueva persona" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir_persona(const Persona& p){

cout << "Nombre: " << p.nombre << endl;cout << "Edad: " << p.edad << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// e s c r i b e l a agenda en pan t a l l avoid escribir_agenda(const Agenda& ag){

for (unsigned i = 0; i < ag.nelms; ++i) {cout << "----------------------------------------" << endl;escribir_persona(ag.elm[i]);

}cout << "----------------------------------------" << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// FORMATO DEL FICHERO DE ENTRADA:

156

Page 157: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//// <nombre> <edad> <RC>// <nombre> <edad> <RC>// . . .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// busca e l i nd i c e de l primer d i g i t o en una l i n e a ( s t r i n g )unsigned buscar_digitos(const string& linea){

unsigned i = 0;while ((i < linea.size ()) && ! isdigit(linea[i])) {

++i;}return i;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// ex t rae un numero de una cadena a pa r t i r de l a pos i c ion iunsigned extraer_num(const string& linea , unsigned& i){

unsigned num = 0;while ((i < linea.size ()) && isdigit(linea[i])) {

num = num * 10 + unsigned(linea[i] - '0');++i;

}return num;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// e l imina espac io s i n i c i a l e s y f i n a l e s en una cadenavoid eliminar_espacios(string& str){

if (str.size() > 0) {unsigned i = 0;while ((i < str.size ())&&(str[i] == ' ')) {

++i;}if (i >= str.size ()) {

str = "";} else {

unsigned j = unsigned(str.size ()) - 1;while (str[j] == ' ') {

--j;}str = str.substr(i, j-i+1);

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// dada una l i n e a l e i d a segun e l formato , ex t rae e l nombre y l a edadvoid extraer(const string& linea , string& nombre , unsigned& edad , bool& ok){

unsigned i = buscar_digitos(linea);if (i >= linea.size ()) {

ok = false;} else {

nombre = linea.substr(0, i);eliminar_espacios(nombre );edad = extraer_num(linea , i);ok = (nombre.size() > 0) && (i >= linea.size ());

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(ifstream& fich , Persona& p, bool& ok){

string linea;fich >> ws; // s a l t a e spac io s y s a l t o s de l i n e agetline(fich , linea ); // l e e una l i n e a completaextraer(linea , p.nombre , p.edad , ok); // ex t rae nombre y edad

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_agenda(const string& nombre_fich , Agenda& ag, bool& ok){

ifstream fich; // f l u j o de entrada de f i c h e r oPersona p;

fich.open(nombre_fich.c_str ()); // v incu la l a v b l e de f l u j o con e l f i c h e r o

157

Page 158: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

if (fich.fail ()) {ok = false; // error de apertura de l f i c h e r o

} else {bool ok1 = true;bool ok2 = true;inic_agenda(ag); // i n i c i a l i z a l a agendaleer_persona(fich , p, ok1); // l e e una personawhile (!fich.fail() && ok1 && ok2) {// mientras l e c t u r a correc ta

anyadir_persona(ag, p, ok2); // anyade persona a l a agendaleer_persona(fich , p, ok1); // l e e otra persona

}ok = ok1 && ok2 && fich.eof(); // correc to s i a lcanzado Fin−De−Ficherofich.close (); // c i e r ra l a v incu lac i on

}}void cargar_agenda(Agenda& ag){

bool ok;string nombre_fich;cout << "Introduce el nombre del fichero: ";cin >> nombre_fich;leer_agenda(nombre_fich , ag , ok);if (!ok) {

cout << "Error al cargar el fichero" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// FORMATO DEL FICHERO DE SALIDA://// <nombre> <edad> <RC>// <nombre> <edad> <RC>// . . .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir_persona(ofstream& fich , const Persona& p){

fich << p.nombre << " " << p.edad << endl;}void escribir_agenda(const string& nombre_fich , const Agenda& ag , bool& ok){

ofstream fich; // f l u j o de s a l i d a de f i c h e r o

fich.open(nombre_fich.c_str ()); // v incu la l a v b l e de f l u j o con e l f i c h e r oif (fich.fail ()) {

ok = false; // error de apertura de l f i c h e r o} else {

unsigned i = 0; // Para cada elementowhile ((i < ag.nelms) && (!fich.fail ())) { // mientras f i c h en buen es tado

escribir_persona(fich , ag.elm[i]); // e s c r i b i r persona en f i c h e r o++i;

}ok = ! fich.fail (); // correc to s i f l u j o en buen es tadofich.close (); // c i e r ra l a v incu lac i on

}}void guardar_agenda(const Agenda& ag){

bool ok;string nombre_fich;cout << "Introduce el nombre del fichero: ";cin >> nombre_fich;escribir_agenda(nombre_fich , ag, ok);if (!ok) {

cout << "Error al guardar el fichero" << endl;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "C. Cargar Agenda" << endl;cout << "M. Mostrar Agenda" << endl;cout << "N. Nueva Persona" << endl;cout << "G. Guardar Agenda" << endl;

158

Page 159: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "X. Fin" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'C')||(op == 'M')||(op == 'N')||(op == 'G')||(op == 'X')));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Agenda ag;char op;inic_agenda(ag);do {

op = menu ();switch (op) {case 'C':

cargar_agenda(ag);break;

case 'M':escribir_agenda(ag);break;

case 'N':nueva_persona(ag);break;

case 'G':guardar_agenda(ag);break;

}} while (op != 'X');

}� �

159

Page 160: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Práctica 2: Tipos Abstractos de Datos (I)1. Diseñe e implemente un TAD para números racionales. Se deberán seguir las siguientes consideraciones:

Los números racionales se representan mediante fracciones, donde tanto el numerador como denomi-nador son de tipo int).

Las fracciones se representarán en todo momento normalizadas (simplificadas):

• Es recomendable implementar un método privado de simplificación de la fracción mediante elcálculo del máximo común divisor (m.c.d.) del numerador y el denominador y su posterior divisiónpor dicho m.c.d.Para calcular el máximo común divisor de dos numeros enteros positivos n y m, el algoritmo deEuclides funciona como se indica a continuación:a) Si n < m, entonces se intercambian los valores de n y m (para asegurarnos que n siempre sea mayor

o igual que m).b) Si el valor de m es distinto de 0, entonces sea r el resto de la división entera entre n y m; después

modificamos los valores de n y m de la siguiente forma: n toma ahora el valor de m y m toma ahorael valor de r (el resto de la división entera entre n y m calculado anteriormente), y se repite esteproceso especificado hasta que el valor de m sea igual a 0.

c) Finalmente, cuando el proceso iterativo acaba, el valor de n es el máximo común divisor de ambosnúmeros.

• Para simplificar la determinación del signo de la fracción puede asumirse que el denominador dela fracción es siempre positivo (por lo que una fracción de signo negativo tendrá un numeradorde signo negativo y un denominador de signo positivo).

El cero se guardará siempre en su forma canónica 0/1.

Por defecto, un número racional debe asignarse a cero cuando se crea.

Debe evitarse en todo momento la asignación de cero a un denominador.

Un determinado método permitirá comprobar si un determinado número racional se encuentra enestado de error. Un denominador igual a cero (0) se considera un estado de error.

Debe poder ser posible crear números racionales especificando su numerador y denominador, comosólamente especificando su numerador (en este último caso, se considerará un denominador igual a1).

Solución: racionales.hpp� �#ifndef racionales_hpp_#define racionales_hpp_namespace umalcc {

class Racional {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//~Racional ( ) {}//Racional ( const Racional& o ) ;//Racional& operator=(const Racional& o ) ;//−−−−−−−−−−−−−−−−−−−−−−−−−Racional () ;// Construye e l número rac iona l 0/1//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Racional(int n) ;// Construye e l número rac iona l n/1//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Racional(int n, int d) ;// Construye e l número rac iona l n/d//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool fail() const;// Devuelve t rue s i e l número rac iona l a c tua l e s t a en es tado erroneo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void sumar(const Racional& r1 , const Racional& r2);// Asigna a l número rac iona l a c tua l e l r e su l t ado de// sumar l o s números rac i ona l e s ( r1 ) y ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

160

Page 161: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void restar(const Racional& r1 , const Racional& r2);// Asigna a l número rac iona l a c tua l e l r e su l t ado de// r e s t a r l o s números rac i ona l e s ( r1 ) y ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void multiplicar(const Racional& r1, const Racional& r2);// Asigna a l número rac iona l a c tua l e l r e su l t ado de// mu l t i p l i c a r l o s números rac i ona l e s ( r1 ) y ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void dividir(const Racional& r1, const Racional& r2);// Asigna a l número rac iona l a c tua l e l r e su l t ado de// d i v i d i r l o s números rac i ona l e s ( r1 ) y ( r2 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir () const;// Muestra en pan t a l l a e l va l o r de l número rac iona l a c tua l//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer ();// Lee de t e c l ado e l va l o r de l número rac iona l a c tua l//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool igual(const Racional& r1) const;// Devuelve t rue s i e l número rac iona l a c tua l es i g u a l a ( r1 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool menor(const Racional& r1) const;// Devuelve t rue s i e l número rac iona l a c tua l es menor que ( r1 )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

private://−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void normalizar ();//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int num; // numeradorint denom; // denominador//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

Solución: racionales.cpp� �#include "racionales.hpp"#include <iostream>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Subprogramas Aux i l i a r e s −−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// va l o r ab so l u t o de un numero enteroinline int abs(int x){

if (x < 0) {x = -x;

}return x;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// maximo comun d i v i s o r . a l gor i tmo de eu c l i d e sint mcd(int n, int m){

n = abs(n);m = abs(m);if (n < m) {

int x = n;n = m;m = x;

}while (m != 0) {

161

Page 162: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

int r = n % m;n = m;m = r;

}return n;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// minimo comun mu l t i p l o// i n l i n e i n t mcm( in t a , i n t b )// {// a = abs (a ) ;// b = abs ( b ) ;// re turn (a / mcd(a , b )) ∗ b ;// }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

Racional :: Racional () : num(0), denom (1) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Racional :: Racional(int n) : num(n), denom (1) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Racional :: Racional(int n, int d) : num(n), denom(d){

normalizar ();}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Racional ::fail() const{

return (denom == 0);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// normal izar un numero rac iona lvoid Racional :: normalizar (){

if (denom == 0) {// Error denominador ceronum = 0;denom = 0;

} else if (num == 0) {// Forma canonicanum = 0;denom = 1;

} else {// d i v i d i r numerador y denominador por MCDint max_com_div = mcd(num , denom );num /= max_com_div;denom /= max_com_div;// s i denominador negat ivo , entonces cambiar s ignoif (denom < 0) {

num = -num;denom = -denom;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Racional ::sumar(const Racional& r1, const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗d2 n2∗d1 (n1∗d2)+(n2∗d1 )// −−−− + −−−− == −−−−−−− + −−−−−−− == −−−−−−−−−−−−−−−−−// d1 d2 d1∗d2 d2∗d1 d1∗d2//−−−−−−−−−−−−−−−−−−−−−−−−−num = ((r1.num * r2.denom) + (r2.num * r1.denom ));denom = r1.denom * r2.denom;normalizar ();

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Racional :: restar(const Racional& r1, const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−

162

Page 163: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// n1 n2 n1∗d2 n2∗d1 (n1∗d2)−(n2∗d1 )// −−−− − −−−− == −−−−−−− − −−−−−−− == −−−−−−−−−−−−−−−−−// d1 d2 d1∗d2 d2∗d1 d1∗d2//−−−−−−−−−−−−−−−−−−−−−−−−−num = ((r1.num * r2.denom) - (r2.num * r1.denom ));denom = r1.denom * r2.denom;normalizar ();

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Racional :: multiplicar(const Racional& r1 , const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗n2// −−−− ∗ −−−− == −−−−−−−// d1 d2 d1∗d2//−−−−−−−−−−−−−−−−−−−−−−−−−num = r1.num * r2.num;denom = r1.denom * r2.denom;normalizar ();

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Racional :: dividir(const Racional& r1 , const Racional& r2){

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗d2// −−−− / −−−− == −−−−−−−// d1 d2 d1∗n2//−−−−−−−−−−−−−−−−−−−−−−−−−if (r1.fail() || r2.fail ()) {

num = 0;denom = 0;

} else {int p_num = r1.num * r2.denom;int p_denom = r1.denom * r2.num;num = p_num;denom = p_denom;

}normalizar ();

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Racional :: escribir () const{

if (fail ()) {cout << "Error";

} else {cout << num << " / " << denom;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Racional ::leer(){

cin >> num >> denom;normalizar ();

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Racional ::igual(const Racional& r1) const{

// ambos numeros es tan normalizadosreturn (num == r1.num && denom == r1.denom);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Racional ::menor(const Racional& r1) const{

//−−−−−−−−−−−−−−−−−−−−−−−−−// n1 n2 n1∗d2 n2∗d1 (n1∗d2 ) < (n2∗d1 )// −−−− < −−−− ==> −−−−−−− < −−−−−−− ==> −−−−−−−−−−−−−−−−−// d1 d2 d1∗d2 d2∗d1 d1∗d2//−−−−−−−−−−−−−−−−−−−−−−−−−return (num * r1.denom) < (r1.num * denom );

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �2. Diseñe un programa que permita utilizar el TAD especificado en el ejercicio anterior.

163

Page 164: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: main.cpp� �#include <iostream>#include <string>#include <cassert>#include "racionales.hpp"using namespace std;using namespace umalcc;

void escribir(const string& msj , const Racional& r){

cout << msj;r.escribir ();cout << endl;

}int main(){

//−−−−−−−−−−−−−−−−−−−−−−−−−cout << "Introduzca numerador y denominador: ";Racional r1;r1.leer ();escribir("R1: ", r1);//−−−−−−−−−−−−−−−−−−−−−−−−−cout << "Introduzca numerador y denominador: ";Racional r2;r2.leer ();escribir("R2: ", r2);//−−−−−−−−−−−−−−−−−−−−−−−−−Racional r3;r3.sumar(r1, r2);escribir("R3 (r1 + r2): ", r3);//−−−−−−−−−−−−−−−−−−−−−−−−−Racional r4;r4.restar(r3, r2);escribir("R4 (r3 - r2): ", r4);if ( ! r1.igual(r4)) {

cout << "Error en suma/resta"<<endl;}//−−−−−−−−−−−−−−−−−−−−−−−−−Racional r5;r5.multiplicar(r1 , r2);escribir("R5 (r1 * r2): ", r5);//−−−−−−−−−−−−−−−−−−−−−−−−−Racional r6;r6.dividir(r5 , r2);escribir("R6 (r5 / r2): ", r6);if ( ! r1.igual(r6)) {

cout << "Error en multiplicacion/division"<<endl;}//−−−−−−−−−−−−−−−−−−−−−−−−−

}� �3. Añada de forma incremental los siguientes métodos públicos al TAD Racional realizado anteriormente:

4. Modifique el programa que utiliza el TAD Racional especificado anteriormente para que utilice los nuevosmétodos añadidos anteriormente.

164

Page 165: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Práctica 3: Tipos Abstractos de Datos (II)1. Diseñe e implemente un TAD Punto del plano cartesiano en el espacio de nombres umalcc, considerando

que un Punto describe una determinada posición en el plano cartesiano, especificada por el valor de lascomponentes X e Y de las coordenadas cartesianas, y proporciona los siguientes métodos públicos. En laimplementación del TAD Punto, se recomienda la implementación en el espacio de nombres anónimo de lafunción double sq(double x) (devuelve x2) y de la función double hipotenusa(double a, double b)(devuelve

√a2 + b2).

Solución: punto.hpp� �#ifndef punto_hpp_#define punto_hpp_namespace umalcc {

class Punto {public:

˜ Punto ();// des t ruye e l o b j e t o ac tua l y sus recursos asoc iados .

Punto ();// crea un punto en e l or igen de coordenadas .

Punto(double cx, double cy);// crea un punto en l a s coordenadas r e c i b i d a s como parametros .

Punto(const Punto& o);// crea un punto copiando sus va l o r e s de l o b j e t o r e c i b i d o como// parametro .

Punto& operator=(const Punto& o);// asigna a un ob j e t o punto e l va l o r de otro ob j e t o punto// r e c i b i d o como parametro .

void desplazar(double dx, double dy);// Desplaza e l o b j e t o ac tua l desde l a pos i c ion ac tua l una// determinada d i s t anc i a e s p e c i f i c a da como parametros en ambos e j e s .

double distancia(const Punto& o) const;// devue l ve l a d i s t anc i a ab so l u t a entre e l o b j e t o ac tua l y e l// ob j e t o punto r e c i b i d o como parametro .

double coord_x () const;// devue l ve e l va l o r de l a componente X de l o b j e t o ac tua l .

double coord_y () const;// devue l ve e l va l o r de l a componente Y de l o b j e t o ac tua l .

private:double x;double y;

} ;}#endif� �

Solución: punto.cpp� �#include "punto.hpp"#include <cmath>using namespace std;namespace {

inline double sq(double x) {return x * x;

}inline double hipotenusa(double c1 , double c2) {

return sqrt( sq(c1) + sq(c2) );}

}namespace umalcc {

Punto :: ˜ Punto() {}Punto :: Punto() : x(0), y(0) {}Punto :: Punto(double cx, double cy) : x(cx), y(cy) {}Punto :: Punto(const Punto& o) : x(o.x), y(o.y) {}Punto& Punto:: operator=(const Punto& o) {

if (this != &o) {x = o.x;y = o.y;

}return *this;

165

Page 166: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}void Punto:: desplazar(double dx, double dy) {

x += dx;y += dy;

}double Punto :: distancia(const Punto& o) const {

return hipotenusa( o.y - y , o.x - x );}double Punto :: coord_x () const { return x; }double Punto :: coord_y () const { return y; }

}� �2. Diseñe un programa que permita comprobar el funcionamiento del TAD especificado en el ejercicio anterior.

Solución: main1.cpp� �#include <iostream>#include "punto.hpp"using namespace std;using namespace umalcc;void mostrar(const Punto& p) {

cout << "(" << p.coord_x () << ", " << p.coord_y () << ")";}void leer(Punto& p) {

double x, y;cout << "Introduce las coordenadas X e Y: ";cin >> x >> y;p = Punto(x, y);

}int main() {

Punto malaga(-4.4750 , 36.7166);Punto pepe(malaga );pepe.desplazar(-0.0344 , -0.1171);cout << "Pepe: posicion: ";mostrar(pepe);cout << endl;cout << "Pepe: distancia: " << pepe.distancia(malaga) << endl;leer(pepe);mostrar(pepe);cout << endl;cout << "Pepe: distancia: " << pepe.distancia(malaga) << endl;

}� �3. Diseñe e implemente un TAD Segmento del plano cartesiano en el espacio de nombres umadpt, considerando

que un Segmento es un fragmento de una recta que se encuentra comprendido entre dos Puntos (origen ydestino) en el plano cartesiano, y proporciona los siguientes métodos públicos:

Solución: segmento.hpp� �#ifndef segmento_hpp_#define segmento_hpp_#include "punto.hpp"namespace umadpt {

class Segmento {public:

˜ Segmento ();// des t ruye e l o b j e t o ac tua l y sus recursos asoc iados .

Segmento ();// crea un ob j e t o Segmento nulo , donde ambos puntos que// l o de l imi tan se encuentran en e l or igen de coordenadas .

Segmento(double x1, double y1, double x2, double y2);// crea un ob j e t o Segmento según l o s va l o r e s de l a s 4// coordenadas de dos puntos e s p e c i f i c a d o s como parámetros .

Segmento(const umalcc ::Punto& o, const umalcc ::Punto& d);// crea un ob j e t o Segmento según l o s va l o r e s de dos puntos// e s p e c i f i c a d o s como parámetros .

Segmento(const Segmento& o);// crea un Segmento copiando sus va l o r e s de l o b j e t o r e c i b i d o// como parametro .

166

Page 167: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Segmento& operator=(const Segmento& o);// asigna a un ob j e t o Segmento e l va l o r de otro ob j e t o Segmento// r e c i b i d o como parametro .

void desplazar(double dx, double dy);// Desplaza e l o b j e t o ac tua l desde l a pos i c ion ac tua l una// determinada d i s t anc i a e s p e c i f i c a da como parametros en ambos e j e s .

double longitud () const;// devue l ve l a l ong i t ud de l o b j e t o Segmento .

umalcc ::Punto origen () const;// devue l ve e l va l o r de l Punto or igen de l Segmento ac tua l .

umalcc ::Punto destino () const;// devue l ve e l va l o r de l Punto de s t ino de l Segmento ac tua l .

private:umalcc ::Punto org;umalcc ::Punto dst;

} ;}#endif� �

Solución: segmento.cpp� �#include "segmento.hpp"using namespace std;using namespace umalcc;namespace umadpt {

Segmento :: ˜ Segmento () {}Segmento :: Segmento () : org(), dst() {}Segmento :: Segmento(double x1 , double y1 , double x2 , double y2)

: org(x1, y1), dst(x2, y2) {}Segmento :: Segmento(const Punto& o, const Punto& d)

: org(o), dst(d) {}Segmento :: Segmento(const Segmento& o)

: org(o.org), dst(o.dst) {}Segmento& Segmento :: operator=(const Segmento& o) {

if (this != &o) {org = o.org;dst = o.dst;

}return *this;

}void Segmento :: desplazar(double dx , double dy) {

org.desplazar(dx, dy);dst.desplazar(dx, dy);

}double Segmento :: longitud () const {

return org.distancia(dst);}Punto Segmento :: origen () const { return org; }Punto Segmento :: destino () const { return dst; }

}� �4. Diseñe un programa que permita comprobar el funcionamiento del TAD especificado en el ejercicio anterior.

Solución: main2.cpp� �#include <iostream>#include "segmento.hpp"using namespace std;using namespace umalcc;using namespace umadpt;void mostrar(const Punto& p) {

cout << "(" << p.coord_x () << ", " << p.coord_y () << ")";}int main() {

Punto malaga(-4.4750 , 36.7166);Punto benalmadena(-4.5094 , 36.5995);Segmento camino(malaga , benalmadena );camino.desplazar(-0.0344 , -0.1171);cout << "Origen: ";mostrar(camino.origen ());cout << endl;

167

Page 168: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "Destino: ";mostrar(camino.destino ());cout << endl;cout << "Longitud: " << camino.longitud () << endl;

}� �5. Diseñe e implemente un TAD Polígono del plano cartesiano en el espacio de nombres umalcc, considerando

que un Polígono es una figura plana compuesta por una secuencia finita de lados consecutivos determinadospor vértices (Puntos) en el plano cartesiano, y proporciona los siguientes métodos públicos:

Solución: poligono.hpp� �#ifndef poligono_hpp_#define poligono_hpp_#include "punto.hpp"#include "segmento.hpp"#include <array>namespace umalcc {

class Poligono {public:

˜ Poligono ();// des t ruye e l o b j e t o ac tua l y sus recursos asoc iados .

Poligono ();// crea un ob j e t o Pol igono vacío , s in v é r t i c e s ni l ados .

Poligono(const Poligono& o);// crea un Poligono copiando sus va l o r e s de l o b j e t o r e c i b i d o// como parametro .

Poligono& operator=(const Poligono& o);// asigna a un ob j e t o Pol igono e l va l o r de otro ob j e t o Pol igono// r e c i b i d o como parametro .

void nuevo_vertice(const Punto& v);// agrega un nuevo v é r t i c e a l o b j e t o Pol ígono ac tua l .

void mover_vertice(int pos , const Punto& v);// cambia l a pos i c ion de l v e r t i c e e s p e c i f i c a do en e l primer// parámetro de l o b j e t o actua l , por e l nuevo va l o r// e s p e c i f i c a do e l e l segundo parametro .

void desplazar(double dx, double dy);// desp la za e l o b j e t o ac tua l desde l a pos i c ión ac tua l una// determinada d i s t anc i a e s p e c i f i c a da como parámetros en ambos// e j e s .

double perimetro () const;// devue l ve e l perímetro de l o b j e t o ac tua l .

Punto vertice(int pos) const;// devue l ve e l va l o r de l v e r t i c e e s p e c i f i c a do en e l primer// parámetro .

umadpt :: Segmento lado(int pos) const;// devue l ve e l va l o r de l lado e s p e c i f i c a do en e l primer// parámetro .

int n_vertices () const;// devue l ve e l numero de v e r t i c e s de l po l i gono ac tua l .

private:static const int MAX = 32;typedef std::array<Punto , MAX> Vertices;//−−−−−−−−−−−−−−−−int n_vert;Vertices vert;

} ;}#endif� �

Solución: poligono.cpp� �#include "poligono.hpp"using namespace std;using namespace umadpt;namespace umalcc {

Poligono :: ˜ Poligono () {}Poligono :: Poligono () : n_vert (0), vert() {}Poligono :: Poligono(const Poligono& o)

168

Page 169: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

: n_vert(o.n_vert), vert(o.vert) {}Poligono& Poligono :: operator=(const Poligono& o) {

if (this != &o) {n_vert = o.n_vert;vert = o.vert;

}return *this;

}void Poligono :: nuevo_vertice(const Punto& v) {

if (n_vert < int(vert.size ())) {vert[n_vert] = v;++n_vert;

}}void Poligono :: mover_vertice(int pos ,

const Punto& v) {if (0 <= pos && pos < n_vert) {

vert[pos] = v;}

}int Poligono :: n_vertices () const {

return n_vert;}void Poligono :: desplazar(double dx , double dy) {

for (int i = 0; i < n_vert; ++i) {vert[i].desplazar(dx, dy);

}}double Poligono :: perimetro () const {

double suma = 0;for (int i = 0; i < n_vert - 1; ++i) {

suma += vert[i].distancia(vert[i+1]);}return suma;

}Punto Poligono :: vertice(int pos) const {

Punto p;if (0 <= pos && pos < n_vert) {

p = vert[pos];}return p;

}Segmento Poligono ::lado(int pos) const {

Segmento s;if (0 <= pos && pos < n_vert - 1) {

s = Segmento(vert[pos], vert[pos+1]);}return s;

}}� �

6. Diseñe un programa que permita comprobar el funcionamiento del TAD especificado en el ejercicio anterior.

Solución: main3.cpp� �#include <iostream>#include "poligono.hpp"using namespace std;using namespace umalcc;void mostrar(const Punto& p) {

cout << "(" << p.coord_x () << ", " << p.coord_y () << ")";}int main() {

Punto malaga(-4.4750 , 36.7166);Punto benalmadena(-4.5094 , 36.5995);Punto mijas(-4.6497 , 36.5959);Punto cartama(-4.6350 , 36.7124);Poligono camino;camino.nuevo_vertice(malaga );camino.nuevo_vertice(benalmadena );camino.nuevo_vertice(mijas);camino.nuevo_vertice(cartama );camino.nuevo_vertice(malaga );

169

Page 170: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "Origen: ";mostrar(camino.vertice (0));cout << endl;cout << "Perimetro: " << camino.perimetro () << endl;

}� �

170

Page 171: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Práctica 4: Tipos Abstractos de Datos (III)1. Diseñe e implemente un TAD (Cuenta) bancaria que represente una cuenta bancaria de un cliente de un

banco. Así, almacena el nombre del cliente (cadena de caracteres), el número de cuenta (número entero)y el saldo de la cuenta (número real), de tal forma que gestione su manipulación segura, especialmenteconsiderando que no se puede quedar con saldo negativo.

El TAD Cuenta se definirá en el espacio de nombres umalcc_1, y deberá proporcionar métodos públicosque soporten adecuadamente las siguientes operaciones. Diseñe también un programa que permita suutilización.

Solución: cuenta.hpp� �#ifndef cuenta_hpp_#define cuenta_hpp_#include <string>namespace umalcc_1 {

class Cuenta {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//~Cuenta ( ) ;//Cuenta ( const Cuenta& o ) ;//Cuenta& operator=(const Cuenta& o ) ;//−−−−−−−−−−−−−−−−−−−−−−−−−Cuenta () ;

// crea una cuenta con va l o r e s por de f e c t o .Cuenta(const std:: string& n, unsigned c, double s) ;

// crea una cuenta con l o s va l o r e s r e c i b i d o s como parametros .bool error() const ;

// devue l ve f a l s e s i l a cuenta es correcta , y t rue s i l a cuenta// es erronea (nombre vac io o numero de cuenta nega t i vo o sa ldo// nega t i vo ) .

void mostrar () const ;// muestra en pan t a l l a toda l a informacion asociada a l a// cuenta bancaria . En caso de cuenta erronea , mostrara un// mensaje adecuado .

std:: string obtener_nombre () const ;// devue l ve e l va l o r de l nombre de l o b j e t o cuenta .

unsigned obtener_cuenta () const ;// devue l ve e l va l o r de l numero de cuenta de l o b j e t o cuenta .

double obtener_saldo () const ;// devue l ve e l va l o r de l sa ldo de l o b j e t o cuenta .

void ingresar_saldo(double inc , bool& ok);// ingre sar una determinada cant idad de dinero e s p e c i f i c a da// como parametro , para sumar a l sa ldo de l a cuenta .

void retirar_saldo(double inc , bool& ok);// r e t i r a r una determinada cant idad de dinero e s p e c i f i c a da// como parametro de l sa ldo de l a cuenta , considerando que e l// sa ldo nunca podra ser nega t i vo .

void ingresar_interes(double porcentaje , bool& ok);// incrementara e l sa ldo de l a cuenta en un determinado// porcen ta j e e s p e c i f i c a do como parametro .

void retirar_comision(double inc , bool& ok);// r e t i r a de l sa ldo una cant idad e s p e c i f i c a da como parametro ,// considerando que s i l a cant idad a r e t i r a r es mayor que// e l sa ldo d i spon i b l e , s o l o r e t i r a r a l a cant idad de sa ldo// d i s p on i b l e .

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−private:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−std:: string nombre;unsigned num_cuenta;double saldo;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

171

Page 172: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: cuenta.cpp� �#include "cuenta.hpp"#include <iostream>#include <string>#include <cassert>using namespace std;namespace umalcc_1 {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Cuenta :: Cuenta () : nombre(), num_cuenta (0), saldo (0.0) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Cuenta :: Cuenta(const string& n, unsigned c, double s)

: nombre(n), num_cuenta(c), saldo(s) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Cuenta :: error() const{

return (nombre == "")||(saldo < 0.0)/∗ | | ( num_cuenta < 0)∗/;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−string Cuenta :: obtener_nombre () const{

return nombre;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned Cuenta :: obtener_cuenta () const{

return num_cuenta;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Cuenta :: obtener_saldo () const{

return saldo;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Cuenta :: mostrar () const{

if (error ()) {cout << " Cuenta errónea" << endl;

} else {cout << " Nombre: " << nombre << endl;cout << " Cuenta: " << num_cuenta << endl;cout << " Saldo: " << saldo << endl;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Cuenta :: ingresar_saldo(double inc , bool& ok){

if (error() || (inc < 0.0) || (saldo + inc < 0.0)) {ok = false;

} else {saldo += inc;ok = true;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Cuenta :: retirar_saldo(double inc , bool& ok){

if (error() || (inc < 0.0) || (saldo - inc < 0.0)) {ok = false;

} else {saldo -= inc;ok = true;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Cuenta :: ingresar_interes(double porcentaje , bool& ok){

double cantidad = saldo * porcentaje / 100.0;ingresar_saldo(cantidad , ok);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Cuenta :: retirar_comision(double cantidad , bool& ok){

if (saldo >= cantidad) {retirar_saldo(cantidad , ok);

172

Page 173: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

} else {retirar_saldo(saldo , ok);

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �2. Diseñe un programa que permita comprobar el funcionamiento del TAD especificado en el ejercicio anterior.

3. Diseñe e implemente un TAD (Banco) que represente las cuentas bancarias de los clientes de un banco,utilizando para ello el TAD Cuenta bancaria diseñado en el apartado anterior.

Así, el TAD Banco se encargará de la gestión del global de cuentas a nivel del banco y considerandomúltiples clientes, utilizando para cada uno de ellos el TAD Cuenta, el cual se encargará de la manipulaciónde la cuenta de un usuario, controlando que operaciones son válidas y cuales no.

Así, para cada cliente, se almacena su nombre (cadena de caracteres), el número de cuenta (número entero)y el saldo de la cuenta (número real), teniendo en cuenta que nunca podrá existir un saldo negativo. Paraello, el TAD Banco contiene un array para almacenar las cuentas bancarias (TAD Cuenta) de cadacliente, así como tambien almacena el número de cuentas bancarias que tiene actualmente activas (todasalmacenadas consecutivamente desde el principio del array). Además, también contiene un número quesirve para asignar números de cuenta consecutivos a las cuentas bancarias que se vayan creando.

El tipo abstracto de datos deberá permitir tanto crear nuevas cuentas bancarias como eliminarlas. Asímismo, deberá permitir mostrar los datos de las cuentas bancarias almacenadas.

El TAD Banco se definirá en el espacio de nombres umalcc_2, y deberá proporcionar métodos públicosque soporten adecuadamente las siguientes operaciones:

Solución: banco.hpp� �#ifndef banco_hpp_#define banco_hpp_#include <string>#include <array>#include "cuenta.hpp"namespace umalcc_2 {

class Banco {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Pub l i cos −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//~Banco ( ) ;//Banco( const Banco& o ) ;//Banco& operator=(const Banco& o ) ;//−−−−−−−−−−−−−−−−−−−−−−−−−Banco ();

// crea un banco vacio , s in c l i e n t e s , i n i c i a l i z a n d o// adecuadamente e l contador para as ignar numeros de cuenta .

void crear_cuenta(const std:: string& nombre , unsigned& num , bool& ok);// crea una cuenta bancaria para una determinada persona ,// u t i l i z a n d o su nombre e s p e c i f i c a do como parametro . El numero// de cuenta se c a l c u l a a p a r t i r de un va l o r almacenado en l o s// a t r i b u t o s de l banco , que l l e v a una cuenta incrementa l de l o s// numeros de cuentas previamente as ignados . Devolvera en un// parametro de s a l i d a e s t e numero de cuenta asignado por e l// banco . Si l a operacion se r e a l i z o correc ta o incorrectamente ,// sera no t i f i c a do mediante un parametro de s a l i d a .

void eliminar_cuenta(unsigned num , bool& ok);// e l imina una cuenta bancaria a p a r t i r de un numero de cuenta// e s p e c i f i c a do como parametro . Si l a operacion se r e a l i z o// correc ta o incorrectamente , sera no t i f i c a do mediante un// parametro de s a l i d a .

void mostrar_cuentas () const ;// muestra toda l a informacion almacenada en l a e s t ruc tu ra// de datos .

void mostrar_cuenta(unsigned num , bool& ok) const;// muestra en pan t a l l a toda l a informacion asociada a l a// cuenta bancaria cuyo numero de cuenta se e s p e c i f i c a como// parametro . Si l a operacion se r e a l i z o correc ta o

173

Page 174: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// incorrectamente , sera no t i f i c a do mediante un parametro de// s a l i d a .

void mostrar_cuentas(const std:: string& nombre) const;// muestra en pan t a l l a toda l a informacion asociada a todas// l a s cuentas bancar ias de de una persona cuyo nombre se// e s p e c i f i c a como parametro .

void ingreso(unsigned num , double cantidad , bool& ok);// ingresa una determinada cant idad de dinero e s p e c i f i c a da// como parametro a un determinado numero de cuenta e s p e c i f i c a do// como parametro . Si l a operacion se r e a l i z o correc ta o// incorrectamente , sera no t i f i c a do mediante un parametro de// s a l i d a .

void retirar(unsigned num , double cantidad , bool& ok);// r e t i r a una determinada cant idad de dinero e s p e c i f i c a da como// parametro de un determinado numero de cuenta e s p e c i f i c a do como// parametro , considerando que e l sa ldo nunca podra ser nega t i vo .// Si l a operacion se r e a l i z o correc ta o incorrectamente , sera// no t i f i c a do mediante un parametro de s a l i d a .

void transferir(unsigned dest , unsigned origen , double cantidad ,bool& ok);

// t r a n s f i e r e una determinada cant idad de dinero e s p e c i f i c a da// como parametro desde un numero de cuenta or igen a otro numero// de cuenta des t ino , ambos e s p e c i f i c a d o s como parametros ,// considerando que e l sa ldo nunca podra ser nega t i vo . Si l a// operacion se r e a l i z o correc ta o incorrectamente , sera// no t i f i c a do mediante un parametro de s a l i d a .

void ingresar_intereses(double porcentaje );// ingresa l o s i n t e r e s e s en todas l a s cuentas de l banco , para// un determinado porcen ta je e s p e c i f i c a do como parametro .

void gastos_comision(double cantidad );// carga l o s gas to s de comision en todas l a s cuentas de l// banco , una cant idad que se e s p e c i f i c a como parametro . Si// l a cant idad a cargar excede de l sa ldo que una determinada// cuenta posee , entonces se l e r e t i r a r a toda l a cant idad de// sa ldo que posea .

void guardar_cuentas_fich(const std:: string& nombre_fich , bool& ok) const;// guarda toda l a informacion almacenada en l a e s t ruc tu ra de// datos en e l f i c h e r o cuyo nombre se e s p e c i f i c a como parametro ,// en un formato adecuado para pos ter iormente poder recuperar l a// informacion almacenada . Si l a operacion se r e a l i z o correc ta o// incorrectamente , sera no t i f i c a do mediante un parametro de// s a l i d a .

void cargar_cuentas_fich(const std:: string& nombre_fich , bool& ok) ;// carga toda l a informacion de l a e s t ruc tu ra de datos desde// e l f i c h e r o cuyo nombre se e s p e c i f i c a como parametro , s i gu i endo// e l formato u t i l i z a d o en l a operacion an t e r i o r . Si l a// operacion se r e a l i z o correc ta o incorrectamente , sera// no t i f i c a do mediante un parametro de s a l i d a .

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−private:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Ctes y Tipos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−static const unsigned MAX = 256;typedef std::array<umalcc_1 ::Cuenta , MAX> Datos;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Metodos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void anyadir_cuenta(const umalcc_1 :: Cuenta& cuenta , bool& ok);void elim_cuenta(unsigned p, bool& ok);unsigned buscar(unsigned num) const;void mostrar_cuenta_pos(unsigned pos) const;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Atr i bu tos Privados −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−unsigned cnt_cuentas;unsigned ncuentas;Datos cuentas;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

174

Page 175: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: banco.cpp� �#include "banco.hpp"#include <iostream>#include <fstream>#include <cassert>using namespace std;using namespace umalcc_1;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres anonimo . Es una par te pr ivada de l a// implementacion . No es a c c e s i b l e desde fuera de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−− Subprogramas Aux i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_cuenta(ifstream& fich , Cuenta& c){

string nombre;unsigned cuenta;double saldo;fich >> ws; // s a l t a e spac io s y s a l t o s de l i n e agetline(fich , nombre ); // l e e e l nombre (una l i n e a completa )fich >> cuenta; // l e e l a cuentafich >> saldo; // l e e e l sa ldoc = Cuenta(nombre , cuenta , saldo);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir_cuenta(ofstream& fich , const Cuenta& c){

if (! c.error ()) {fich << c.obtener_nombre () << endl;fich << c.obtener_cuenta () << endl;fich << c.obtener_saldo () << endl;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc_2 .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc_2 {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Banco :: Banco()

: cnt_cuentas (1), ncuentas (0), cuentas () {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: crear_cuenta(const std:: string& nombre , unsigned& num , bool& ok){

anyadir_cuenta(Cuenta(nombre , cnt_cuentas , 0.0), ok);if (ok) {

num = cnt_cuentas;++cnt_cuentas;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: eliminar_cuenta(unsigned num , bool& ok){

unsigned p = buscar(num);if (p < ncuentas) {

if (cuentas[p].obtener_saldo () > 0.0) {ok = false;

} else {elim_cuenta(p, ok);

}} else {

ok = false;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: ingreso(unsigned num , double cantidad , bool& ok){

assert(cantidad > 0.0);unsigned p = buscar(num);if (p < ncuentas) {

cuentas[p].ingresar_saldo(cantidad , ok);

175

Page 176: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: retirar(unsigned num , double cantidad , bool& ok){

assert(cantidad > 0.0);unsigned p = buscar(num);if (p < ncuentas) {

cuentas[p].retirar_saldo(cantidad , ok);} else {

ok = false;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: transferir(unsigned dest , unsigned origen , double cantidad ,

bool& ok){

assert(cantidad > 0.0);unsigned pd = buscar(dest);if (pd < ncuentas) {

unsigned po = buscar(origen );if (po < ncuentas) {

// primero se in t en ta r e t i r a r sa ldo , para comprobar// que hay s u f i c i e n t e sa ldocuentas[po].retirar_saldo(cantidad , ok);if (ok) {

cuentas[pd].ingresar_saldo(cantidad , ok);if (! ok) {

cuentas[po].ingresar_saldo(cantidad , ok);ok = false;

}}

} else {ok = false;

}} else {

ok = false;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: ingresar_intereses(double porcentaje){

assert(porcentaje > 0.0);bool ok;for (unsigned i = 0; i < ncuentas; ++i) {

cuentas[i].ingresar_interes(porcentaje , ok);if (! ok) {

cout << "Error al ingresar intereses a cuenta: "<< cuentas[i].obtener_cuenta () << endl;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: gastos_comision(double cantidad){

assert(cantidad > 0.0);bool ok;for (unsigned i = 0; i < ncuentas; ++i) {

cuentas[i].retirar_comision(cantidad , ok);if (! ok) {

cout << "Error al retirar comisiones a cuenta: "<< cuentas[i].obtener_cuenta () << endl;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: mostrar_cuenta(unsigned num , bool& ok) const{

unsigned p = buscar(num);if (p < ncuentas) {

mostrar_cuenta_pos(p);ok = true;

176

Page 177: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: mostrar_cuentas(const std:: string& nombre) const{

for (unsigned i = 0; i < ncuentas; ++i) {if (nombre == cuentas[i].obtener_nombre ()) {

mostrar_cuenta_pos(i);}

}cout << "-------------------------------------" << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: mostrar_cuentas () const{

for (unsigned i = 0; i < ncuentas; ++i) {mostrar_cuenta_pos(i);

}cout << "-------------------------------------" << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: mostrar_cuenta_pos(unsigned pos) const{

assert(pos < ncuentas );cout << "-------------------------------------" << endl;cuentas[pos].mostrar ();

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// FORMATO DEL FICHERO DE ENTRADA://// <cnt_cuentas> <RC>// <nombre> <RC> <cuenta> <RC> <saldo> <RC>// <nombre> <RC> <cuenta> <RC> <saldo> <RC>// . . .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: cargar_cuentas_fich(const std:: string& nombre_fich , bool& ok){

ifstream fich; // f l u j o de entrada de f i c h e r oCuenta c;

fich.open(nombre_fich.c_str ()); // v incu la l a v b l e de f l u j o con e l f i c h e r oif (fich.fail ()) {

ok = false; // error de apertura de l f i c h e r o} else {

ok = true;ncuentas = 0; // i n i c i a l i z a l a s cuentas bancar iasfich >> cnt_cuentas; // l e e e l contador de cuentasleer_cuenta(fich , c); // l e e una cuentawhile (!fich.fail() && ok) { // mientras l e c t u r a correc ta

anyadir_cuenta(c, ok); // anyade cuenta a l bancoleer_cuenta(fich , c); // l e e otra cuenta

}ok = ok && fich.eof(); // correc to s i a lcanzado Fin−De−Ficherofich.close (); // c i e r ra l a v incu lac i on

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// FORMATO DEL FICHERO DE SALIDA://// <cnt_cuentas> <RC>// <nombre> <RC> <cuenta> <RC> <saldo> <RC>// <nombre> <RC> <cuenta> <RC> <saldo> <RC>// . . .//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: guardar_cuentas_fich(const std:: string& nombre_fich , bool& ok) const{

ofstream fich; // f l u j o de s a l i d a de f i c h e r o

fich.open(nombre_fich.c_str ()); // v incu la l a v b l e de f l u j o con e l f i c h e r oif (fich.fail ()) {

ok = false; // error de apertura de l f i c h e r o} else {

177

Page 178: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

fich << cnt_cuentas << endl; // e c r i b e e l contador de cuentasunsigned i = 0; // Para cada elementowhile ((i < ncuentas) && (! fich.fail ())) { // mientras f i c h en buen es tado

escribir_cuenta(fich , cuentas[i]); // e s c r i b i r persona en f i c h e r o++i;

}ok = ! fich.fail (); // correc to s i f l u j o en buen es tadofich.close (); // c i e r ra l a v incu lac i on

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: anyadir_cuenta(const Cuenta& cuenta , bool& ok){

if (( ncuentas < cuentas.size ())&&( ! cuenta.error ())) {cuentas[ncuentas] = cuenta;++ncuentas;ok = true;

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Banco:: elim_cuenta(unsigned p, bool& ok){

if (p < ncuentas) {if (p < ncuentas-1) {

cuentas[p] = cuentas[ncuentas-1];}--ncuentas;ok = true;

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// busca un numero de cuentaunsigned Banco:: buscar(unsigned num) const{

unsigned i = 0;while ((i < ncuentas)

&&(num != cuentas[i].obtener_cuenta ())) {++i;

}return i;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �4. Diseñe un programa que permita utilizar el TAD especificado en el ejercicio anterior.

Solución: main.cpp� �#include <iostream>#include <string>#include <cctype>#include "banco.hpp"using namespace std;using namespace umalcc_2;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_nombre(string& n){

cout << "Introduza nombre: ";cin >> ws;getline(cin , n);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_num_cuenta(unsigned& n){

cout << "Introduza numero de cuenta: ";cin >> n;

}void leer_num_cuenta_o(unsigned& n){

178

Page 179: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "Introduza numero de cuenta origen: ";cin >> n;

}void leer_num_cuenta_d(unsigned& n){

cout << "Introduza numero de cuenta destino: ";cin >> n;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_cantidad(double& n){

do {cout << "Introduza cantidad (euros ): ";cin >> n;

} while ( !(n > 0.0) );}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_porcentaje(double& n){

do {cout << "Introduza porcentaje: ";cin >> n;

} while ( !(n > 0.0 && n <= 100) );}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void cargar_cuentas_bancarias(Banco& bnk){

string nombre_fich;bool ok;cout << "Introduce el nombre del fichero: ";cin >> nombre_fich;bnk.cargar_cuentas_fich(nombre_fich , ok);if (!ok) {

cout << "Error al cargar datos desde el fichero: "<< nombre_fich << endl;

}}void guardar_cuentas_bancarias(const Banco& bnk){

string nombre_fich;bool ok;cout << "Introduce el nombre del fichero: ";cin >> nombre_fich;bnk.guardar_cuentas_fich(nombre_fich , ok);if (!ok) {

cout << "Error al guardar datos al fichero: " << nombre_fich << endl;}

}void nueva_cuenta(Banco& bnk){

string n;bool ok;unsigned ncuenta;leer_nombre(n);bnk.crear_cuenta(n, ncuenta , ok);if (ok) {

cout << "Nueva Cuenta: " << endl;bnk.mostrar_cuenta(ncuenta , ok);if (! ok) {

cout << "Error al mostrar cuenta: " << n << endl;}

} else {cout << "Error al crear nueva cuenta para: " << n << endl;

}}void eliminar_cuenta(Banco& bnk){

unsigned n;bool ok;leer_num_cuenta(n);bnk.eliminar_cuenta(n, ok);if (! ok) {

cout << "Error al eliminar cuenta: " << n << endl;}

179

Page 180: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}void ingresar_efectivo(Banco& bnk){

unsigned n;bool ok;double c;leer_num_cuenta(n);leer_cantidad(c);bnk.ingreso(n, c, ok);if (! ok) {

cout << "Error al ingresar efectivo en cuenta: " << n << endl;}

}void retirar_efectivo(Banco& bnk){

unsigned n;bool ok;double c;leer_num_cuenta(n);leer_cantidad(c);bnk.retirar(n, c, ok);if (! ok) {

cout << "Error al retirar efectivo de cuenta: " << n << endl;}

}void transferir_efectivo(Banco& bnk){

unsigned nd , no;bool ok;double c;leer_num_cuenta_d(nd);leer_num_cuenta_o(no);leer_cantidad(c);bnk.transferir(nd , no , c, ok);if (! ok) {

cout << "Error al transferir efectivo desde: " << no<< " hasta: " << nd << endl;

}}void intereses(Banco& bnk){

double p;leer_porcentaje(p);bnk.ingresar_intereses(p);

}void comisiones(Banco& bnk){

double c;leer_cantidad(c);bnk.gastos_comision(c);

}void mostrar_ncuenta(const Banco& bnk){

unsigned n;bool ok;leer_num_cuenta(n);bnk.mostrar_cuenta(n, ok);if (! ok) {

cout << "Error al mostrar cuenta: " << n << endl;}

}void mostrar_nombre(const Banco& bnk){

string n;leer_nombre(n);bnk.mostrar_cuentas(n);

}void mostrar_completo(const Banco& bnk){

bnk.mostrar_cuentas ();}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

180

Page 181: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

char op;cout << endl;cout << "A. Cargar Cuentas Bancarias" << endl;cout << "B. Crear Cuenta Bancaria" << endl;cout << "C. Eliminar Cuenta Bancaria" << endl;cout << "D. Ingreso de Efectivo en Cuenta Bancaria" << endl;cout << "E. Retirada de Efectivo de Cuenta Bancaria" << endl;cout << "F. Transferencia de Efectivo de Cuenta Bancaria" << endl;cout << "G. Ingresar Intereses en Cuentas Bancarias" << endl;cout << "H. Gastos de Comision de Cuentas Bancarias" << endl;cout << "I. Mostrar Cuentas Bancarias (num -cuenta)" << endl;cout << "J. Mostrar Cuentas Bancarias (nombre)" << endl;cout << "K. Mostrar Cuentas Bancarias (completo)" << endl;cout << "L. Guardar Cuentas Bancarias" << endl;cout << "X. Fin" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'X')||(op >= 'A' && op <= 'L')));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Banco bnk;char op = ' ';do {

op = menu ();switch (op) {case 'A':

cargar_cuentas_bancarias(bnk);break;

case 'B':nueva_cuenta(bnk);break;

case 'C':eliminar_cuenta(bnk);break;

case 'D':ingresar_efectivo(bnk);break;

case 'E':retirar_efectivo(bnk);break;

case 'F':transferir_efectivo(bnk);break;

case 'G':intereses(bnk);break;

case 'H':comisiones(bnk);break;

case 'I':mostrar_ncuenta(bnk);break;

case 'J':mostrar_nombre(bnk);break;

case 'K':mostrar_completo(bnk);break;

case 'L':guardar_cuentas_bancarias(bnk);break;

}} while (op != 'X');

}� �5. Añada de forma incremental los siguientes métodos públicos al TAD Cuenta realizado anteriormente, de

tal forma que deberá permitir realizar ingresos y retirar efectivo de la cuenta bancaria. Además, también

181

Page 182: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

permitirá aplicar un determinado interés al saldo, así como cobrar unos gastos de comisión. Considerandoque si la cuenta se encuentra en estado erróneo, la operación será errónea y no se realizará ningunaoperación. Además, si la operación se realizó correcta o incorrectamente, será notificado mediante unparámetro de salida.

6. Añada de forma incremental los siguientes métodos públicos al TAD Banco realizado anteriormente,considerando que nunca podrá existir un saldo negativo. El tipo abstracto de datos deberá permitirrealizar ingresos y retirar efectivo de una determinada cuenta bancaria, así como realizar transferencias deefectivo de una cuenta a otra. Además, también permitirá aplicar un determinado interés a los saldos de lascuentas bancarias existentes, cobrar unos gastos de comisión, y mostrar los datos de las cuentas bancariasalmacenadas (para un determinado nombre de cliente, y para un determinado número de cuenta). Asímismo, también permitirá guardar y cargar los datos de ficheros.

7. Modifique el programa que utiliza el TAD Banco especificado anteriormente para que utilice los nuevosmétodos añadidos anteriormente.

182

Page 183: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Práctica 5: Gestión de Memoria Dinámica1. Diseñe un módulo (programación modular) que proporcione soporte adecuado a la manipulación de listas

enlazadas en memoria dinámica (véase siguiente figura). El módulo deberá definir el tipo PNodo como unpuntero a un registro en memoria dinámica de tipo Nodo que contiene un enlace al siguiente nodo, asícomo un dato de tipo int. Además, el módulo deberá definir los siguientes subprogramas. Diseñe tambiénun módulo principal que permita comprobar la corrección del módulo lista implementado.

lista: −−→◦ −−−−→◦0

−−−−→◦1

�2

Solución: lista.hpp� �#ifndef lista_hpp_#define lista_hpp_namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−struct Nodo ; // Declaración ade lantada de l t i p o incompleto Nodotypedef Nodo* PNodo ; // Def in i c ión de t i p o Puntero a t i p o incompleto Nodostruct Nodo { // Def in i c ión de l t i p o Nodo

PNodo sig ; // Enlace a l a s i g u i e n t e e s t ruc tu ra dinámicaint dato ; // Dato almacenado en l a l i s t a

} ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void inicializa(PNodo& lista) ;// I n i c i a l i z a ( l i s t a ) a una l i s t a vac ia//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void destruir(PNodo& lista) ;// Destruye todos l o s e lementos de l a l i s t a , l i b e rando// todos l o s nodos de memoria dinamica . ( l i s t a ) queda vac ia//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_principio(PNodo& lista , int dt) ;// Inse r ta un elemento a l p r i n c i p i o de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_final(PNodo& lista , int dt) ;// Inse r ta un elemento a l f i n a l de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo situar(PNodo lista , int pos) ;// Devuelve un puntero a l nodo que se encuentra en l a pos i c ion// indicada por ( pos ) . La pos i c ion cero (0) ind i ca e l primer nodo .// Si e l nodo no ex i s t e , entonces devue l ve NULL//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_pos(PNodo& lista , int pos , int dt) ;// Inse r ta en ( l i s t a ) un elemento en l a pos i c ion indicada por ( pos )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_primero(PNodo& lista) ;// Elimina e l primer elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_ultimo(PNodo& lista) ;// Elimina e l u l t imo elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_pos(PNodo& lista , int pos) ;// Elimina de ( l i s t a ) e l e lemento de l a pos i c ion indicada por ( pos ) ,// s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo duplicar(PNodo lista) ;// Devuelve un puntero a una nueva l i s t a r e su l t ado de dup l i c a r en// memoria dinamica l a l i s t a r e c i b i d a como parametro//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void escribir(PNodo lista) ;// Muestra en pan t a l l a e l contenido de ( l i s t a )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo leer() ;// Devuelve una l i s t a con l o s numeros l e i d o s de t e c l ado ( en e l mismo// orden que son in t roduc ido s ) hasta que l e a e l numero 0 ( que no es// in t roduc ido )//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−PNodo buscar(PNodo lista , int dt) ;

183

Page 184: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// Devuelve un puntero a l nodo que cont iene e l elemento// i g u a l a ( dt ) . Si no se encuentra , entonces devue l ve NULL//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void insertar_ord(PNodo& lista , int dt) ;// Inse r ta un elemento de forma ordenada en ( l i s t a ) , que debe e s t a r ordenada//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_elem(PNodo& lista , int dt) ;// Elimina de ( l i s t a ) e l primer elemento i g u a l a ( dt ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void eliminar_mayor(PNodo& lista) ;// Elimina e l mayor elemento de ( l i s t a ) , s i e x i s t e//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void purgar(PNodo& lista , int dt) ;// Elimina de ( l i s t a ) todos l o s e lementos que sean i g u a l e s a ( dt ) ,// s i e x i s t en//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}#endif� �

Solución: lista.cpp� �#include "lista.hpp"#include <iostream>#include <cstddef>#include <cassert>using namespace std;using namespace umalcc ;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Espacio de nombres umalcc .// Aqui r e s i d e l a implementacion de l a par te pub l i c a de l modulo//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// I n i c i a l i z a ( l i s t a ) a una l i s t a vac ia// sera inse r tado en l a l i s t a )void inicializa(PNodo& lista){

lista = NULL ;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Destruye todos l o s e lementos de l a l i s t a , l i b e rando// todos l o s nodos de memoria dinamica . ( l i s t a ) queda vac iavoid destruir(PNodo& lista){

while (lista != NULL) {PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento a l p r i n c i p i o de ( l i s t a )void insertar_principio(PNodo& lista , int dt){

PNodo ptr = new Nodo ;ptr->dato = dt ;ptr->sig = lista ;lista = ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento a l f i n a l de ( l i s t a )void insertar_final(PNodo& lista , int dt){

PNodo ptr = new Nodo ;ptr->dato = dt ;ptr->sig = NULL ;if (lista == NULL) {

lista = ptr ;} else {

PNodo act = lista ;while (act->sig != NULL) {

184

Page 185: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

act = act->sig ;}act->sig = ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que se encuentra en l a pos i c ion// indicada por ( pos ) . La pos i c ion cero (0) ind i ca e l primer nodo .// Si e l nodo no ex i s t e , entonces devue l ve NULLPNodo situar(PNodo lista , int pos){

PNodo ptr = lista;while ((ptr != NULL)&&(pos > 0)) {

ptr = ptr->sig;--pos;

}return ptr;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta en ( l i s t a ) un elemento en l a pos i c ion indicada por ( pos )void insertar_pos(PNodo& lista , int pos , int dt){

if (pos < 1) {PNodo ptr = new Nodo ;ptr->dato = dt ;ptr->sig = lista ;lista = ptr ;

} else {PNodo ant = situar(lista , pos - 1);if (ant != NULL) {

PNodo ptr = new Nodo ;ptr->dato = dt ;ptr->sig = ant->sig ;ant->sig = ptr ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l primer elemento de ( l i s t a ) , s i e x i s t evoid eliminar_primero(PNodo& lista){

if (lista != NULL) {PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l u l t imo elemento de ( l i s t a ) , s i e x i s t evoid eliminar_ultimo(PNodo& lista){

if (lista != NULL) {if (lista->sig == NULL) {

delete lista ;lista = NULL ;

} else {PNodo ant = lista ;PNodo act = ant->sig ;while (act->sig != NULL) {

ant = act ;act = act->sig ;

}delete act ;ant->sig = NULL ;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) e l e lemento de l a pos i c ion indicada por ( pos ) ,// s i e x i s t evoid eliminar_pos(PNodo& lista , int pos){

if (lista != NULL) {if (pos < 1) {

185

Page 186: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

} else {PNodo ant = situar(lista , pos - 1) ;if ((ant != NULL)&&(ant->sig != NULL)) {

PNodo act = ant->sig ;ant->sig = act->sig ;delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a una nueva l i s t a r e su l t ado de dup l i c a r en// memoria dinamica l a l i s t a r e c i b i d a como parametroPNodo duplicar(PNodo lista){

PNodo nueva = NULL;if (lista != NULL) {

nueva = new Nodo ;nueva->dato = lista->dato ;PNodo u = nueva ;PNodo p = lista->sig ;while (p != NULL) {

u->sig = new Nodo ;u->sig->dato = p->dato ;u = u->sig ;p = p->sig ;

}u->sig = NULL ;

}return nueva;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Muestra en pan t a l l a e l contenido de ( l i s t a )void escribir(PNodo lista){

PNodo ptr = lista;while (ptr != NULL) {

cout << ptr->dato << " " ;ptr = ptr->sig ;

}cout << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve una l i s t a con l o s numeros l e i d o s de t e c l ado ( en e l mismo// orden que son in t roduc ido s ) hasta que l e a e l numero 0 ( que no es// in t roduc ido )PNodo leer(){

PNodo lista = NULL ;int dt ;cin >> dt ;if (dt != 0) {

lista = new Nodo ;lista->dato = dt ;PNodo u = lista ;cin >> dt ;while (dt != 0) {

u->sig = new Nodo ;u->sig->dato = dt ;u = u->sig ;cin >> dt ;

}u->sig = NULL ;

}return lista;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Devuelve un puntero a l nodo que cont iene e l elemento// i g u a l a ( dt ) . Si no se encuentra , entonces devue l ve NULLPNodo buscar(PNodo lista , int dt){

186

Page 187: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

PNodo ptr = lista ;while ((ptr != NULL)&&(ptr->dato != dt)) {

ptr = ptr->sig ;}return ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Inse r ta un elemento de forma ordenada en ( l i s t a ) , que debe e s t a r// ordenadavoid insertar_ord(PNodo& lista , int dt){

PNodo ptr = new Nodo ;ptr->dato = dt ;if ((lista == NULL)||(dt < lista->dato)) {

ptr->sig = lista ;lista = ptr ;

} else {PNodo ant = lista ;PNodo act = ant->sig ;while ((act!=NULL)&&(act->dato<=dt)) {

ant = act ;act = act->sig ;

}ptr->sig = ant->sig ;ant->sig = ptr ;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) e l primer elemento i g u a l a ( dt ) , s i e x i s t evoid eliminar_elem(PNodo& lista , int dt){

if (lista != NULL) {if (lista->dato == dt) {

PNodo ptr = lista ;lista = lista->sig ;delete ptr ;

} else {PNodo ant = lista ;PNodo act = ant->sig ;while ((act != NULL)&&(act->dato != dt)) {

ant = act ;act = act->sig ;

}if (act != NULL) {

ant->sig = act->sig ;delete act ;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina e l mayor elemento de ( l i s t a ) , s i e x i s t evoid eliminar_mayor(PNodo& lista){

if (lista != NULL) {PNodo ant_may = NULL; // an t e r i o r a l mayorPNodo ptr_may = lista; // apunta a l mayorPNodo ant = lista; // an t e r i o r a l p t rPNodo ptr = lista->sig; // p t r de recor r idowhile (ptr != NULL) {

if (ptr->dato > ptr_may->dato) { // s i es mayorant_may = ant; // a c t u a l i z a r an t e r i o r a l mayorptr_may = ptr; // a c t u a l i z a r e l puntero a l mayor

}ant = ptr; // mover l o s punteros de recor r idoptr = ptr->sig;

}if (ptr_may == lista) {

lista = lista->sig;} else {

ant_may->sig = ptr_may->sig;}delete ptr_may;

}

187

Page 188: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// Elimina de ( l i s t a ) todos l o s e lementos que sean i g u a l e s a ( dt ) ,// s i e x i s t envoid purgar(PNodo& lista , int dt){

while ((lista != NULL)&&(dt == lista->dato)) {PNodo ptr = lista;lista = lista->sig;delete ptr;

}if (lista != NULL) {

PNodo ant = lista;PNodo act = lista->sig;while (act != NULL) {

if (dt == act->dato) {ant->sig = act->sig;delete act;

} else {ant = act;

}act = ant->sig;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include "lista.hpp"#include <iostream>using namespace std;using namespace umalcc;

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "X. Fin" << endl;cout << "A. Destruir Lista" << endl;cout << "B. Insertar Inicio" << endl;cout << "C. Insertar Final" << endl;cout << "D. Situar Posicion" << endl;cout << "E. Insertar Posicion" << endl;cout << "F. Eliminar Primero" << endl;cout << "G. Eliminar Ultimo" << endl;cout << "H. Eliminar Posicion" << endl;cout << "I. Duplicar" << endl;cout << "J. Escribir" << endl;cout << "K. Leer" << endl;cout << "L. Buscar Elemento" << endl;cout << "M. Insertar Ordenado" << endl;cout << "N. Eliminar Elemento" << endl;cout << "O. Eliminar Mayor" << endl;cout << "P. Purgar" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'X')||((op >= 'A')&&(op <= 'P'))));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer(int& dato){

cout << "Introduzca dato: " ;cin >> dato;

}void leer(unsigned& pos){

188

Page 189: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "Introduzca posicion: " ;cin >> pos;

}void prueba_duplicar(PNodo lista){

PNodo aux = duplicar(lista);cout << "Lista original: " ;escribir(lista);cout << "Lista copia: " ;escribir(aux);destruir(aux);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

PNodo lista;PNodo aux;char op = ' ';int dato;unsigned pos;inicializa(lista);do {

op = menu ();switch (op) {case 'A':

destruir(lista);escribir(lista);break;

case 'B':leer(dato);insertar_principio(lista , dato);escribir(lista);break;

case 'C':leer(dato);insertar_final(lista , dato);escribir(lista);break;

case 'D':leer(pos);aux = situar(lista , pos);if (aux == NULL) {

cout << "Error: posicion erronea" << endl;} else {

cout << "Elemento ["<<pos<<"]: " << aux->dato << endl;}escribir(lista);break;

case 'E':leer(pos);leer(dato);insertar_pos(lista , pos , dato) ;escribir(lista);break;

case 'F':eliminar_primero(lista);escribir(lista);break;

case 'G':eliminar_ultimo(lista);escribir(lista);break;

case 'H':leer(pos);eliminar_pos(lista , pos) ;escribir(lista);break;

case 'I':prueba_duplicar(lista);break;

case 'J':escribir(lista);break;

case 'K':

189

Page 190: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

destruir(lista);cout << "Introduzca elementos (0 -> FIN)" << endl;lista = leer ();escribir(lista);break;

case 'L':leer(dato);aux = buscar(lista , dato);if (aux == NULL) {

cout << "Error: No encontrado" << endl;} else {

cout << "Elemento: " << aux->dato << endl;}escribir(lista);break;

case 'M':leer(dato);insertar_ord(lista , dato);escribir(lista);break;

case 'N':leer(dato);eliminar_elem(lista , dato);escribir(lista);break;

case 'O':eliminar_mayor(lista );escribir(lista);break;

case 'P':leer(dato);purgar(lista , dato);escribir(lista);break;

}} while (op != 'X');destruir(lista);

}� �

190

Page 191: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Práctica 6: Abstracción en la Gestión de Memoria Dinámica (I)1. Diseñe un TAD Dato en el espacio de nombres umadpt que contiene un valor de tipo entero, y defina los

siguientes métodos:

Destructor: destruye y libera los recursos asociados al objeto.

Constructor por defecto: construye un objeto con valor cero.

Constructor específico: construye un objeto con el valor recibido como parámetro.

Constructor de copia: copia el contenido de otro objeto.

Operador de asignación: asigna el contenido de otro objeto.

Acceder: método constante que devuelve el valor contenido en el objeto.

Modificar: cambia el valor contenido en el objeto por el valor recibido como parámetro.

Solución: dato.hpp� �#ifndef dato_hpp_#define dato_hpp_namespace umadpt {

class Dato {public:

// ~Dato ( ) ;// Dato ( const Dato& o ) ;// Dato& operator=(const Dato& o ) ;Dato ();Dato(int v);int acceder () const;void modificar(int v);

private:int valor;

};}#endif� �

Solución: dato.cpp� �#include "dato.hpp"namespace umadpt {

// Dato : :~ Dato () {}// Dato : : Dato ( const Dato& o) : va l o r (o . va l o r ) {}// Dato& Dato : : operator=(const Dato& o)// {// i f ( t h i s != &o) {// va l o r = o . va l o r ;// }// return ∗ t h i s ;// }Dato::Dato() : valor (0) {}Dato::Dato(int v) : valor(v) {}int Dato:: acceder () const{

return valor;}void Dato:: modificar(int v){

valor = v;}

}� �2. Diseñe un TAD BolsaDato en el espacio de nombres umalcc que contiene una colección de elementos

homogéneos (de tipo Dato de umadpt), y defina los siguientes métodos:

Destructor: destruye y libera los recursos asociados a la bolsa.

Constructor por defecto: construye una bolsa vacía.

Constructor de copia: copia el contenido de otra bolsa.

Operador de asignación: asigna el contenido de otra bolsa.

191

Page 192: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Size: método constante que devuelve el número de elementos almacenados en la bolsa.

Clear: elimina los elementos almacenados, dejando la bolsa vacía.

Mostrar: método constante que muestra en pantalla el contenido de la bolsa.

Añadir: añade el dato recibido como parámetro a la bolsa.

Eliminar: elimina un elemento de la bolsa que sea igual al valor del dato recibido como parámetro.

Pertenece: método constante que devuelve true si el dato recibido como parámetro se encuentra enla bolsa, y false en cualquier otro caso.

Cambiar: cambia el valor de todos los elementos de la bolsa que son iguales al primer dato recibidocomo parámetro por el valor del segundo dato recibido como parámetro.

Extraer: elimina de la bolsa todos los elementos iguales al valor del dato recibido como parámetro, ydevuelve la cuenta del número de elementos eliminados.

Solución: bolsa_dato.hpp� �#ifndef bolsa_dato_hpp_#define bolsa_dato_hpp_#include "dato.hpp"namespace umalcc {

class BolsaDato {public:

˜ BolsaDato ();BolsaDato ();BolsaDato(const BolsaDato& o);BolsaDato& operator=(const BolsaDato& o);int size() const;void clear ();void mostrar () const;void anyadir(const umadpt ::Dato& d);void eliminar(const umadpt ::Dato& d);bool pertenece(const umadpt ::Dato& d) const;void cambiar(const umadpt ::Dato& d1, const umadpt ::Dato& d2);int extraer(const umadpt ::Dato& d);

private://−− Tipos −−struct Nodo;typedef Nodo* PNodo;struct Nodo {

PNodo sig;umadpt ::Dato d;

};//−− Métodos Privados −−void destruir(PNodo& l) const;PNodo duplicar(PNodo l) const;void mostrar_lista(PNodo l) const;void insertar_principio(PNodo& l, const umadpt ::Dato& d) const;void eliminar_elm(PNodo& l, const umadpt ::Dato& d, bool& ok) const;PNodo buscar_elm(PNodo l, const umadpt ::Dato& d) const;void reemplazar(PNodo& l, const umadpt ::Dato& d1 , const umadpt ::Dato& d2) const;int purgar(PNodo& l, const umadpt ::Dato& d) const;//−− Atr i bu tos −−int sz;PNodo lista;

};}#endif� �

Solución: bolsa_dato.cpp� �#include "bolsa_dato.hpp"#include <iostream>#include <cstddef>using namespace std;using namespace umadpt;namespace umalcc {

BolsaDato :: ˜ BolsaDato (){

destruir(lista);

192

Page 193: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}BolsaDato :: BolsaDato () : sz(0), lista(NULL) {}BolsaDato :: BolsaDato(const BolsaDato& o)

: sz(o.sz), lista(duplicar(o.lista)) {}BolsaDato& BolsaDato :: operator=(const BolsaDato& o){

if (this != &o) {destruir(lista);sz = o.sz;lista = duplicar(o.lista);

}return *this;

}void BolsaDato :: clear(){

destruir(lista);sz = 0;

}int BolsaDato ::size() const{

return sz;}void BolsaDato :: mostrar () const{

mostrar_lista(lista );}void BolsaDato :: anyadir(const Dato& d){

insertar_principio(lista , d);++sz;

}void BolsaDato :: eliminar(const Dato& d){

bool ok;eliminar_elm(lista , d, ok);if (ok) {

--sz;}

}bool BolsaDato :: pertenece(const Dato& d) const{

PNodo p = buscar_elm(lista , d);return p != NULL;

}void BolsaDato :: cambiar(const Dato& d1, const Dato& d2){

reemplazar(lista , d1 , d2);}int BolsaDato :: extraer(const Dato& d){

int cnt = purgar(lista , d);sz -= cnt;return cnt;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void BolsaDato :: destruir(PNodo& l) const{

while (l != NULL) {PNodo p = l;l = l->sig;delete p;

}}BolsaDato :: PNodo BolsaDato :: duplicar(PNodo l) const{

PNodo r = NULL;if (l != NULL) {

r = new Nodo;r->d = l->d;PNodo u = r;PNodo p = l->sig;while (p != NULL) {

u->sig = new Nodo;u->sig->d = p->d;

193

Page 194: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

u = u->sig;p = p->sig;

}u->sig = NULL;

}return r;

}void BolsaDato :: mostrar_lista(PNodo l) const{

PNodo p = l;cout << "{ ";while (p != NULL) {

cout << p->d.acceder ();p = p->sig;if (p != NULL) {

cout << ", ";}

}cout << " }";

}void BolsaDato :: insertar_principio(PNodo& l, const Dato& d) const{

PNodo p = new Nodo;p->d = d;p->sig = l;l = p;

}void BolsaDato :: eliminar_elm(PNodo& l, const Dato& d, bool& ok) const{

ok = false;if (l != NULL) {

if (d.acceder () == l->d.acceder ()) {PNodo p = l;l = l->sig;delete p;ok = true;

} else {PNodo ant = l;PNodo act = l->sig;while ((act != NULL)&&(d.acceder ()!=act->d.acceder ())){

ant = act;act = act->sig;

}if (act != NULL) {

ant->sig = act->sig;delete act;ok = true;

}}

}}BolsaDato :: PNodo BolsaDato :: buscar_elm(PNodo l, const Dato& d) const{

PNodo p = l;while ((p != NULL)&&(d.acceder () != p->d.acceder ())) {

p = p->sig;}return p;

}void BolsaDato :: reemplazar(PNodo& l, const Dato& d1, const Dato& d2) const{

PNodo p = l;while (p != NULL) {

if (d1.acceder () == p->d.acceder ()) {p->d.modificar(d2.acceder ()); // e qu i v a l en t e a : p−>d = d2 ;

}p = p->sig;

}}int BolsaDato :: purgar(PNodo& l, const Dato& d) const{

int cnt = 0;while ((l != NULL)&&(d.acceder () == l->d.acceder ())) {

PNodo ptr = l;

194

Page 195: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

l = l->sig;delete ptr;++cnt;

}if (l != NULL) {

PNodo ant = l;PNodo act = l->sig;while (act != NULL) {

if (d.acceder () == act->d.acceder ()) {ant->sig = act->sig;delete act;++cnt;

} else {ant = act;

}act = ant->sig;

}}return cnt;

}}� �

3. Diseñe un programa que permita utilizar el TAD especificado en el ejercicio anterior.

Solución: main.cpp� �#include <iostream>#include "bolsa_dato.hpp"using namespace std;using namespace umadpt;using namespace umalcc;void comprobar_1(const BolsaDato& b){

if (b.size() != 5) {cout << "Error en tamaño" << endl;

}for (int i = 1; i <= 4; ++i) {

if (! b.pertenece(Dato(i))) {cout << "Error: elemento " << i

<< endl;}

}}void comprobar_2(const BolsaDato& b){

if (b.size() != 3) {cout << "Error en tamaño" << endl;

}for (int i = 4; i <= 6; ++i) {

if (! b.pertenece(Dato(i))) {cout << "Error: elemento " << i

<< endl;}

}}int main(){

BolsaDato b1;for (int i = 1; i <= 4; ++i) {

b1.anyadir(Dato(i));}b1.anyadir(Dato (2));b1.mostrar ();cout << endl;BolsaDato b2 = b1;comprobar_1(b1);comprobar_1(b2);b2.cambiar(Dato(2), Dato (5));b2.cambiar(Dato(3), Dato (6));b2.eliminar(Dato (5));b2.eliminar(Dato (1));comprobar_2(b2);b2.mostrar ();

195

Page 196: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << endl;

b2 = b1;b2.anyadir(Dato (2));b2.mostrar ();cout << endl;int cnt = b2.extraer(Dato (2));b2.mostrar ();cout << endl;cout << "Cuenta de elementos extraídos: " << cnt << endl;cout << "Fin de BolsaDato" << endl;

// Fal ta prueba de ex t rae r}� �

196

Page 197: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Práctica 7: Abstracción en la Gestión de Memoria Dinámica (II)1. Diseñe e implemente un TAD Persona, que almacene el nombre y el teléfono de una persona (ambos de

tipo cadena de caracteres), y proporcione los siguientes métodos publicos:

Solución: persona.hpp� �#ifndef persona_hpp_#define persona_hpp_#include <string>namespace umalcc {

class Persona {public:

˜ Persona () ;// Destruye e l o b j e t o y todos sus recursos asoc iados .

Persona () ;// Construye una persona con nombre y t e l e f o no vac ío .

Persona(const std:: string& n, const std:: string& t) ;// Construye una persona con e l nombre y e l t e l e f o no// segun l o s parametros r e c i b i d o s .

bool error() const;// Devuelve t rue s i e l o b j e t o ac tua l e s ta en es tado erroneo ,// es decir , e l nombre o e l t e l e f o no son vac ío s .

std:: string obtener_nombre () const;// Devuelve e l va l o r de l nombre de l o b j e t o ac tua l .

std:: string obtener_telefono () const;// Devuelve e l va l o r de l t e l e f o no de l o b j e t o ac tua l .

private:std:: string nombre;std:: string telefono;

};}#endif� �

Solución: persona.cpp� �#include "persona.hpp"#include <string>using namespace std;namespace umalcc {

Persona :: ˜ Persona () {}Persona :: Persona () : nombre(), telefono () {}Persona :: Persona(const std:: string& n, const std:: string& t)

: nombre(n), telefono(t) {}bool Persona ::error () const{

return (nombre.size() == 0)||(telefono.size() == 0);}std:: string Persona :: obtener_nombre () const{

return nombre;}std:: string Persona :: obtener_telefono () const{

return telefono;}

}� �2. Diseñe e implemente un TAD Agenda que, utilizando el TAD Persona definido anteriormente, almacene

el nombre y teléfono de múltiples personas, y permita su acceso de forma adecuada. La agenda se puedeimplementar eficientemente utilizando técnicas hash, de la siguiente forma:

Cuando se quiere almacenar una nueva persona, se calcula el número que proporciona la función hashaplicada al nombre de la persona, y posteriormente se añade la persona a la lista enlazada que seencuentra en la posición indicada por el número hash calculado (véase ejemplo a continuación).Cuando se quiere acceder a una determinada persona, se calcula el número que proporciona la funciónhash aplicada al nombre de la persona, y se busca la persona en la lista enlazada que se encuentraen la posición indicada por el número hash calculado (véase ejemplo a continuación).

197

Page 198: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Cuando se quiere borrar a una determinada persona, se calcula el número que proporciona la funciónhash aplicada al nombre de la persona, y se elimina la persona con ese nombre de la lista enlazada quese encuentra en la posición indicada por el número hash calculado (véase ejemplo a continuación).

Por ejemplo, la función hash para el nombre de la persona puede ser la siguiente, donde el primer parámetroespecifica el nombre de la persona, y el segundo parámetro especifica el tamaño del array de listas enlazadas:

unsigned hash(const std:: string& nombre , unsigned tamanyo){

unsigned valor = 0;for (unsigned i = 0; i < nombre.size (); ++i) {

valor = valor * 7 + unsigned(nombre[i]);}return valor % tamanyo;

}

Por ejemplo, dado un tamaño del array de 5, si la función hash para los nombres pepe, maria y anaproporciona el valor 0, para el nombre juan proporciona el valor 2 y para los nombres lola y jaimeproporciona el valor 4, tendríamos la estructura que se muestra a continuación:

6nelms

elms0

1

2

3

4

30

pepe

22

maria

35

ana

37

jaime

23

lola

27

juan

El TAD Agenda debe proporcionar los siguientes métodos públicos:

Solución: persona.hpp� �#ifndef agenda_hpp_#define agenda_hpp_#include "persona.hpp"#include <string>#include <array>namespace umalcc {

class Agenda {public:

˜ Agenda () ;// Destruye e l o b j e t o y todos sus recursos asoc iados .

Agenda () ;// Construye una agenda vac ia .

Agenda(const Agenda& o) ;// Construye una agenda como copia de otra agenda

Agenda& operator=(const Agenda& o) ;// Construye una agenda como copia de otra agenda

void anyadir(const Persona& p);// Si l a persona e s p e c i f i c a da como parametro no es ta en modo// erroneo , s i l a persona ya se encontraba en l a agenda ,// entonces l o s nuevos va l o r e s de l a persona reemplazan a l o s// anter iore s , en otro caso anyade l a persona e s p e c i f i c a da a// l a agenda ac tua l .

Persona buscar(const std:: string& nombre) const;// Busca en l a agenda l a persona cuyo nombre se e s p e c i f i c a// como parametro , y s i l a encuentra , entonces devue l ve un ob j e t o// Persona con l o s va l o r e s de l a persona almacenados . Si no// l a encuentra , entonces devue l ve una persona en es tado de// error .

void eliminar(const std:: string& nombre , bool& ok);// Elimina de l a agenda ac tua l l a persona cuyo nombre se// e s p e c i f i c a como parametro y ok tomara e l va l o r t rue . En caso// de no e x i s t i r , ok tomara e l va l o r f a l s e .

void mostrar () const;

198

Page 199: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

// Muestra en pan t a l l a e l contenido completo de l a agenda .private:

struct Nodo;typedef Nodo* PNodo;struct Nodo {

PNodo sig;Persona per;

};static const int MAX = 100;typedef std::array<PNodo , MAX> Datos;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−void destruir(PNodo& lista) const;PNodo duplicar(PNodo lista) const;PNodo buscar(PNodo lista , const std:: string& nombre) const;void insertar_principio(PNodo& lista , const Persona& p) const;void eliminar(PNodo& lista , const std:: string& nombre , bool& ok) const;void mostrar(PNodo lista) const;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−int nelms;Datos v;

};}#endif� �

Solución: persona.cpp� �#include "agenda.hpp"#include "persona.hpp"#include <iostream>#include <string>#include <array>using namespace std;namespace {

unsigned hash(const std:: string& nombre , unsigned tamanyo){

unsigned valor = 0;for (unsigned i = 0; i < nombre.size (); ++i) {

valor = valor * 7 + unsigned(nombre[i]);}return valor % tamanyo;

}}namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Agenda :: ˜ Agenda (){

for (unsigned i = 0; i < v.size (); ++i) {destruir(v[i]);

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Agenda :: Agenda () : nelms(0), v(){

for (unsigned i = 0; i < v.size (); ++i) {v[i] = NULL;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Agenda :: Agenda(const Agenda& o) : nelms(o.nelms), v(){

for (unsigned i = 0; i < v.size (); ++i) {v[i] = duplicar(o.v[i]);

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Agenda& Agenda :: operator=(const Agenda& o){

if (this != &o) {nelms = o.nelms;for (unsigned i = 0; i < v.size (); ++i) {

destruir(v[i]);v[i] = duplicar(o.v[i]);

199

Page 200: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}}return *this;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: anyadir(const Persona& p){

if (! p.error ()) {unsigned h = hash(p.obtener_nombre (), v.size ());PNodo ptr = buscar(v[h], p.obtener_nombre ());if (ptr != NULL) {

ptr->per = p;} else {

insertar_principio(v[h], p);++nelms;

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Persona Agenda :: buscar(const std:: string& nombre) const{

Persona p;unsigned h = hash(nombre , v.size ());PNodo ptr = buscar(v[h], nombre );if (ptr != NULL) {

p = ptr->per;}return p;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: eliminar(const std:: string& nombre , bool& ok){

unsigned h = hash(nombre , v.size ());eliminar(v[h], nombre , ok);if (ok) {

--nelms;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: mostrar () const{

cout << "N_Personas: " << nelms << endl;for (unsigned i = 0; i < v.size (); ++i) {

if (v[i] != NULL) {cout << "[" << i << "]" << endl;mostrar(v[i]);

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: destruir(PNodo& lista) const{

while (lista != NULL) {PNodo ptr = lista;lista = lista->sig;delete ptr;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Agenda ::PNodo Agenda :: duplicar(PNodo lista) const{

PNodo nueva = NULL;if (lista != NULL) {

nueva = new Nodo ;nueva->per = lista->per ;PNodo u = nueva ;PNodo p = lista->sig ;while (p != NULL) {

u->sig = new Nodo ;u->sig->per = p->per ;u = u->sig ;p = p->sig ;

}u->sig = NULL ;

200

Page 201: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}return nueva;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Agenda ::PNodo Agenda :: buscar(PNodo lista , const std:: string& nombre) const{

PNodo ptr = lista ;while ((ptr != NULL)&&(nombre != ptr->per.obtener_nombre ())) {

ptr = ptr->sig ;}return ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: insertar_principio(PNodo& lista , const Persona& p) const{

PNodo ptr = new Nodo ;ptr->per = p ;ptr->sig = lista ;lista = ptr ;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: eliminar(PNodo& lista , const std:: string& nombre ,

bool& ok) const{

ok = false;if (lista != NULL) {

if (lista->per.obtener_nombre () == nombre) {PNodo ptr = lista ;lista = lista->sig ;delete ptr ;ok = true;

} else {PNodo ant = lista ;PNodo act = ant->sig ;while ((act != NULL)&&(act->per.obtener_nombre () != nombre )) {

ant = act ;act = act->sig ;

}if (act != NULL) {

ant->sig = act->sig ;delete act ;ok = true;

}}

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Agenda :: mostrar(PNodo lista) const{

PNodo ptr = lista ;while (ptr != NULL) {

cout << ptr->per.obtener_nombre () << " "<< ptr->per.obtener_telefono () << endl ;

ptr = ptr->sig ;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �3. Diseñe un programa que permita utilizar el TAD especificado en el ejercicio anterior.

Solución: main.cpp� �#include <iostream>#include <string>#include <cctype>#include "persona.hpp"#include "agenda.hpp"using namespace std;using namespace umalcc;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_nombre(string& nombre){

201

Page 202: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

cout << "Introduza nombre (sin espacios ): ";cin >> nombre;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void leer_persona(Persona& p){

string nombre , tfn;leer_nombre(nombre );cout << "Introduza telefono: ";cin >> tfn;p = Persona(nombre , tfn);

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void mostrar_persona(const Persona& p){

cout << "Nombre: " << p.obtener_nombre () << endl;cout << "telefono: " << p.obtener_telefono () << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−char menu(){

char op;cout << endl;cout << "A. Añadir datos de persona" << endl;cout << "B. Mostrar toda la agenda" << endl;cout << "C. Mostrar datos de persona" << endl;cout << "D. Borrar persona" << endl;cout << "X. Fin" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!(((op >= 'A')&&(op <= 'D'))||(op == 'X')));cout << endl;return op;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int main(){

Agenda ag;Persona p;string n;bool ok;char op;do {

op = menu ();switch (op) {case 'A':

leer_persona(p);ag.anyadir(p);break;

case 'B':ag.mostrar ();break;

case 'C':leer_nombre(n);p = ag.buscar(n);if (p.error ()) {

cout << "Error , persona no encontrada" << endl;} else {

mostrar_persona(p);}break;

case 'D':leer_nombre(n);ag.eliminar(n, ok);if (!ok) {

cout << "Error , persona no encontrada" << endl;}break;

}} while (op != 'X');

}� �202

Page 203: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Práctica 8: Introducción a la Programación Orientada a Objetos1. Se dispone de la siguiente jerarquía de clases para gestionar los coches de un concesionario de coches.

Coche

CocheOcasion Importado

Coche

Concesionario

La clase polimórfica Coche representa un determinado modelo de coche, tiene un constructor quepermite crear un objeto con el nombre (string) y el precio base (double) del modelo del cocherecibidos como parámetros, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• obtener_modelo(): devuelve el nombre del modelo del objeto actual.• calc_precio(): calcula y devuelve el precio del coche actual, según la siguiente ecuación:

precio = precio_base

• mostrar(): muestra en pantalla la información del objeto actual, según el formato del siguienteejemplo (sin salto de línea): (Porsche-911, 40000), considerando que el acceso a la informaciónse realizará invocando a los metodos adecuados.

La clase polimórfica CocheOcasion representa un coche de ocasión, que es-un coche con un porcen-taje de descuento. Para ello, tiene un constructor que permite crear un objeto con el nombre (string),el precio base (double) y el porcentaje de descuento (double) del modelo del coche recibidos comoparámetros, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• obtener_descuento(): devuelve el porcentaje de descuento que se aplicará cuando se calcule elprecio del objeto actual.

• calc_precio(): calcula y devuelve el precio del coche actual, según la siguiente ecuación:

precio = precio_base − precio_base × porcentaje ÷ 100

La clase polimórfica CocheImportado representa un coche de importado, que es-un coche con uncoste de homologación adicional. Para ello, tiene un constructor que permite crear un objeto con elnombre (string), el precio base (double) y el coste de homologación (double) del modelo del cocherecibidos como parámetros, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• obtener_homologacion(): devuelve el coste de homologacion que se aplicará cuando se calculeel precio del objeto actual.

• calc_precio(): calcula y devuelve el precio del coche actual, según la siguiente ecuación:

precio = precio_base + coste_homologacion

La clase polimórfica Concesionario representa un concesionario de coches, de tal forma que puedecontener múltiples coches de diversas clases. Para ello, tiene un constructor que permite crear unobjeto concesionario vacío, sin coches, y proporciona los siguientes métodos públicos virtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.• anyadir(): recibe como parámetro un puntero a un objeto coche, y comprueba si ya está alma-cenado un coche con el mismo nombre de modelo, en cuyo caso reemplaza el coche anterior porel nuevo recibido como parámetro (atención a la pérdida de recursos). Sin embargo, si no hay uncoche con el mismo nombre de modelo, entonces. si cabe, lo añade al concesionario. Finalmentedevuelve en un parámetro de salida true si la operación se ha realizado adecuadamente y falseen otro caso.

• calc_precio(): recibe como parámetro el nombre de un modelo, y, si existe, devuelve el preciode dicho modelo. En caso de que no exista dicho modelo, entonces devuelve el valor -1.

203

Page 204: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

• seleccionar_barato(): calcula y devuelve un puntero al objeto coche que tenga el menor preciode todos los almacenados en el concesionario. Si no hay coches almacenados, entonces devuelveNULL.

• mostrar(): muestra en pantalla la información de todos los coches almacenados en el objetoactual, invocando al método mostrar sobre cada coche, según el formato del siguiente ejemplo:{ (Seat-Marbella, 7200), (Seat-Leon, 15000), (Porsche-911, 40000) }

• Hay que considerar que el destructor del concesionario debe destruir todos los coches allí alma-cenados.

• Se recomienda definir un método privado para buscar un determinado nombre de modelo en elarray, y devuelva la posición donde se encuentra, o -1 en otro caso.

Finalmente, el programa principal realizará las siguientes acciones:a) Creará un objeto concesionario,b) Añadirá los siguientes coches:

• Coche de ocasión, Seat-Marbella, precio 9000, descuento 20%.• Coche, Seat-Leon, precio 15000.• Coche de importación, Porsche-911, precio 39000, homologación 1000.

c) Clonará el concesionario actual en otro nuevo, y destruirá el antiguo.d) Calculará y mostrará el precio final de los tres coches anteriores.e) Seleccionará y mostrará el coche más barato.f ) Mostrará el contenido completo del concesionario.g) Finalmente, destruirá el concesionario.Producirá la siguiente salida en pantalla:

Precio Seat-Marbella: 7200Precio Seat-Leon: 15000Precio Porsche-911: 40000Mas Barato: (Seat-Marbella, 7200){ (Seat-Marbella, 7200), (Seat-Leon, 15000), (Porsche-911, 40000) }

Solución: coche.hpp� �#ifndef coche_hpp__#define coche_hpp__#include <string>namespace umalcc {

class Coche {public:

Coche(const std:: string& m, double p);virtual ˜ Coche ();virtual Coche* clone() const;virtual std:: string obtener_modelo () const;virtual double calc_precio () const;virtual void mostrar () const;

protected:Coche(const Coche& o);

private:Coche& operator=(const Coche& o);//−−−−−−−−−−−−−−−−−−−−−−−−−−−−std:: string modelo;double precio;

};}#endif� �

Solución: coche.cpp� �#include "coche.hpp"#include <iostream>using namespace std;namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Coche :: Coche(const std:: string& m, double p) : modelo(m), precio(p) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

204

Page 205: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Coche :: Coche(const Coche& o) : modelo(o.modelo), precio(o.precio) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Coche :: ˜ Coche() {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Coche* Coche:: clone() const { return new Coche(*this); }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−std:: string Coche :: obtener_modelo () const { return modelo; }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Coche :: calc_precio () const { return precio; }//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Coche:: mostrar () const {

cout << "(" << obtener_modelo () << ", " << calc_precio () << ")";}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: coche_ocasion.hpp� �

#ifndef coche_ocasion_hpp__#define coche_ocasion_hpp__#include <string>#include "coche.hpp"namespace umalcc {

class CocheOcasion : public Coche {public:

CocheOcasion(const std:: string& m, double p, double d);virtual ˜ CocheOcasion ();virtual CocheOcasion* clone () const;virtual double calc_precio () const;virtual double obtener_descuento () const;

protected:CocheOcasion(const CocheOcasion& o);

private:double porc_descuento;

};}#endif� �

Solución: coche_ocasion.cpp� �#include "coche_ocasion.hpp"namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CocheOcasion :: CocheOcasion(const std:: string& m, double p, double d)

: Coche(m, p), porc_descuento(d) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CocheOcasion :: CocheOcasion(const CocheOcasion& o)

: Coche(o), porc_descuento(o.porc_descuento) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CocheOcasion :: ˜ CocheOcasion () {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CocheOcasion* CocheOcasion :: clone() const {

return new CocheOcasion(*this);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double CocheOcasion :: calc_precio () const {

double pr = Coche:: calc_precio ();return pr - pr * obtener_descuento () / 100.0;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double CocheOcasion :: obtener_descuento () const {

return porc_descuento;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: coche_importado.hpp� �

#ifndef coche_importado_hpp__

205

Page 206: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

#define coche_importado_hpp__#include <string>#include "coche.hpp"namespace umalcc {

class CocheImportado : public Coche {public:

CocheImportado(const std:: string& m, double p, double h);virtual ˜ CocheImportado ();virtual CocheImportado* clone() const;virtual double calc_precio () const;virtual double obtener_homologacion () const;

protected:CocheImportado(const CocheImportado& o);

private:double homologacion;

};}#endif� �

Solución: coche_importado.cpp� �#include "coche_importado.hpp"namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CocheImportado :: CocheImportado(const std:: string& m, double p, double h)

: Coche(m, p), homologacion(h) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CocheImportado :: CocheImportado(const CocheImportado& o)

: Coche(o), homologacion(o.homologacion) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CocheImportado :: ˜ CocheImportado () {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CocheImportado* CocheImportado ::clone() const {

return new CocheImportado(*this);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double CocheImportado :: calc_precio () const {

return Coche :: calc_precio () + obtener_homologacion ();}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double CocheImportado :: obtener_homologacion () const {

return homologacion;}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: concesionario.hpp� �

#ifndef concesionario_hpp__#define concesionario_hpp__#include <string>#include <array>#include "coche.hpp"namespace umalcc {

class Concesionario {public:

Concesionario ();virtual ˜ Concesionario ();virtual Concesionario* clone() const;virtual void anyadir(Coche* c, bool& ok);virtual double calc_precio(const std:: string& m) const;virtual Coche* seleccionar_barato () const;virtual void mostrar () const;

protected:Concesionario(const Concesionario& o);

private:Concesionario& operator=(const Concesionario& o);int buscar(const std:: string& m) const;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−static const int MAX_COCHES = 30;typedef std::array<Coche*, MAX_COCHES> ACoches;

206

Page 207: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−int ncoches;ACoches coches;

};}#endif� �

Solución: concesionario.cpp� �#include "concesionario.hpp"#include <iostream>#include <string>#include <array>using namespace std;namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Concesionario :: Concesionario () : ncoches (0), coches () {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Concesionario :: Concesionario(const Concesionario& o)

: ncoches(o.ncoches), coches () {for (int i = 0; i < ncoches; ++i) {

coches[i] = o.coches[i]->clone ();}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Concesionario :: ˜ Concesionario () {

for (int i = 0; i < ncoches; ++i) {delete coches[i];

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Concesionario* Concesionario ::clone() const {

return new Concesionario(*this);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Concesionario :: anyadir(Coche* c, bool& ok) {

int p = buscar(c->obtener_modelo ());if (p >= 0) {

delete coches[p];coches[p] = c;ok = true;

} else if (ncoches < int(coches.size ())) {coches[ncoches] = c;++ncoches;ok = true;

} else {ok = false;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−double Concesionario :: calc_precio(const std:: string& m) const {

double pr = -1;int p = buscar(m);if (p >= 0) {

pr = coches[p]->calc_precio ();}return pr;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Coche* Concesionario :: seleccionar_barato () const {

Coche* c = NULL;if (ncoches > 0) {

c = coches[0];for (int i = 1; i < ncoches; ++i) {

if (coches[i]->calc_precio () < c->calc_precio ()) {c = coches[i];

}}

}return c;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−int Concesionario :: buscar(const std:: string& m) const {

207

Page 208: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

int i = 0;while ((i < ncoches)&&(m != coches[i]->obtener_modelo ())) {

++i;}if (i == ncoches) {

i = -1;}return i;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Concesionario :: mostrar () const {

cout << "{ ";if (ncoches > 0) {

coches[0]->mostrar ();for (int i = 1; i < ncoches; ++i) {

cout << ", " ;coches[i]->mostrar ();

}}cout << " }" << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �Solución: main.cpp� �

#include <iostream>#include <string>#include "coche.hpp"#include "coche_ocasion.hpp"#include "coche_importado.hpp"#include "concesionario.hpp"using namespace std;using namespace umalcc;

int main(){

bool ok;Concesionario* caux = new Concesionario ();caux->anyadir(new CocheOcasion("Seat -Marbella", 9000, 20), ok);caux->anyadir(new Coche("Seat -Leon", 15000) , ok);caux->anyadir(new CocheImportado("Porsche -911", 39000, 1000) , ok);

Concesionario* concesionario = caux->clone ();delete caux;

cout << "Precio Seat -Marbella: "<< concesionario->calc_precio("Seat -Marbella") << endl;

cout << "Precio Seat -Leon: "<< concesionario->calc_precio("Seat -Leon") << endl;

cout << "Precio Porsche -911: "<< concesionario->calc_precio("Porsche -911") << endl;

Coche* b = concesionario->seleccionar_barato ();

cout << "Mas Barato: ";b->mostrar ();cout << endl;

concesionario->mostrar ();

delete concesionario;}� �

208

Page 209: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Práctica 9: La Clase Vector de la Biblioteca Estándar1. Defina e implemente la clase Hotel (dentro del espacio de nombres umalcc) que defina las siguientes estruc-

turas de datos y proporcione los siguientes métodos públicos para gestionar la ocupación de habitacionesy reservas de un hotel:

Estructura de Datos: La estructura que contendrá los datos de ocupación de las habitaciones se definirámediante un tipo vector de dos dimensiones, donde cada fila almacena los datos de cada planta del hotel,cada planta contiene las habitaciones de esa planta, y donde cada habitación se compone del nombre delcliente (cadena de caracteres) que se encuentra alojado.

Hotel

habitaciones0 1 2 3 4

0 nombre · · · · · · · · · · · ·1 · · · · · · · · · · · · · · ·2 · · · · · · · · · · · · · · ·

Métodos Públicos:

a) Hotel(⇓ n_plantas, ⇓ n_habs):Inicializará la estructura de datos Hotel a un estado vacío, es decir, sin habitaciones ocupadas, de talforma que el vector que representa las habitaciones del hotel se creará con tantas filas como indique elparámetro n_plantas, y tantos elementos por fila como indique el parámetro n_habs.

b) ~Hotel():Liberará y destruirá todos los recursos asociados a la estructura de datos Hotel.

c) Mostrar():Muestra en pantalla toda la información almacenada en las estructuras de datos del Hotel, en un formatoadecuadamente legible.

d) Alojar(⇓ nombre, ⇑ planta, ⇑ n_hab, ⇑ ok):Comprueba si hay habitaciones disponibles, en cuyo caso alojará adecuadamente a dicho cliente en algunahabitación que no esté ocupada. ok tomará el valor true, y planta y n_hab tomarán el valor de la plantay número de habitación donde se alojará el cliente.Cuando se aloja un determinado cliente en una habitación (planta y número de habitación), ésta pasaráa estar ocupada por dicho cliente, almacenando su nombre.Si todas las habitaciones están ocupadas, ok tomará el valor false.

e) Desalojar(⇓ nombre, ⇑ ok):Busca el cliente cuyo nombre se especifica como parámetro, y en caso de encontrarlo en una determinadahabitación, lo desalojará de ella borrando su nombre (a ""), y ok tomará el valor true. En otro caso, oktomará el valor false.

Notas:

a) ⇓ Especifica un parámetro de entrada y ⇑ especifica un parámetro de salida.b) El parámetro nombre es de tipo “cadena de caracteres”.c) El parámetro ok es de tipo “lógico” (“boolean”).d) Los parámetros planta y n_hab representan la planta y número de habitación donde se alojará el cliente

en caso de que la operación haya sido correcta, y se representan mediante números de tipo “entero”.

Solución: hotel.hpp� �#ifndef hotel_hpp_#define hotel_hpp_#include <iostream>#include <string>#include <queue>#include <vector>namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−class Hotel {public:

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−// ~Hote l ( ) {} // Destruccion por de f e c t oHotel(unsigned n_plantas , unsigned n_habs );void Mostrar () const;void Alojar(const std:: string& nombre ,

unsigned& planta , unsigned& n_hab , bool& ok);

209

Page 210: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void Desalojar(const std:: string& nombre , bool& ok);void Anyadir_Planta(bool& ok);void Eliminar_Planta(bool& ok);void Extender_Habitaciones(unsigned n_habs , bool& ok);

private://− t i p o s −−−−−−−−−−−−−−−−−−−−−−typedef std:: vector<std:: string> Fila;typedef std:: vector<Fila> Habitaciones;//− a t r i b u t o s −−−−−−−−−−−−−−−−−−Habitaciones hab;//− metodos 1 −−−−−−−−−−−−−−−−−−void mostrar(const std:: string& h) const;void mostrar_hab () const;void buscar(const std:: string& nombre , unsigned& f, unsigned& c,

bool& ok) const;void buscar_hab_libre(unsigned& f, unsigned& c, bool& ok) const;bool planta_vacia(unsigned f) const;//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

};}#endif� �

Solución: hotel.cpp� �#include "hotel.hpp"#include <iostream>#include <cassert>#include <fstream>using namespace std;using namespace umalcc;

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−namespace umalcc {

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−Hotel :: Hotel(unsigned n_plantas , unsigned n_habs)

: hab(n_plantas , Fila(n_habs , "")) {}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: mostrar(const std:: string& h) const{

if (h == "") {cout << "vacia" << endl;

} else {cout << h << endl;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: mostrar_hab () const{

for (unsigned f = 0; f < hab.size (); ++f) {for (unsigned c = 0; c < hab[f].size (); ++c) {

cout << f << "." << c << ": ";mostrar(hab[f][c]);

}}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: Mostrar () const{

cout << "Habitaciones:" << endl;mostrar_hab ();cout << endl;

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: buscar(const std:: string& nombre , unsigned& f, unsigned& c,

bool& ok) const{

f = 0;c = 0;while ((f < hab.size ())&&(hab[f][c] != nombre )) {

++c;if (c >= hab[f].size ()) {

c = 0;++f;

210

Page 211: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

}}ok = (f < hab.size ());

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: buscar_hab_libre(unsigned& f, unsigned& c, bool& ok) const{

buscar("", f, c, ok);}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: Alojar(const std:: string& nombre ,

unsigned& planta , unsigned& n_hab , bool& ok){

buscar_hab_libre(planta , n_hab , ok);if (ok) {

hab[planta][n_hab] = nombre;}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: Desalojar(const std:: string& nombre , bool& ok){

unsigned f, c;buscar(nombre , f, c, ok);if (ok) {

hab[f][c] = "";}

}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: Anyadir_Planta(bool& ok){

ok = false;if (hab.size() > 0) {

hab.push_back(Fila(hab[hab.size()-1].size(), ""));// Opción a l t e r n a t i v a// Fi l a nueva_planta ( hab [ hab . s i z e ()−1]. s i z e ( ) , "") ;// hab . push_back ( nueva_planta ) ;ok = true;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−bool Hotel:: planta_vacia(unsigned f) const{

unsigned c = 0;while ((c < hab[f].size ())&&(hab[f][c].size() == 0)) {

++c;}return (c >= hab[f].size ());

}void Hotel:: Eliminar_Planta(bool& ok){

ok = false;if ((hab.size() > 1)&&(planta_vacia(hab.size()-1))) {

hab.pop_back ();ok = true;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−void Hotel:: Extender_Habitaciones(unsigned n_habs , bool& ok){

ok = false;if ((hab.size() > 0)&&(hab[0].size() < n_habs )) {

for (unsigned f = 0; f < hab.size (); ++f) {hab[f].resize(n_habs , "");

}ok = true;

}}//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

}� �2. Diseñe un programa que utilice la clase Hotel definida anteriormente y permita gestionar las habitaciones

de un hotel.

211

Page 212: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Solución: main.cpp� �#include <iostream>#include <string>#include <cctype>#include "hotel.hpp"using namespace std;using namespace umalcc;

void leer_num(unsigned& num , const string& msj){

cout << msj ;cin >> num;

}void leer_str(string& str , const string& msj){

cout << msj ;cin >> str;

}void leer_cliente(string& nombre){

leer_str(nombre , "Introduzca el nombre del cliente: ");}void check_ok(bool ok , const string& msj){

if (ok) {cout << "Operacion Correcta. [" << msj << "]" << endl;

} else {cout << "Operacion Erronea. [" << msj << "]" << endl;

}}char menu(){

char op;cout << "X: Fin" << endl;cout << "A: Mostrar Datos Hotel" << endl;cout << "B: Alojar Nuevo Cliente" << endl;cout << "C: Desalojar Cliente" << endl;cout << "D: Añadir Nueva Planta" << endl;cout << "E: Eliminar Última Planta" << endl;cout << "F: Extender Habitaciones por Planta" << endl;do {

cout << endl << " Opcion: ";cin >> op;op = char(toupper(op));

} while (!((op == 'X')||((op >= 'A')&&(op <= 'F'))));cout << endl;return op;

}int main(){

unsigned n_plantas , n_habs;leer_num(n_plantas , "Introduzca el numero de plantas del hotel: ");leer_num(n_habs , "Introduzca el numero de habitaciones por planta: ");Hotel hotel(n_plantas , n_habs );bool ok;string nombre;unsigned planta , n_hab;char op = ' ';do {

op = menu ();switch(op) {case 'A':

hotel.Mostrar ();break;

case 'B':leer_cliente(nombre );hotel.Alojar(nombre , planta , n_hab , ok);check_ok(ok, "Alojar");if (ok) {

cout << " Alojar: " << nombre<< " Planta: " << planta<< " Hab: " << n_hab << endl;

}break;

212

Page 213: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

case 'C':leer_cliente(nombre );hotel.Desalojar(nombre , ok);check_ok(ok, "Desalojar");break;

case 'D':hotel.Anyadir_Planta(ok);check_ok(ok, "Añadir_Planta");break;

case 'E':hotel.Eliminar_Planta(ok);check_ok(ok, "Eliminar_Planta");break;

case 'F':leer_num(n_habs , "Introduzca el nuevo numero de habitaciones por planta: ");hotel.Extender_Habitaciones(n_habs , ok);check_ok(ok, "Extender_Habitaciones");break;

}} while (op != 'X');

}� �3. Añada de forma incremental los siguientes métodos públicos a la clase Hotel realizado anteriormente:

a) Anyadir_Planta(⇑ ok):Si el hotel tiene al menos una planta, entonces añade una nueva planta al hotel actual, acontinuación de las ya existentes, con tantas habitaciones como haya en la última planta, yok tomará el valor true. En otro caso, ok tomará el valor false. Estas nuevas habitacionesse crearán en estado disponible.

b) Eliminar_Planta(⇑ ok):Si el hotel tiene más de una planta, y la última planta tiene todas sus habitaciones en estadodisponible, entonces elimina la última planta del hotel y ok tomará el valor true. En otrocaso, ok tomará el valor false.

c) Extender_Habitaciones(⇓ n_habs, ⇑ ok):Si el hotel tiene al menos una planta, y el numero de habitaciones de la primera planta esmenor que el valor del parámetro n_habs, entonces añade a cada planta tantas habitacionescomo sea necesario para que cada planta tenga el nuevo número de habitaciones especificadopor el valor del parámetro n_habs, y ok tomará el valor true. En otro caso, ok tomará elvalor false. Estas nuevas habitaciones se crearán en estado disponible.

4. Modifique el programa que utiliza la clase Hotel especificado anteriormente para que utilice los nuevosmétodos añadidos anteriormente.

213

Page 214: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Prácticas de Autoevaluación

Gestión de Factoría de AndroidesLa clase Pieza

Defina e implemente en el espacio de nombres umalcc la clase Pieza (en los ficheros pieza.hpp y pieza.cpp),que proporcione los métodos públicos especificados a continuación.

Estructura de datos interna de la claseLa estructura de datos interna de la clase Pieza almacena la información relativa a unadeterminada pieza, compuesta por su código de pieza (de tipo int), y su identificador(de tipo string). El código de la pieza hace referencia al tipo de pieza en concreto,según los códigos representados en la tabla lateral.

cod 2id C-123-4567

Código Descripción0 Cabeza1 Tronco2 Brazo-Izq3 Brazo-Dch4 Pierna-Izq5 Pierna-Dch

Métodos Públicos

~Pieza(); // Destructor

Destruye el objeto, liberando todos los recursos asociados al mismo.

Pieza(); // Constructor por defecto

Inicializa el código del objeto con valor -1 y el identificador con valor vacío ("").

Pieza(const int cod, const std::string& id);

Inicializa el objeto con los valores especificados en los parámetros. El primer parámetro especifica el códigode la pieza, y el segundo parámetro su identificador.

Tanto el constructor de copia como el operador de asignación serán generados por el compilador.

int obtener_codigo() const;

Devuelve el valor del atributo código del objeto actual.

std::string obtener_id() const;

Devuelve el valor del atributo identificador del objeto actual.

bool error() const;

Devuelve true si el valor del atributo código es inválido, o si el valor del atributo identificador es vacío(""). En otro caso, devuelve false.

void mostrar() const;

Muestra en pantalla, según el siguiente formato, la información almacenada en el estado interno del objeto.Si el objeto está en modo erróneo, añadirá la palabra ERROR al final de la línea. Por ejemplo:

2 C-123-4567 7 C-123-4567 ERROR

La clase Androide

Defina e implemente en el espacio de nombres umalcc la clase Androide (en los ficheros androide.hpp yandroide.cpp), que proporcione los métodos públicos especificados a continuación.

Estructura de datos interna de la claseLa estructura de datos interna de la clase Androide almacena la información relativa ala composición de un determinado androide, compuesta por su identificador (de tipostring), y de un array (piezas) de 6 cadenas de caracteres (string), de tal forma queel identificador de cada pieza que compone el androide se almacenará en el índice quese corresponde con el código de la pieza. Por ejemplo, el identificador de la cabeza sealmacenará en la posición 0 del array, el tronco en la posición 1, el brazo izquierdo enla posición 2, y así sucesivamente, según la tabla de códigos especificada en la clasePieza.

id B-987-6734piezas

0 A-251-42451 C-251-96822 C-123-45673 C-123-25634 A-762-82305 C-762-8274

214

Page 215: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Métodos Públicos

~Androide(); // Destructor

Destruye el objeto, liberando todos los recursos asociados al mismo.

Androide(); // Constructor por defecto

Inicializa el identificador del objeto y de las piezas que lo componen con valor vacío ("").

Androide(const std::string& i);

Inicializa el identificador del objeto con el valor especificado en el parámetro, y el identificador de laspiezas que lo componen con valor vacío ("").

Tanto el constructor de copia como el operador de asignación serán generados por el compilador.

std::string obtener_id() const;

Devuelve el valor del atributo identificador del objeto actual.

void anyadir_pieza(const Pieza& p, bool& ok);

Añade la pieza especificada a los componentes del objeto actual en la posición adecuada (indicada por elcódigo de la pieza) y devuelve true en ok si la operación se realiza correctamente. La operación fallará,y devolverá false en ok, si el objeto actual es erróneo, o si la pieza a añadir es errónea, o si ya existe esecomponente en el objeto (el identificador almacenado en la posición indicada por el código no es vacío).

void retirar_pieza(int codigo, Pieza& p);

Retira del objeto actual la pieza cuyo código se especifica como parámetro, y devuelve su valor adecua-damente (código e identificador) en el parámetro de salida p. Si el código es erróneo, o el componenteespecificado no existe, o el objeto actual es erróneo, entonces devolverá una pieza vacía (en modo erróneo).

bool error() const;

Devuelve true si el valor del atributo identificador es vacío (""). En otro caso, devuelve false.

void mostrar() const;

Muestra en pantalla, según el siguiente formato, la información almacenada en el estado interno del objeto.Si el objeto está en modo erróneo, añadirá la palabra ERROR al final de la primera línea.

Androide B-987-67340 A-251-42451 C-251-96822 C-123-45673 C-123-25634 A-762-82305 C-762-8274

Androide ERROR012345

La clase Factoría

Defina e implemente en el espacio de nombres umalcc la clase Factoria (en los ficheros factoria.hpp yfactoria.cpp), que proporcione los métodos públicos especificados a continuación.

Estructura de datos interna de la clase

La estructura de datos interna de la clase Factoria almacena información para facilitar el ensamblaje deandroides utilizando las piezas adecuadas, para ello utiliza las clases Pieza y Androide definidas anteriormente.Así, la clase Factoria contiene un primer atributo, androides, que almacena los androides ya ensamblados enun vector1 de elementos de tipo Androide. Además, tiene un segundo atributo, piezas, que es un puntero anodos que se encuentran organizados como una lista enlazada, donde cada nodo de la lista enlazada contieneun objeto de la clase Pieza. Por ejemplo:

1Si el alumno lo desea, obteniendo menor puntuación, podrá utilizar una estructura de lista de máximo 10 elementos en lugardel tipo vector.

215

Page 216: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Factoria

androides

B-987-6734

A-251-4245C-251-9682C-123-4567C-123-2563A-762-8230C-762-8274

A-765-9823

A-232-8822A-232-8923A-213-1233A-213-9232A-621-9234A-621-9213

D-987-6734

A-251-2312C-213-9213F-912-2139F-912-2138F-912-8923F-912-8213

piezas• - • -

3F-732-2193

• -0

A-823-9332

• -1

A-824-8455

/

2A-213-2372

Métodos Públicos

~Factoria(); // Destructor

Destruye el objeto, liberando todos los recursos asociados al mismo.

Factoria(); // Constructor por defecto

Inicializa el estado interno del objeto con el vector de androides vacío yla lista de piezas vacía.

Factoria(const Factoria& obj); // Constructor de copia

Crea un nuevo objeto copiando (duplicando) el estado del objeto obj recibido como parámetro.

Nótese que NO se debe implementar el operador de asignación.

void mostrar() const;

Androide B-987-67340 A-251-42451 C-251-96822 C-123-45673 C-123-25634 A-762-82305 C-762-8274

Androide A-765-98230 A-232-88221 A-232-89232 A-213-12333 A-213-92324 A-621-92345 A-621-9213

Androide D-987-67340 A-251-23121 C-213-92132 F-912-21393 F-912-21384 F-912-89235 F-912-8213

Piezas3 F-732-21930 A-823-93321 A-824-84552 A-213-2372

Muestra en pantalla, según el formato mostrado en la figura superior, la información del estado internodel objeto (el vector de androides desde el principio, y la lista de piezas según su orden secuencial).

void anyadir_pieza(const int cod, const std::string& id, bool& ok);

Si NO existe en la lista de piezas ninguna pieza con identificador igual al especificado por el parámetroid, entonces crea una pieza con los parámetros especificados, y si la pieza creada NO es errónea, entoncesla inserta al final en la lista de piezas, y asigna true al parámetro ok. En otro caso, asigna false alparámetro ok.

void eliminar_pieza(const std::string& id, bool& ok);

En caso de que exista, elimina de la lista de piezas aquella pieza cuyo identificador sea igual al valor delparámetro id, y asigna true al parámetro ok. En otro caso, asigna false al parámetro ok.

void ensamblar_androide(const std::string& id, bool& ok);

Si NO existe en el sistema ningún androide con identificador igual al especificado por el parámetro id,entonces crea un androide con el identificador especificado, y si el androide creadoNO es erróneo, entonces:

1. Comprueba si hay piezas suficientes de los códigos adecuados para ensamblar un androide.

2. En caso afirmativo del paso anterior:

a) Retira las piezas de los códigos adecuados de la lista de piezas y las añade al androide hastacompletarlo.

b) Inserta el androide ensamblado al final en el vector de androides.c) Finalmente asigna true al parámetro ok.

En el caso de que no se haya podido realizar la operación correctamente, entonces asigna false al pará-metro ok.

void desmontar_androide(const std::string& id, bool& ok);

En caso de que exista, retira las piezas que componen el androide cuyo identificador sea igual al valor delparámetro id, añadiéndolas a la lista de piezas, también elimina del vector de androides aquel androidecuyo identificador sea igual al valor del parámetro id, y asigna true al parámetro ok. En otro caso, asignafalse al parámetro ok.

216

Page 217: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

El programa Principal

Así mismo, el alumno puede utilizar el programa principal que se proporciona (en el fichero main_androides.cppque debe descargarse desde el Campus Virtual) para poder comprobar adecuadamente la corrección de los mé-todos de las clases.

Además, se proporciona un fichero (salida_androides.txt) con la salida esperada para el programa prin-cipal que se suministra, de tal forma que el alumno pueda comprobar su corrección.

217

Page 218: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

Gestión de Tareas PeriódicasLa clase Tarea

Defina e implemente en el espacio de nombres umalcc la clase Tarea (en los ficheros tarea.hpp y tarea.cpp),que proporcione los métodos públicos especificados a continuación.

Estructura de datos interna de la claseLa estructura de datos interna de la clase Tarea almacena la información relativa a unadeterminada tarea periódica del sistema, tal como su identificador (de tipo string), elcódigo de la tarea (de tipo int), el periodo de ejecución (en segundos) de la tarea (detipo int), el límite de tiempo (en segundos) que indica el tiempo en el que finalizarála ejecución de la tarea (de tipo int), la prioridad de la tarea, siendo un número enteromayor o igual a cero, donde el valor cero indica la mayor prioridad (de tipo int), el tiempopróximo de ejecución (en segundos) que indica cuando será ejecutada próximamente latarea (de tipo int) y un determinado valor que representa un número entero (de tipoint).

Tarea

identificadorcódigoperiodolímite

prioridadpróximo

valor

Tarea-0115300102

Métodos Públicos

~Tarea(); // Destructor

Destruye el objeto, liberando todos los recursos asociados al mismo.

Tarea(); // Constructor por defecto

Inicializa el objeto con identificador vacío (""), y con valor cero (0) el resto de atributos.

Tarea(const std::string& id, int cod, int per, int lim, int prio, int prox, int val);

Inicializa el objeto con los valores especificados en los parámetros. Los parámetros están especificados enel mismo orden que los atributos en la figura anterior.

// Tarea(const Tarea& obj); // Constructor de copia// Tarea& operator=(const Tarea& obj); // Operador de asignación

Tanto el constructor de copia como el operador de asignación serán generados por el compilador.

std::string obtener_id() const;

Devuelve el valor del atributo identificador del objeto actual.

int obtener_prioridad() const;

Devuelve el valor del atributo prioridad del objeto actual.

int obtener_proximo() const;

Devuelve el valor del atributo próximo del objeto actual.

bool esta_activa() const;

Devuelve true si el valor del atributo próximo es menor que el valor del atributo límite en el objetoactual. En otro caso, devuelve false.

bool error() const;

Devuelve true si el valor del atributo identificador es vacío (""), o si el valor del atributo código o el valordel atributo periodo es menor o igual a cero. En otro caso, devuelve false.

void mostrar_estado() const;

Muestra en pantalla, según el siguiente formato, la información almacenada en el estado interno del objeto.Además, si la tarea NO está activa, entonces también mostrará dos asteriscos (**) al final de la línea.Para el ejemplo de la figura anterior mostrará:

Tarea-01 1 5 30 0 10 2

void ejecutar(int tiempo_actual);

Si el valor del atributo próximo del objeto es igual al valor del parámetro tiempo_actual, entonces ejecutala tarea actual según lo especificado a continuación:

218

Page 219: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

1. Incrementa el valor del atributo próximo con el valor del atributo periodo.2. Si el valor del parámetro tiempo_actual es menor que el valor del atributo límite, entonces realiza

las siguientes acciones:a) Si el valor del atributo código de la tarea es uno (1), entonces eleva al cuadrado el valor del

atributo valor y almacena el resultado en el atributo valor.b) Si el valor del atributo código de la tarea es dos (2), entonces multiplica por dos el valor del

atributo valor y almacena el resultado en el atributo valor.c) Si el valor del atributo código de la tarea es tres (3), entonces multiplica por tres el valor del

atributo valor y almacena el resultado en el atributo valor.

La clase Planificador

Defina e implemente en el espacio de nombres umalcc la clase Planificador (en los ficheros planificador.hppy planificador.cpp), que proporcione los métodos públicos especificados a continuación.

Estructura de datos interna de la clase

La estructura de datos interna de la clase Planificador almacena información para facilitar la gestión yejecución de tareas periódicas del sistema, para ello utiliza la clase Tarea definida anteriormente. Así, la clasePlanificador contiene un atributo que almacena el valor del tiempo_actual de la ejecución en segundos (detipo int). Además, tiene un segundo atributo, tareas, que es un vector de punteros a nodos que se encuentranorganizados como listas enlazadas ordenadas, donde cada nodo de la lista enlazada contiene un objeto de laclase Tarea.

Cada tarea se encontrará en la lista enlazada que comienza en el elemento del vector cuyo índice es iguala la prioridad de la tarea, y se encontrará ordenada según el valor de su atributo próximo. Por ejemplo:

Planificador

tiempo_actual1

tareas0 • -1 /2 /3 /4 /5 /6 /7 • -

• -Tarea-07· · ·

prio: 0prox: 1

• -Tarea-03· · ·

prio: 0prox: 1

/Tarea-09· · ·

prio: 0prox: 3

• -Tarea-05· · ·

prio: 7prox: 1

/Tarea-02· · ·

prio: 7prox: 4

Métodos Públicos

~Planificador(); // Destructor

Destruye el objeto, liberando todos los recursos asociados al mismo.

Planificador(); // Constructor por defecto

Inicializa el estado interno del objeto con el tiempo_actual a cero (0), y el vector de tareas vacío.

Planificador(const Planificador& obj); // Constructor de copia

Crea un nuevo objeto copiando (duplicando) el estado del objeto obj recibido como parámetro.Nótese que NO se debe implementar el operador de asignación.

void mostrar() const;

Muestra en pantalla, según el siguiente formato, la información del estado interno del objeto (el vector detareas desde el principio, y las listas de tareas según su ordenación). Si alguna lista de tareas está vacía,entonces mostrará el mensaje Vacio. Para el ejemplo de la figura anterior, mostrará:

Tiempo actual: 1Tarea-07 2 7 30 0 1 32Tarea-03 1 3 30 0 1 2Tarea-09 1 5 2 0 3 8 **VacioVacioVacioVacioVacioVacioTarea-05 1 4 30 7 1 4Tarea-02 3 3 2 7 4 2 **

219

Page 220: Programación IIvicente/docencia/docencia/mp_ejercicios...Programación II Relación de Ejercicios y Soluciones UNIVERSIDAD DE MÁLAGA Sonido e Imagen Dpto. Lenguajes y CC. Computación

void anyadir_tarea(const std::string& id, int cod, int per, int lim,int prio, int prox, int val, bool& ok);

Si el valor del parámetro prio es mayor o igual a cero, y el valor del parámetro prox es mayor o igual al valordel atributo tiempo_actual, y NO existe en el sistema una tarea con identificador igual al especificadopor el parámetro id, entonces crea una tarea con los parámetros especificados, y si la tarea creada NO eserrónea, entonces la inserta de forma ordenada (según el valor del parámetro prox ) en la lista de tareascuyo índice es igual al valor del parámetro prio, y asigna true al parámetro ok. En otro caso, asigna falseal parámetro ok.Nota: debe asegurarse de que la lista de tareas con la prioridad especificada ha sido creada adecuadamenteen el vector de tareas.

void eliminar_tarea(const std::string& id, bool& ok);

En caso de que exista, elimina del sistema aquella tarea cuyo identificador sea igual al valor del parámetroid, y asigna true al parámetro ok. En otro caso, asigna false al parámetro ok.Nota: en caso de que los últimos elementos del vector de tareas sean listas vacías, estos elementos deberánser eliminados, de tal forma que el último elemento del vector, si existe, debe ser una lista NO vacía.

bool hay_tareas_activas() const;

Devuelve true si hay tareas activas (véase el método esta_activa() de la clase Tarea) en el sistema, yfalse en otro caso.

void eliminar_tareas_terminadas();

Elimina del sistema todas aquellas tareas que NO están activas (véase el método esta_activa() de laclase Tarea).Nota: en caso de que los últimos elementos del vector de tareas sean listas vacías, estos elementos deberánser eliminados, de tal forma que el último elemento del vector, si existe, debe ser una lista NO vacía.

void ejecutar_ciclo();

Ejecuta las tareas del sistema que están preparadas, según el orden de prioridad del vector de tareas (elíndice cero es el más prioritario), y el orden del tiempo próximo de ejecución de cada tarea. Al finalizar,deberá incrementar en uno (1) el valor del atributo tiempo_actual del objeto.

Así, para cada tarea cuyo tiempo próximo de ejecución es igual al valor del atributo tiempo_actual, seextrae la tarea del principio de la lista enlazada correspondiente, entonces se ejecuta la tarea (invocandoal método ejecutar() de la clase Tarea), y se vuelve a insertar de forma ordenada (según su nuevo tiempopróximo de ejecución) en la lista correspondiente según su prioridad.

El programa Principal

Así mismo, el alumno puede utilizar el programa principal que se proporciona (en el fichero main_tareas.cppque debe descargarse desde el Campus Virtual) para poder comprobar adecuadamente la corrección de losmétodos de las clases.

Además, se proporciona un fichero (salida_tareas.txt) con la salida esperada para el programa principalque se suministra, de tal forma que el alumno pueda comprobar su corrección.

220