Soluciones Color - Universidad de Málaga

Anuncio
Programación II
Relación de Ejercicios
y Soluciones
UNIVERSIDAD DE MÁLAGA
Dpto. Lenguajes y CC. Computación
E.T.S.I. Telecomunicación
Sonido e Imagen
Contenido
Tema 1: Almacenamiento en Memoria Secundaria. Ficheros
Tema 2: Tipos Abstractos de Datos
2
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
83
Tema 5: Colecciones
99
Prácticas de Laboratorio
110
Práctica 1: Almacenamiento Persistente de Datos . . . . . . . . . . . . . . . . . . . . . . . 110
Práctica 2: Tipos Abstractos de Datos (I) . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Práctica 3: Tipos Abstractos de Datos (II) . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Práctica 4: Tipos Abstractos de Datos (III) . . . . . . . . . . . . . . . . . . . . . . . . . . 130
Práctica 5: Gestión de Memoria Dinámica . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Práctica 6: Abstracción en la Gestión de Memoria Dinámica (I) . . . . . . . . . . . . . . . 150
Práctica 7: Abstracción en la Gestión de Memoria Dinámica (II) . . . . . . . . . . . . . . 156
Práctica 8: Introducción a la Programación Orientada a Objetos . . . . . . . . . . . . . . 166
Práctica 9: La Clase Vector de la Biblioteca Estándar . . . . . . . . . . . . . . . . . . . . 197
Prácticas de Autoevaluación
202
Gestión de Factoría de Androides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Gestión de Tareas Periódicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
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
Nota: en la solución a los ejercicios, se ha utilizado el tipo array de TR1, que ha sido incorporado a la biblioteca de C++ en el estándar de 2011. Si su biblioteca estándar no contiene la definición del tipo array, puede
descargarla desde la siguiente dirección: http://www.lcc.uma.es/%7Evicente/docencia/cpplibs/array_tr1.zip
Tema 1: Almacenamiento en Memoria Secundaria. Ficheros
1. 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 c u e n t a de e s t a d i s t i c a s
void 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 s
void 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
}
}
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 texto
de entrada (extensión txt) genere otro fichero de salida encriptado (extensión cod). Esta codificación
consiste 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 recuperar
la 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 a d o r o t a c i o n a l (DESPL) de l e t r a
char 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 ;
}
// d e s c i f r a d o r o t a c i o n a l (DESPL) de l e t r a
char 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 ;
}
// t r a n s f o r m a una l e t r a segun e l c o d i g o de o p e r a c i o n
3
char transformar ( char c , int op )
{
char res ;
if ( op = = CIFRAR ) {
res = cifrar ( c );
} else {
res = descifrar ( c );
}
return res ;
}
// t r a s n f o r m a e l f i c h e r o de e n t r a d a 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 a
void t r a n s f o r m a r _ f i c h e r o ( 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 ();
}
}
// b u s c a un c a r a c t e r e una cadena
unsigned buscar ( const string & nombre , char c )
{
unsigned i = 0;
while (( i < nombre . size ()) & & ( c ! = nombre [ i ] )) {
++i;
}
return i ;
}
// d e v u e l v e l a e x t e n s i o n d e l nombre de f i c h e r o
string 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 ;
}
// c a l c u l a l a o p e r a c i o n a r e a l i z a r a p a r t i r de l a s e x t e n s i o n e s de l o s
// f i c h e r o s de e n t r a d a y s a l i d a
int 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
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 ) {
t r a n s f o r m a r _ f i c h e r o ( 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 programa
debe crear un fichero de texto (cuyo nombre se leerá por teclado) en el que se guarde la información de
un número indeterminado de personas. La información que se guardará por cada persona será:
Nombre:
Edad
Género
Arte
Deporte
Libros
Música
Cadena de caracteres.
int.
char (M/F).
char (S/N).
char (S/N).
char (S/N).
char (S/N).
La información correspondiente a cada persona se leerá del teclado. El proceso finalizará cuando se teclee
un 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 ;
};
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// c o n v i e r t e una l e t r a a mayusculas
inline char mayuscula ( char c )
{
if ( c > = 'a ' & & c < = 'z ') {
c = char ( c - 'a ' + 'A ' );
}
return c ;
5
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Leer de Teclado −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e r una o p c i o n (S/N) a b o o l
inline void leer ( bool & a )
{
char c ;
cin > > c ;
a = ( mayuscula ( c ) = = 'S ' );
}
// l e e r e l g e n e r o (M/F) a c h a r
inline 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 o n e s
void leer ( Aficciones & af )
{
for ( unsigned i = 0; i < af . size (); + + i ) {
cout < < AFICCIONES [ i ] < < " ( S/N ): " ;
leer ( af [ i ] );
}
}
// l e e r d a t o s de p e r s o n a
void 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 ' );
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− E s c r i b i r a F i c h e r o −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// e s c r i b i r una o p c i o n (S/N) b o o l a f i c h e r o
inline void escribir ( ofstream & fich , bool a )
{
if ( a ) {
fich < < 'S ';
} else {
fich < < 'N ';
}
}
// e s c r i b i r e l g e n e r o (M/F) c h a r a f i c h e r o
inline void es c ri bi r _g en e ro ( ofstream & fich , char g )
{
if ( g = = MASCULINO ) {
fich < < MASCULINO ;
} else {
fich < < FEMENINO ;
}
}
// e s c r i b i r una p e r s o n a a f i c h e r o
void escribir ( ofstream & fich , const Persona & p )
{
fich < < p . nombre < < endl ;
6
}
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 como
resultado un fichero (cuyo nombre será leído desde teclado) con toda la información correspondiente a los
candidatos aceptados. Una persona del fichero de entrada se considerará aceptable como candidato si tiene
diferente 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
};
char gen ;
Aficciones af ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// c o n v i e r t e una l e t r a a mayusculas
inline char mayuscula ( char c )
{
if ( c > = 'a ' & & c < = 'z ') {
c = char ( c - 'a ' + 'A ' );
}
return c ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Leer de Teclado −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e r una o p c i o n (S/N) a b o o l
inline void leer ( bool & a )
{
char c ;
cin > > c ;
a = ( mayuscula ( c ) = = 'S ' );
}
// l e e r e l g e n e r o (M/F) a c h a r
inline 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 o n e s
void leer ( Aficciones & af )
{
for ( unsigned i = 0; i < af . size (); + + i ) {
cout < < AFICCIONES [ i ] < < " ( S/N ): " ;
leer ( af [ i ] );
}
}
// l e e r d a t o s de p e r s o n a
void 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 F i c h e r o −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e r una o p c i o n (S/N) a b o o l
inline void leer ( ifstream & in , bool & a )
{
char c ;
in > > c ;
a = ( mayuscula ( c ) = = 'S ' );
}
// l e e r e l g e n e r o (M/F) a c h a r
inline void leer_genero ( ifstream & in , char & g )
{
8
}
char c ;
in > > c ;
if ( mayuscula ( c ) = = MASCULINO ) {
g = MASCULINO ;
} else {
g = FEMENINO ;
}
// l e e r d a t o s de p e r s o n a
void 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 ' );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− E s c r i b i r a F i c h e r o −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// e s c r i b i r una o p c i o n (S/N) b o o l a f i c h e r o
inline void escribir ( ofstream & fich , bool a )
{
if ( a ) {
fich < < 'S ';
} else {
fich < < 'N ';
}
}
// e s c r i b i r e l g e n e r o (M/F) c h a r a f i c h e r o
inline void es c ri bi r _g en e ro ( ofstream & fich , char g )
{
if ( g = = MASCULINO ) {
fich < < MASCULINO ;
} else {
fich < < FEMENINO ;
}
}
// e s c r i b i t una p e r s o n a a f i c h e r o
void 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 p e r s o n a s son c o m p a t i b l e s s i s u s a f i c c i o n e s comunes s u p e r a n un
// d e t e r m i n a d o umbral
bool 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 p r o c e s a r _ f i c h e r o ( 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
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) {
p r o c e s a r _ f i c h e r o ( 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
Nombre del artículo
Existencias
Precio
Numérico
Cadena de caracteres
Numérico
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 d e s d e e l t e c l a d o
void leer ( Articulo & a )
{
cout < < " Codigo de articulo : " ;
cin > > a . codigo ;
if ( a . codigo ! = 0) {
10
}
}
cout < < " Nombre de articulo : " ;
cin > > ws ;
// s a l t a s e p a r a d o r e s d e l c o d i g o de a r t i c u l o
getline ( 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 o
void 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 o
void 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 se
cumple 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
const
const
const
const
const
int
int
int
int
int
int
MENOR = 0;
MENIG = 1;
MAYOR = 2;
MAYIG = 3;
IGUAL = 4;
DISTINTO = 5;
11
struct Condicion {
int campo ;
int cmp ;
unsigned num ;
};
struct Articulo {
unsigned codigo ;
string nombre ;
unsigned existencias ;
unsigned precio ;
};
// c o n v i e r t e a mayusculas
inline 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 comparacion
inline 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 c o d i g o de comparacion
inline 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 c o n d i c i o n de p r o c e s a m i e n t o ( 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
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Leer de F i c h e r o −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e un a r t i c u l o de f i c h e r o
void leer ( ifstream & in , Articulo & a )
{
in > > a . codigo ;
in > > ws ;
getline ( in , a . nombre );
in > > a . existencias ;
in > > a . precio ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− E s c r i b i r a F i c h e r o −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// e s c r i b e a r t i c u l o a f i c h e r o
void 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 e s c o m p a t i b l e con l a c o n d i c i o n de comparacion
bool 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 o t r o f i c h e r o a q u e l l o s que son
// c o m p a t i b l e s con un c o d i g o de comparacion
void p r o c e s a r _ f i c h e r o ( 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
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 ) {
p r o c e s a r _ f i c h e r o ( nombre_ent , nombre_sal , c , ok );
if ( ok ) {
cout < < " Procesamiento correcto " < < endl ;
} else {
cout < < " Error al procesar el fichero " < < endl ;
}
}
}
14
Tema 2: Tipos Abstractos de Datos
Tema 2.1: Programacion Modular
Diseñ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ódulo
deberá definir el tipo Complejo, así como los siguientes subprogramas:
Solución: complejos.hpp
# ifndef com plejos _hpp_
# define com plejos _hpp_
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
const double E R RO R _P RE C IS IO N = 1 e - 6 ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
struct Complejo {
double real ; // p a r t e r e a l d e l numero c o m p l e j o
double imag ; // p a r t e i m a g i n a r i a d e l numero c o m p l e j o
} ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void sumar ( Complejo & r , const Complejo & a , const Complejo & b ) ;
// D e v u e l v e un numero c o m p l e j o ( r ) que c o n t i e n e e l r e s u l t a d o de
// sumar l o s numeros c o m p l e j o s ( a ) y ( b ) .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void restar ( Complejo & r , const Complejo & a , const Complejo & b ) ;
// D e v u e l v e un numero c o m p l e j o ( r ) que c o n t i e n e e l r e s u l t a d o de
// r e s t a r l o s numeros c o m p l e j o s ( a ) y ( b ) .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void multiplicar ( Complejo & r , const Complejo & a , const Complejo & b ) ;
// D e v u e l v e un numero c o m p l e j o ( r ) que c o n t i e n e e l r e s u l t a d o de
// m u l t i p l i c a r l o s numeros c o m p l e j o s ( a ) y ( b ) .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void dividir ( Complejo & r , const Complejo & a , const Complejo & b ) ;
// D e v u e l v e un numero c o m p l e j o ( r ) que c o n t i e n e e l r e s u l t a d o de
// d i v i d i r l o s numeros c o m p l e j o s ( a ) y ( b ) .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool iguales ( const Complejo & a , const Complejo & b ) ;
// D e v u e l v e t r u e s i l o s numeros c o m p l e j o s ( a ) y ( b ) son i g u a l e s .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void escribir ( const Complejo & a ) ;
// muestra en p a n t a l l a e l numero c o m p l e j o ( a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void leer ( Complejo & a ) ;
// l e e de t e c l a d o e l v a l o r d e l numero c o m p l e j o ( a ) .
// l e e l a p a r t e r e a l y l a p a r t e i m a g i n a r i a d e l numero
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
# endif
Solución: complejos.cpp
# include " complejos . hpp "
# include < iostream >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Subprogramas A u x i l i a r e s −−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// cuadrado de un numero ( a ^2)
inline double sq ( double a )
{
15
return a * a ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Valor a b s o l u t o de un numero
inline 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 a n c i a que l o s
// s e p a r a e s l o s u f i c i e n t e m e n t e pequenya
inline bool iguales ( double a , double b )
{
return abs ( a - b ) < = ER RO R _P RE C IS IO N ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Implementación −−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un numero c o m p l e j o ( r ) que c o n t i e n e e l r e s u l t a d o de
// sumar l o s numeros c o m p l e j o s ( 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un numero c o m p l e j o ( r ) que c o n t i e n e e l r e s u l t a d o de
// r e s t a r l o s numeros c o m p l e j o s ( 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un numero c o m p l e j o ( r ) que c o n t i e n e e l r e s u l t a d o de
// m u l t i p l i c a r l o s numeros c o m p l e j o s ( 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un numero c o m p l e j o ( r ) que c o n t i e n e e l r e s u l t a d o de
// d i v i d i r l o s numeros c o m p l e j o s ( 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 ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e t r u e s i l o s numeros c o m p l e j o s ( 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
}
// muestra en p a n t a l l a e l numero c o m p l e j o ( a )
void escribir ( const Complejo & a )
{
cout < < " { " < < a . real < < " , " < < a . imag < < " } " ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e de t e c l a d o e l v a l o r d e l numero c o m p l e j o ( a ) .
// l e e l a p a r t e r e a l y l a p a r t e i m a g i n a r i a d e l numero
void 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 d e l e s p a c i o de nombres uamalcc
// para e v i t a r c o l i s i ó n en i n v o c a c i ó n a subprograma
// l e e r ( Complejo& c ) d e l e s p a c i o de nombres umalcc
umalcc :: 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
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 d e l e s p a c i o de nombres g l o b a l
// para e v i t a r c o l i s i ó n en i n v o c a c i ó n a l subprograma
// l e e r ( Complejo& c ) d e l e s p a c i o 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 siguientes
consideraciones:
Los números racionales se representan mediante fracciones, donde tanto el numerador como denominador 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 mediante
el cálculo del máximo común divisor (m.c.d.) del numerador y el denominador y su posterior
división por dicho m.c.d.
Para calcular el máximo común divisor de dos numeros enteros positivos n y m, el algoritmo de
Euclides 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 ahora
el valor de r (el resto de la división entera entre n y m calculado anteriormente), y se repite este
proceso 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 ambos
números.
• Para simplificar la determinación del signo de la fracción puede asumirse que el denominador de
la fracción es siempre positivo (por lo que una fracción de signo negativo tendrá un numerador
de signo negativo y un denominador de signo positivo).
El número cero se guardará siempre en su forma canónica 0/1.
18
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 ra ci o na le s _h pp _
# define ra ci o na le s _h pp _
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
struct Racional {
int num ;
// numerador
int denom ; // denominador
};
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void sumar ( Racional & r , const Racional & r1 , const Racional & r2 );
// Asigna a l número r a c i o n a l ( r ) e l r e s u l t a d o de
// sumar l o s números r a c i o n a l e s ( r1 ) y ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void restar ( Racional & r , const Racional & r1 , const Racional & r2 );
// Asigna a l número r a c i o n a l ( r ) e l r e s u l t a d o de
// r e s t a r l o s números r a c i o n a l e s ( r1 ) y ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void multiplicar ( Racional & r , const Racional & r1 , const Racional & r2 );
// Asigna a l número r a c i o n a l ( r ) e l r e s u l t a d o de
// m u l t i p l i c a r l o s números r a c i o n a l e s ( r1 ) y ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void dividir ( Racional & r , const Racional & r1 , const Racional & r2 );
// Asigna a l número r a c i o n a l ( r ) e l r e s u l t a d o de
// d i v i d i r l o s números r a c i o n a l e s ( r1 ) y ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void escribir ( const Racional & r );
// Muestra en p a n t a l l a e l v a l o r d e l número r a c i o n a l ( r )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void leer ( Racional & r );
// Lee de t e c l a d o e l v a l o r d e l número r a c i o n a l ( r )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool igual ( const Racional & r1 , const Racional & r2 );
// D e v u e l v e t r u e s i e l número r a c i o n a l ( r1 ) e s i g u a l a ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool menor ( const Racional & r1 , const Racional & r2 );
// D e v u e l v e t r u e s i e l número r a c i o n a l ( r1 ) e s menor que ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
# endif
Solución: racionales.cpp
# include " racionales . hpp "
# include < iostream >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Subprogramas A u x i l i a r e s −−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// v a l o r a b s o l u t o de un numero e n t e r o
inline int abs ( int x )
{
if ( x < 0) {
x = -x;
}
return x ;
}
19
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// maximo comun d i v i s o r . a l g o r i t m o de e u c l i d e s
int 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 m u l t i p l o
// i n l i n e i n t mcm( i n t a , i n t b )
// {
// a = a b s ( a ) ;
// b = a b s ( b ) ;
// r e t u r n ( a / mcd( a , b ) ) ∗ b ;
// }
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// n o r m a l i z a r un numero r a c i o n a l
void normalizar ( Racional & r )
{
if ( r . denom = = 0) {
// Error denominador c e r o
r . num = 0;
r . denom = 0;
} else if ( r . num = = 0) {
// Forma c a n o n i c a
r . num = 0;
r . denom = 1;
} else {
// d i v i d i r numerador y denominador por MCD
int max_com_div = mcd ( r . num , r . denom );
r . num / = max_com_div ;
r . denom / = max_com_div ;
// s i denominador n e g a t i v o , e n t o n c e s cambiar s i g n o
if ( r . denom < 0) {
r . num = - r . num ;
r . denom = - r . denom ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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
// −−−− − −−−− == −−−−−−− − −−−−−−− == −−−−−−−−−−−−−−−−−
// 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 e s t a n n o r m a l i z a d o s
return ( 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
# 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 m u l t i p l i c a c i o n / d i v i s i o n " < < 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 pol inomio _hpp_
# define pol inomio _hpp_
# include < iostream >
# include < array >
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
const double E R RO R _P RE C IS IO N = 1 e - 6;
const unsigned MAX = 100;
typedef std :: array < double , MAX > Datos ;
struct Polinomio {
unsigned mg ; // maximo g rado d e l p o l i n o m i o
Datos coef ; // c o e f i c i e n t e s d e l p o l i n o m i o ( i n d i c e e s e l exp . de l a X)
};
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
double evaluar ( const Polinomio & a , double x );
22
// D e v u e l v e e l r e s u l t a d o de e v a l u a r e l p o l i n o m i o ( a )
// para un v a l o r de ( x ) e s p e c i f i c a d o como parametro
void derivar ( Polinomio & r , const Polinomio & a );
// D e v u e l v e un p o l i n o m i o ( r ) que c o n t i e n e e l r e s u l t a d o de
// c a l c u l a r l a d e r i v a d a d e l p o l i n o m i o ( a )
void sumar ( Polinomio & r , const Polinomio & a , const Polinomio & b );
// D e v u e l v e un p o l i n o m i o ( r ) que c o n t i e n e e l r e s u l t a d o de
// sumar l o s p o l i n o m i o s ( a ) y ( b )
void escribir ( const Polinomio & a ) ;
// Muestra en p a n t a l l a e l c o n t e n i d o d e l p o l i n o m i o ( a )
void leer ( Polinomio & a ) ;
// Lee de t e c l a d o e l v a l o r d e l p o l i n o m i o ( a )
// Lee p a r e s de c o e f i c i e n t e y gr ado h a s t a que e l c o e f i c i e n t e s e a c e r o
}
# endif
Solución: polinomios.cpp
# include " polinomios . hpp "
# include < iostream >
# include < cassert >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−
// Subprogramas A u x i l i a r e s
//−−−−−−−−−−−−−−−−−−−−−−−−−
// Valor a b s o l u t o de un numero
inline 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 a n c i a que l o s
// s e p a r a e s l o s u f i c i e n t e m e n t e pequenya
inline bool iguales ( double a , double b ) {
return abs ( a - b ) < = ER RO R _P RE C IS IO N ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−
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;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
double evaluar ( const Polinomio & a , double x )
{
// D e v u e l v e e l r e s u l t a d o de e v a l u a r e l p o l i n o m i o ( a )
// para un v a l o r de ( x ) e s p e c i f i c a d o como parametro
double res = 0;
for ( unsigned i = 0; i < = a . mg ; + + i ) {
res + = a . coef [ i ] * potencia (x , i );
}
23
}
return res ;
}
void derivar ( Polinomio & r , const Polinomio & a )
{
assert ( & r ! = & a );
// D e v u e l v e un p o l i n o m i o ( r ) que c o n t i e n e e l r e s u l t a d o de
// c a l c u l a r l a d e r i v a d a d e l p o l i n o m i o ( 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 ));
// D e v u e l v e un p o l i n o m i o ( r ) que c o n t i e n e e l r e s u l t a d o de
// sumar l o s p o l i n o m i o s ( 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 p a n t a l l a e l c o n t e n i d o d e l p o l i n o m i o ( 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 a d o e l v a l o r d e l p o l i n o m i o ( a )
// Lee p a r e s de c o e f i c i e n t e y gr ado h a s t a que e l c o e f i c i e n t e s e a c e r o
inicializar ( 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
}
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 de
utilización que permitan comprobar su funcionamiento.
1. TAD número complejo que defina los siguientes métodos públicos:
Solución: complejo.hpp
# ifndef com plejos _hpp_
# define com plejos _hpp_
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
const double E R RO R _P RE C IS IO N = 1 e - 6 ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
class Complejo {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Métodos P ú b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Complejo () ;
// C o n s t r u c t o r por D e f e c t o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
double parte_real () const ;
// d e v u e l v e l a p a r t e r e a l d e l numero c o m p l e j o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
double parte_imag () const ;
// d e v u e l v e l a p a r t e i m a g i n a r i a d e l numero c o m p l e j o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void sumar ( const Complejo & a , const Complejo & b ) ;
// a s i g n a a l numero c o m p l e j o ( a c t u a l ) e l r e s u l t a d o de
// sumar l o s numeros c o m p l e j o s ( a ) y ( b ) .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void restar ( const Complejo & a , const Complejo & b ) ;
// a s i g n a a l numero c o m p l e j o ( a c t u a l ) e l r e s u l t a d o de
// r e s t a r l o s numeros c o m p l e j o s ( a ) y ( b ) .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void multiplicar ( const Complejo & a , const Complejo & b ) ;
// a s i g n a a l numero c o m p l e j o ( a c t u a l ) e l r e s u l t a d o de
// m u l t i p l i c a r l o s numeros c o m p l e j o s ( a ) y ( b ) .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void dividir ( const Complejo & a , const Complejo & b ) ;
// a s i g n a a l numero c o m p l e j o ( a c t u a l ) e l r e s u l t a d o de
// d i v i d i r l o s numeros c o m p l e j o s ( a ) y ( b ) .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool igual ( const Complejo & b ) const ;
// D e v u e l v e t r u e s i e l numero c o m p l e j o ( a c t u a l ) e s
// i g u a l a l numero c o m p l e j o ( b )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void escribir () const ;
// muestra en p a n t a l l a e l numero c o m p l e j o ( a c t u a l )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void leer () ;
// l e e de t e c l a d o e l v a l o r d e l numero c o m p l e j o ( a c t u a l ) .
// l e e l a p a r t e r e a l y l a p a r t e i m a g i n a r i a d e l numero
25
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
double real ; // p a r t e r e a l d e l numero c o m p l e j o
double imag ; // p a r t e i m a g i n a r i a d e l numero c o m p l e j o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
} ;
}
# endif
Solución: complejo.cpp
# include " complejos . hpp "
# include < iostream >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Subprogramas A u x i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// cuadrado de un numero ( a ^2)
inline double sq ( double a )
{
return a * a ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−
// Valor a b s o l u t o de un numero
inline 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 a n c i a que l o s
// s e p a r a e s l o s u f i c i e n t e m e n t e pequenya
inline bool iguales ( double a , double b )
{
return abs ( a - b ) < = ER RO R _P RE C IS IO N ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Métodos P ú b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Complejo :: Complejo ()
// C o n s t r u c t o r por D e f e c t o
: real (0.0) , imag (0.0) {}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d e v u e l v e l a p a r t e r e a l d e l numero c o m p l e j o
double Complejo :: parte_real () const
{
return real ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d e v u e l v e l a p a r t e i m a g i n a r i a d e l numero c o m p l e j o
double Complejo :: parte_imag () const
{
return imag ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// a s i g n a a l numero c o m p l e j o ( a c t u a l ) e l r e s u l t a d o de
// sumar l o s numeros c o m p l e j o s ( a ) y ( b ) .
void Complejo :: sumar ( const Complejo & a , const Complejo & b )
{
real = a . real + b . real ;
26
}
imag = a . imag + b . imag ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// a s i g n a a l numero c o m p l e j o ( a c t u a l ) e l r e s u l t a d o de
// r e s t a r l o s numeros c o m p l e j o s ( a ) y ( b ) .
void Complejo :: restar ( const Complejo & a , const Complejo & b )
{
real = a . real - b . real ;
imag = a . imag - b . imag ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// a s i g n a a l numero c o m p l e j o ( a c t u a l ) e l r e s u l t a d o de
// m u l t i p l i c a r l o s numeros c o m p l e j o s ( 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// a s i g n a a l numero c o m p l e j o ( a c t u a l ) e l r e s u l t a d o de
// d i v i d i r l o s numeros c o m p l e j o s ( 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 ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e t r u e s i e l numero c o m p l e j o ( a c t u a l ) e s
// i g u a l a l numero c o m p l e j o ( b )
bool Complejo :: igual ( const Complejo & b ) const
{
return iguales ( real , b . real ) & & iguales ( imag , b . imag ) ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// muestra en p a n t a l l a e l numero c o m p l e j o ( a c t u a l )
void Complejo :: escribir () const
{
cout < < " { " < < real < < " , " < < imag < < " } " ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e de t e c l a d o e l v a l o r d e l numero c o m p l e j o ( a c t u a l ) .
// l e e l a p a r t e r e a l y l a p a r t e i m a g i n a r i a d e l numero
void 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
{
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
}
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 po li n om io s _h pp _
# define po li n om io s _h pp _
# include < array >
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
const double E R RO R _P RE C IS IO N = 1 e - 6;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
class Polinomio {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e f i n i d o s automaticamente por e l c o m p i l a d o r
//−−−−−−−−−−−−−−−−−−−−−−−−−
//~Polinomio ( ) ;
// Polinomio ( c o n s t Polinomio& p ) ;
// Polinomio& o p e r a t o r =( c o n s t Polinomio& p ) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Polinomio ();
unsigned max_grado () const ;
// D e v u e l v e e l mayor grado d e l p o l i n o m i o a c t u a l
// cuyo c o e f i c i e n t e e s d i s t i n t o de c e r o
void poner ( unsigned e , double c );
// Asigna e l c o e f i c i e n t e ( c ) a l t e r m i n o de grad o ( e )
// d e l p o l i n o m i o a c t u a l
double obtener ( unsigned e ) const ;
// D e v u e l v e e l c o e f i c i e n t e c o r r e s p o n d i e n t e a l
// t e r m i n o de grado ( e ) d e l p o l i n o m i o a c t u a l
double evaluar ( double x ) const ;
// D e v u e l v e e l r e s u l t a d o de e v a l u a r e l p o l i n o m i o a c t u a l
// para un v a l o r de ( x ) e s p e c i f i c a d o como parametro
void derivar ( const Polinomio & a );
// Asigna a l p o l i n o m i o a c t u a l e l r e s u l t a d o de
// c a l c u l a r l a d e r i v a d a d e l p o l i n o m i o ( a )
void sumar ( const Polinomio & a , const Polinomio & b );
// Asigna a l p o l i n o m i o a c t u a l e l r e s u l t a d o de
// sumar l o s p o l i n o m i o s ( a ) y ( b )
void escribir () const ;
// Muestra en p a n t a l l a e l c o n t e n i d o d e l p o l i n o m i o a c t u a l
void leer ();
// Lee de t e c l a d o e l v a l o r d e l p o l i n o m i o a c t u a l
// Lee p a r e s de c o e f i c i e n t e y gr ado h a s t a que e l c o e f i c i e n t e s e a c e r o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Ctes y Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
static const unsigned MAX = 100;
typedef std :: array < double , MAX > Datos ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void inicializar ();
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned mg ; // maximo g rado d e l p o l i n o m i o
Datos coef ; // c o e f i c i e n t e s d e l p o l i n o m i o ( i n d i c e e s e l exp de l a X)
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
};
}
29
# endif
Solución: polinomios.cpp
# include " polinomios . hpp "
# include < iostream >
# include < cassert >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Subprogramas A u x i l i a r e s −−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Valor a b s o l u t o de un numero
inline 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 a n c i a que l o s
// s e p a r a e s l o s u f i c i e n t e m e n t e pequenya
inline bool iguales ( double a , double b ) {
return abs ( a - b ) < = ER RO R _P RE C IS IO N ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−
double potencia ( double base , unsigned exp )
{
double res = 1;
for ( unsigned i = 0; i < exp ; + + i ) {
res * = base ;
}
return res ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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
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 de
números enteros que defina los siguientes métodos públicos:
Solución: conjuntos.hpp
# ifndef con juntos _hpp_
# define con juntos _hpp_
# include < iostream >
# include < array >
namespace umalcc {
class Conjunto {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Generados automaticamente por e l c o m p i l a d o r
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//~Conjunto ( ) ;
// Conjunto ( c o n s t Conjunto& c ) ;
// Conjunto& o p e r a t o r =( c o n s t Conjunto& c ) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Conjunto ();
// C o n s t r u c t o r por D e f e c t o : c o n j u n t o v a c i o
void clear ();
// Elimina t o d o s l o s e l e m e n t o s d e l c o n j u n t o a c t u a l ( queda v a c i o )
bool es_vacio () const ;
// D e v u e l v e t r u e s i e l c o n j u n t o a c t u a l e s t a v a c i o
void incluir ( int e );
// I n c l u y e e l e l e m e n t o ( e ) en e l c o n j u n t o a c t u a l
void eliminar ( int e );
// Elimina e l e l e m e n t o ( e ) d e l c o n j u n t o a c t u a l
bool pertenece ( int e ) const ;
// D e v u e l v e t r u e s i e l e l e m e n t o ( e ) p e r t e n e c e a l c o n j u n t o a c t u a l
bool e s_subc onjunt o ( const Conjunto & a ) const ;
// D e v u e l v e t r u e s i e l c o n j u n t o a c t u a l e s s u b c o n j u n t o d e l c o n j u n t o ( a )
void union_conj ( const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o a c t u a l e l r e s u l t a d o de
// l a union de l o s c o n j u n t o s ( a ) y ( b )
void interseccion ( const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o a c t u a l e l r e s u l t a d o de
// l a i n t e r s e c c i o n de l o s c o n j u n t o s ( a ) y ( b )
32
void diferencia ( const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o a c t u a l e l r e s u l t a d o de
// l a d i f e r e n c i a de l o s c o n j u n t o s ( a ) y ( b )
void d i f e r e n c i a _ s i m e t r i c a ( const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o a c t u a l e l r e s u l t a d o de
// l a d i f e r e n c i a s i m e t r i c a de l o s c o n j u n t o s ( a ) y ( b )
void escribir () const ;
// Muestra en p a n t a l l a e l c o n t e n i d o d e l c o n j u n t o a c t u a l
void leer ();
// Lee de t e c l a d o e l v a l o r d e l c o n j u n t o a c t u a l ,
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Ctes y Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
static const unsigned MAX = 100;
typedef std :: array < int , MAX > Datos ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void anyadir ( int e ) ;
void quitar ( unsigned i ) ;
unsigned buscar ( int e ) const ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned sz ;
// numero de e l e m e n t o s d e l c o n j u n t o
Datos dat ;
// componentes d e l c o n j u n t o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
};
}
# endif
Solución: conjuntos.cpp
# include " conjuntos . hpp "
# include < iostream >
# include < array >
# include < cassert >
using namespace std ;
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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_s ubconj unto ( const Conjunto & a ) const
33
{
// e s s u b c o n j u n t o s i t o d o s l o s e l e m e n t o s d e l c o n j u n t o a c t u a l
// p e r t e n e c e n tambien a l c o n j u n t o e s p e c i f i c a d o como parametro
unsigned 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 :: d i f e r e n c i a _ s i m e t r i c a ( 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 P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
34
}
void Conjunto :: anyadir ( int e ) {
if ( sz < dat . size ()) {
dat [ sz ] = e ;
+ + sz ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Conjunto :: quitar ( unsigned i ) {
// Elimina un e l e m e n t o a s i g n a n d o e l u l t i m o e l e m e n t o a l a
// p o s i c i o n e s p e c i f i c a d a
if ( 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 . e s_subc onjunt o ( 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 . d i f e r e n c i a _ s i m e t r i c a ( 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
# include < array >
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
const double E R RO R _P RE C IS IO N = 1 e - 6;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
class Matriz {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e f i n i d o s automaticamente por e l c o m p i l a d o r
//−−−−−−−−−−−−−−−−−−−−−−−−−
//~M a t r i z ( ) ;
// M a t r i z ( c o n s t M a t r i z& m) ;
// M a t r i z& o p e r a t o r =( c o n s t M a t r i z& m) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matriz () ;
// C o n s t r u c t o r por D e f e c t o : m a t r i z v a c i a
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matriz ( unsigned nf , unsigned nc );
// C o n s t r u c t o r e s p e c i f i c o : c r e a m a t r i z de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned nfils () const ;
// D e v u e l v e e l numero de f i l a s de l a m a t r i z a c t u a l
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned ncols () const ;
// D e v u e l v e e l numero de columnas de l a m a t r i z a c t u a l
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void clear ( unsigned nf , unsigned nc );
// Elimina t o d o s l o s e l e m e n t o s de l a m a t r i z a c t u a l , y a s i g n a
// a l a m a t r i z a c t u a l una m a t r i z de ( n f i l s ) x ( n c o l s ) con v a 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 < n c o l s ( ) )
// Asigna e l v a l o r ( v a l ) a l e l e m e n t o de l a f i l a ( f )
// y columna ( c ) de l a m a t r i z a c t u a l
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
double obtener ( unsigned f , unsigned c ) const ;
// PRECOND: ( f < n f i l s ( ) && c < n c o l s ( ) )
// D e v u e l v e e l v a l o r d e l e l e m e n t o de l a f i l a ( f )
// y columna ( c ) de l a m a t r i z a c t u a l
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void sumar ( const Matriz & m1 , const Matriz & m2 );
// Asigna a l a m a t r i z a c t u a l e l r e s u l t a d o de
// sumar l a s m a t r i c e s ( a ) y ( b )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void restar ( const Matriz & m1 , const Matriz & m2 );
// Asigna a l a m a t r i z a c t u a l e l r e s u l t a d o de
// r e s t a r l a s m a t r i c e s ( a ) y ( b )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void multiplicar ( const Matriz & m1 , const Matriz & m2 );
// Asigna a l a m a t r i z a c t u a l e l r e s u l t a d o de
// m u l t i p l i c a r l a s m a t r i c e s ( a ) y ( b )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void escribir () const ;
// Muestra en p a n t a l l a e l c o n t e n i d o de l a m a t r i z a c t u a l
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void leer ();
// Lee de t e c l a d o e l v a l o r de l a m a t r i z a c t u a l ,
// Lee n f i l s , n c o l s y l o s v a l o r e s de l o s e l e m e n t o s
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Ctes y Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
static const unsigned MAX = 10;
typedef std :: array < double , MAX > Fila ;
typedef std :: array < Fila , MAX > Datos ; // m a t r i z maxima de 10 x10
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned nfilas ;
unsigned ncolumnas ;
Datos dat ;
36
};
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
# endif
Solución: matriz.cpp
# include " matriz . hpp "
# include < iostream >
# include < iomanip >
# include < cassert >
using namespace std ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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
{
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 columnas
if (( 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
}
}
}
cin > > x ; // l e e cada e l e m e n t o de l a m a t r i z
poner (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 < < " Multip licaci on : " < < 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 acceder
a cada elemento por la posición donde se encuentra. Así mismo, también es posible insertar y eliminar
elementos de la secuencia en la posición indicada, manteniendo el mismo orden posicional de los elementos
en 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 c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// ~ L i s t a I n t ( ) ;
// D e s t r u c t o r Automático
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
ListaInt () ;
ListaInt ( const ListaInt & o ) ;
ListaInt & operator = ( const ListaInt & o ) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool llena () const ;
// D e v u e l v e t r u e s i e l numero de e l e m e n t o s almacenados
// a l c a n z a l a c a p a c i d a d maxima de almacenamiento
39
int size () const ;
// D e v u e l v e e l numero de e l e m e n t o s almacenados
void clear () ;
// Elimina t o d o s l o s e l e m e n t o s de l a l i s t a a c t u a l ( queda v a c i a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void insertar ( int pos , int dato ) ;
// PRECOND: ( ! l l e n a ( ) && pos >= 0 && pos <= s i z e ( ) )
// I n s e r t a ( d a t o ) en l a l i s t a a c t u a l en l a p o s i c i o n ( pos )
void eliminar ( int pos ) ;
// PRECOND: ( pos >= 0 && pos < s i z e ( ) )
// Elimina de l a l i s t a a c t u a l e l e l e m e n t o que ocupa l a p o s i c i o n ( pos )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
int acceder ( int pos ) const ;
// PRECOND: ( pos >= 0 && pos < s i z e ( ) )
// D e v u e l v e e l e l e m e n t o de l a l i s t a a c t u a l que ocupa l a p o s i c i o n ( pos )
void modificar ( int pos , int dato );
// PRECOND: ( pos >= 0 && pos < s i z e ( ) )
// Asigna ( d a t o ) a l e l e m e n t o de l a l i s t a a c t u a l que ocupa l a p o s i c i o n ( pos )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Ctes y Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
static const int MAX = 100;
typedef std :: array < int , MAX > Datos ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void abrir_hueco ( int pos ) ;
void cerrar_hueco ( int pos ) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
int sz ;
// numero de e l e m e n t o s de l a l i s t a
Datos v ;
// c o n t i e n e l o s e l e m e n t o s 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 c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// L i s t a I n t : : ~ L i s t a I n t ( ) {}
// D e s t r u c t o r Automático
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
ListaInt :: ListaInt () : sz (0) , v () {}
// C o n s t r u c t o r por D e f e c t o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
ListaInt :: ListaInt ( const ListaInt & o )
// C o n s t r u c t o r 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 A s i g n a c i ó 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
}
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 P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 e l e m e n t o más
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void ListaInt :: cerrar_hueco ( int pos )
{
assert ( sz > 0) ;
- - sz ;
// Ahora hay un e l e m e n t o menos
for ( 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
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
}
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
Tema 3: Gestión de Memoria Dinámica
Tema 3.1: Listas Enlazadas
1. 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 un
puntero 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én
un 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 ;
// D e c l a r a c i ó n a d e l a n t a d a d e l t i p o i n c o m p l e t o Nodo
typedef Nodo * PNodo ; // D e f i n i c i ó n de t i p o Puntero a t i p o i n c o m p l e t o Nodo
struct Nodo {
// D e f i n i c i ó n d e l t i p o Nodo
PNodo sig ;
// Enlace a l a s i g u i e n t e e s t r u c t u r a dinámica
int 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 v a c i a
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void destruir ( PNodo & lista ) ;
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l i s t a , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l i s t a ) queda v a c i a
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void i n s e r t a r _ p r i n c i p i o ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o a l p r i n c i p i o de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void i nserta r_fina l ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o a l f i n a l de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo situar ( PNodo lista , int pos ) ;
// D e v u e l v e un p u n t e r o a l nodo que s e e n c u e n t r a en l a p o s i c i o n
// i n d i c a d a por ( pos ) . La p o s i c i o n c e r o ( 0 ) i n d i c a e l primer nodo .
// S i e l nodo no e x i s t e , e n t o n c e s d e v u e l v e NULL
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void insertar_pos ( PNodo & lista , int pos , int dt ) ;
// I n s e r t a en ( l i s t a ) un e l e m e n t o en l a p o s i c i o n i n d i c a d a por ( pos )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e l i m i n a r _ p r i m e r o ( PNodo & lista ) ;
// Elimina e l primer e l e m e n t o de ( l i s t a ) , s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e li mi n ar _u l ti mo ( PNodo & lista ) ;
// Elimina e l u l t i m o e l e m e n t o 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 l e m e n t o de l a p o s i c i o n i n d i c a d a por ( pos ) ,
// s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo duplicar ( PNodo lista ) ;
// D e v u e l v e un p u n t e r o a una nueva l i s t a r e s u l t a d o de d u p 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 p a n t a l l a e l c o n t e n i d o de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo leer () ;
// D e v u e l v e una l i s t a con l o s numeros l e i d o s de t e c l a d o ( en e l mismo
// orden que son i n t r o d u c i d o s ) h a s t a que l e a e l numero 0 ( que no e s
// i n t r o d u c i d o )
44
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo buscar ( PNodo lista , int dt ) ;
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e l e m e n t o
// i g u a l a ( d t ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void insertar_ord ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o de forma ordenada en ( l i s t a ) , que d e b e e s t a r ordenada
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void eliminar_elem ( PNodo & lista , int dt ) ;
// Elimina de ( l i s t a ) e l primer e l e m e n t o i g u a l a ( d t ) , s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e limina r_mayo r ( PNodo & lista ) ;
// Elimina e l mayor e l e m e n t o 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 ) t o d o s l o s e l e m e n t o s que sean i g u a l e s a ( d t ) ,
// s i e x i s t e n
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
# endif
Solución: lista.cpp
# include " lista . hpp "
# include < iostream >
# include < cstddef >
# include < cassert >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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 v a c i a
// s e r a i n s e r t a d o en l a l i s t a )
void inicializa ( PNodo & lista )
{
lista = NULL ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l i s t a , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l i s t a ) queda v a c i a
void destruir ( PNodo & lista )
{
while ( lista ! = NULL ) {
PNodo ptr = lista ;
lista = lista - > sig ;
delete ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o a l p r i n c i p i o de ( l i s t a )
void i n s e r t a r _ p r i n c i p i o ( PNodo & lista , int dt )
{
PNodo ptr = new Nodo ;
ptr - > dato = dt ;
ptr - > sig = lista ;
lista = ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o a l f i n a l de ( l i s t a )
void i nserta r_fina l ( PNodo & lista , int dt )
{
PNodo ptr = new Nodo ;
ptr - > dato = dt ;
ptr - > sig = NULL ;
if ( lista = = NULL ) {
lista = ptr ;
} else {
45
PNodo act = lista ;
while ( act - > sig ! = NULL ) {
act = act - > sig ;
}
act - > sig = ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que s e e n c u e n t r a en l a p o s i c i o n
// i n d i c a d a por ( pos ) . La p o s i c i o n c e r o ( 0 ) i n d i c a e l primer nodo .
// S i e l nodo no e x i s t e , e n t o n c e s d e v u e l v e NULL
PNodo situar ( PNodo lista , int pos )
{
PNodo ptr = lista ;
while (( ptr ! = NULL ) & & ( pos > 0)) {
ptr = ptr - > sig ;
- - pos ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a en ( l i s t a ) un e l e m e n t o en l a p o s i c i o n i n d i c a d a 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 e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e l i m i n a r _ p r i m e r o ( PNodo & lista )
{
if ( lista ! = NULL ) {
PNodo ptr = lista ;
lista = lista - > sig ;
delete ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Elimina e l u l t i m o e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e li mi n ar _u l ti mo ( 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 l e m e n t o de l a p o s i c i o n i n d i c a d a por ( pos ) ,
// s i e x i s t e
void eliminar_pos ( PNodo & lista , int pos )
{
46
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 ;
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a una nueva l i s t a r e s u l t a d o de d u p 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
PNodo 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 p a n t a l l a e l c o n t e n i d o de ( l i s t a )
void escribir ( PNodo lista )
{
PNodo ptr = lista ;
while ( ptr ! = NULL ) {
cout < < ptr - > dato < < " " ;
ptr = ptr - > sig ;
}
cout < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e una l i s t a con l o s numeros l e i d o s de t e c l a d o ( en e l mismo
// orden que son i n t r o d u c i d o s ) h a s t a que l e a e l numero 0 ( que no e s
// i n t r o d u c i d o )
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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e l e m e n t o
// i g u a l a ( d t ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
47
PNodo buscar ( PNodo lista , int dt )
{
PNodo ptr = lista ;
while (( ptr ! = NULL ) & & ( ptr - > dato ! = dt )) {
ptr = ptr - > sig ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o de forma ordenada en ( l i s t a ) , que d e b e e s t a r
// ordenada
void 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 e l e m e n t o i g u a l a ( d t ) , s i e x i s t e
void 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 e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e limina r_mayo r ( PNodo & lista )
{
if ( lista ! = NULL ) {
PNodo ant_may = NULL ;
// a n t e r i o r a l mayor
PNodo ptr_may = lista ; // apunta a l mayor
PNodo ant = lista ;
// a n t e r i o r a l p t r
PNodo ptr = lista - > sig ; // p t r de r e c o r r i d o
while ( ptr ! = NULL ) {
if ( ptr - > dato > ptr_may - > dato ) {
// s i e s mayor
ant_may = ant ; // a c t u a l i z a r a n t e r i o r a l mayor
ptr_may = ptr ; // a c t u a l i z a r e l p u n t e r o a l mayor
}
ant = ptr ;
// mover l o s p u n t e r o s de r e c o r r i d o
ptr = ptr - > sig ;
}
if ( ptr_may = = lista ) {
lista = lista - > sig ;
} else {
ant_may - > sig = ptr_may - > sig ;
}
48
}
}
delete ptr_may ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Elimina de ( l i s t a ) t o d o s l o s e l e m e n t o s que sean i g u a l e s a ( d t ) ,
// s i e x i s t e n
void 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
void leer ( unsigned & pos )
{
cout < < " Introduzca posicion : " ;
cin > > pos ;
}
void p ru eb a _d up l ic ar ( 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 );
i n s e r t a r _ p r i n c i p i o ( lista , dato );
escribir ( lista );
break ;
case 'C ':
leer ( dato );
inse rtar_f inal ( 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 ':
e l i m i n a r _ p r i m e r o ( lista );
escribir ( lista );
break ;
case 'G ':
e li mi n ar _ ul ti m o ( lista );
escribir ( lista );
break ;
case 'H ':
leer ( pos );
eliminar_pos ( lista , pos ) ;
escribir ( lista );
break ;
case 'I ':
p ru eb a _d u pl ic a r ( lista );
break ;
case 'J ':
escribir ( lista );
50
}
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 ':
elim inar_m ayor ( 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 contiene
un elemento del conjunto. Por ejemplo el conjunto con los elementos {1, 2, 3} puede ser representado por
la siguiente lista enlazada:
lista:
◦−−→
◦−−−−→
1
◦−−−−→
2
3
Diseñe un módulo (programación modular) que proporcione soporte adecuado a la manipulación de conjuntos de números enteros implementados mediante listas enlazadas en memoria dinámica (véase figura
anterior). El módulo deberá definir el tipo Conjunto como un registro con un campo de tipo PNodo, que se
define como un tipo puntero 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é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 lo
tanto, la opción más simple para incluir elementos en él podría ser “insertar siempre los elementos por el
principio”, con objeto de prácticar los conceptos de listas enlazadas, en esta práctica, los elementos del
conjunto serán insertados (sin repetición) ordenados en la lista enlazada donde se encuentran almacenados.
Solución: conjuntos.hpp
51
# ifndef con juntos _hpp_
# define con juntos _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 c o n j u n t o v a c i o
void destruir ( Conjunto & c );
// D e s t r u y e t o d o s l o s e l e m e n t o s d e l c o n j u n t o , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( c ) queda v a c i o
void copiar ( Conjunto & d , const Conjunto & o ) ;
// Copia ( d u p l i c a ) e l c o n j u n t o ( o ) en e l c o n j u n t o ( d )
bool es_vacio ( const Conjunto & c ) ;
// D e v u e l v e t r u e s i e l c o n j u n t o ( c ) e s t a v a c i o
void incluir ( Conjunto & c , int e );
// I n c l u y e e l e l e m e n t o ( e ) en e l c o n j u n t o ( c ) ( s i n r e p e t i c i o n )
void eliminar ( Conjunto & c , int e );
// Elimina e l e l e m e n t o ( e ) d e l c o n j u n t o ( c )
bool pertenece ( const Conjunto & c , int e ) ;
// D e v u e l v e t r u e s i e l e l e m e n t o ( e ) p e r t e n e c e a l c o n j u n t o ( c )
bool e s_subc onjunt o ( const Conjunto & a , const Conjunto & b ) ;
// D e v u e l v e t r u e s i e l c o n j u n t o ( a ) e s s u b c o n j u n t o d e l c o n j u n t o ( b )
void union_conj ( Conjunto & c , const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o ( c ) e l r e s u l t a d o de
// l a union de l o s c o n j u n t o s ( a ) y ( b ) ( d u p l i c a l o s nodos )
void interseccion ( Conjunto & c , const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o ( c ) e l r e s u l t a d o de
// l a i n t e r s e c c i o n de l o s c o n j u n t o s ( a ) y ( b ) ( d u p l i c a l o s nodos )
void diferencia ( Conjunto & c , const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o ( c ) e l r e s u l t a d o de
// l a d i f e r e n c i a de l o s c o n j u n t o s ( a ) y ( b ) ( d u p l i c a l o s nodos )
void d i f e r e n c i a _ s i m e t r i c a ( Conjunto & c , const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o ( c ) e l r e s u l t a d o de
// l a d i f e r e n c i a s i m e t r i c a de l o s c o n j u n t o s ( a ) y ( b ) ( d u p l i c a l o s nodos )
void escribir ( const Conjunto & c ) ;
// Muestra en p a n t a l l a e l c o n t e n i d o d e l c o n j u n t o ( c )
void leer ( Conjunto & c );
// Lee de t e c l a d o e l v a l o r d e l c o n j u n t o ( c )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
# endif
Solución: conjuntos.cpp
# include " conjuntos . hpp "
# include < iostream >
# include < array >
# include < cassert >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A u x i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e l e m e n t o
// i g u a l a ( d t ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
PNodo buscar_ord ( PNodo lst , int dt )
{
PNodo ptr = lst ;
52
while (( ptr ! = NULL ) & & ( ptr - > dato < dt )) {
ptr = ptr - > sig ;
}
if (( ptr ! = NULL ) & & ( ptr - > dato ! = dt )) {
ptr = NULL ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o de forma ordenada en ( l s t ) , que d e b e e s t a r
// ordenada ( s i n r e p e t i c i o n )
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 l e m e n t o cuyo d a t o e s i g u a l a ( d t ) , s i e x i s t e
// La l i s t a ( l s t ) s e e n c u e n t r a ordenada
void 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 ;
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a una nueva l s t r e s u l t a d o de d u p l i c a r en
// memoria dinamica l a l s t r e c i b i d a como parametro
PNodo 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
}
u - > sig = NULL ;
}
return nueva ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l s t , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l s t ) queda v a c i a
void d estrui r_list a ( PNodo & lst )
{
while ( lst ! = NULL ) {
PNodo ptr = lst ;
lst = lst - > sig ;
delete ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void inicializar ( Conjunto & c )
{
c . lista = NULL ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void destruir ( Conjunto & c )
{
dest ruir_l ista ( c . lista );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void copiar ( Conjunto & d , const Conjunto & o )
{
if ( d . lista ! = o . lista ) {
dest ruir_l ista ( 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 );
// i n s e r t a s i n r e p e t i c i o n
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 e s_subc onjunt o ( 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
{
}
PNodo lst = duplicar ( a . lista );
PNodo ptr = b . lista ;
while ( ptr ! = NULL ) {
insertar_ord ( lst , ptr - > dato );
ptr = ptr - > sig ;
}
dest ruir_l ista ( c . lista );
c . lista = lst ;
// i n s e r t a s i n r e p e t i c i o n
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 );
// i n s e r t a s i n r e p e t i c i o n
}
ptr = ptr - > sig ;
}
dest ruir_l ista ( 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 );
// i n s e r t a s i n r e p e t i c i o n
}
ptr = ptr - > sig ;
}
dest ruir_l ista ( c . lista );
c . lista = lst ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void d i f e r e n c i a _ s i m e t r i c a ( 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
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_sub conjun to ( 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 );
d i f e r e n c i a _ s i m e t r i c a ( 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 tipo
PNodo como un puntero a un registro en memoria dinámica de tipo Nodo que contiene un enlace al siguiente
nodo, un enlace al nodo anterior, 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 lista implementado.
lista:
◦−−→
◦−−−
−−→
◦−−−
−−→
←−−−−
−◦
←−−−−
−◦
0
1
2
Solución: listadbl.hpp
# ifndef listadbl_hpp_
# define listadbl_hpp_
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
struct Nodo ;
// D e c l a r a c i ó n a d e l a n t a d a d e l t i p o i n c o m p l e t o Nodo
typedef Nodo * PNodo ; // D e f i n i c i ó n de t i p o Puntero a t i p o i n c o m p l e t o Nodo
struct Nodo {
// D e f i n i c i ó n d e l t i p o Nodo
PNodo sig ;
// Enlace a l a s i g u i e n t e e s t r u c t u r a dinámica
PNodo ant ;
// Enlace a l a e s t r u c t u r a dinámica a n t e r i o r
int 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 v a c i a
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void destruir ( PNodo & lista ) ;
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l i s t a , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l i s t a ) queda v a c i a
56
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void i n s e r t a r _ p r i n c i p i o ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o a l p r i n c i p i o de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void i nserta r_fina l ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o a l f i n a l de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo situar ( PNodo lista , int pos ) ;
// D e v u e l v e un p u n t e r o a l nodo que s e e n c u e n t r a en l a p o s i c i o n
// i n d i c a d a por ( pos ) . La p o s i c i o n c e r o ( 0 ) i n d i c a e l primer nodo .
// S i e l nodo no e x i s t e , e n t o n c e s d e v u e l v e NULL
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void insertar ( PNodo & lista , int pos , int dt ) ;
// I n s e r t a en ( l i s t a ) un e l e m e n t o en l a p o s i c i o n i n d i c a d a por ( pos )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e l i m i n a r _ p r i m e r o ( PNodo & lista ) ;
// Elimina e l primer e l e m e n t o de ( l i s t a ) , s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e li mi n ar _u l ti mo ( PNodo & lista ) ;
// Elimina e l u l t i m o e l e m e n t o 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 l e m e n t o de l a p o s i c i o n i n d i c a d a por ( pos ) ,
// s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo duplicar ( PNodo lista ) ;
// D e v u e l v e un p u n t e r o a una nueva l i s t a r e s u l t a d o de d u p 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 p a n t a l l a e l c o n t e n i d o de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo leer () ;
// D e v u e l v e una l i s t a con l o s numeros l e i d o s de t e c l a d o ( en e l mismo
// orden que son i n t r o d u c i d o s ) h a s t a que l e a e l numero 0 ( que no e s
// i n t r o d u c i d o )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo buscar ( PNodo lista , int dt ) ;
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e l e m e n t o
// i g u a l a ( d t ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void insertar_ord ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o de forma ordenada en ( l i s t a ) , que d e b e e s t a r ordenada
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void eliminar_elem ( PNodo & lista , int dt ) ;
// Elimina de ( l i s t a ) e l primer e l e m e n t o i g u a l a ( d t ) , s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e limina r_mayo r ( PNodo & lista ) ;
// Elimina e l mayor e l e m e n t o 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 ) t o d o s l o s e l e m e n t o s que sean i g u a l e s a ( d t ) ,
// s i e x i s t e n
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
# endif
Solución: listadbl.cpp
# include " listadbl . hpp "
# include < iostream >
# include < cstddef >
# include < cassert >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A u x i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
57
void insertar_nodo ( PNodo & ptr , PNodo ant , int dt )
{
// Crea e l nodo con e l v a l o r d e l dato , e l v a l o r d e l campo
// ' s i g ' apuntando a l nodo apuntado por ' p t r ' , e l v a l o r
// d e l campo ' a n t ' apuntando a l nodo apuntado por ' a n t ' y
// hace que ' p t r ' a pu n te a e s t e nuevo nodo . Tambien hace
// que e l a n t e r i o r d e l s i g u i e n t e ap u nt e a e s t e nodo
PNodo 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 ' a pu n te a l nodo s i g u i e n t e a l que apunta
// a c t u a l m e n t e , y hace que e l a n t e r i o r de e s t e nodo
// s i g u i e n t e a p un t e a l a n t e r i o r a l nodo de p t r . Fi na lme nt e
// l i b e r a e l nodo a l que ' p t r ' apuntaba i n i c i a l m e n t e
assert ( ptr ! = NULL );
PNodo aux = ptr ;
ptr = ptr - > sig ;
if ( ptr ! = NULL ) {
ptr - > ant = aux - > ant ;
}
delete aux ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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 v a c i a
// s e r a i n s e r t a d o en l a l i s t a )
void inicializa ( PNodo & lista )
{
lista = NULL ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l i s t a , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l i s t a ) queda v a c i a
void destruir ( PNodo & lista )
{
while ( lista ! = NULL ) {
PNodo ptr = lista ;
lista = lista - > sig ;
delete ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o a l p r i n c i p i o de ( l i s t a )
void i n s e r t a r _ p r i n c i p i o ( PNodo & lista , int dt )
{
insertar_nodo ( lista , NULL , dt );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o a l f i n a l de ( l i s t a )
void i nserta r_fina l ( 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
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que s e e n c u e n t r a en l a p o s i c i o n
// i n d i c a d a por ( pos ) . La p o s i c i o n c e r o ( 0 ) i n d i c a e l primer nodo .
// S i e l nodo no e x i s t e , e n t o n c e s d e v u e l v e NULL
PNodo situar ( PNodo lista , int pos )
{
PNodo ptr = lista ;
while (( ptr ! = NULL ) & & ( pos > 0)) {
ptr = ptr - > sig ;
- - pos ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a en ( l i s t a ) un e l e m e n t o en l a p o s i c i o n i n d i c a d a 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 e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e l i m i n a r _ p r i m e r o ( PNodo & lista )
{
if ( lista ! = NULL ) {
eliminar_nodo ( lista ) ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Elimina e l u l t i m o e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e li mi n ar _u l ti mo ( 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 l e m e n t o de l a p o s i c i o n i n d i c a d a por ( pos ) ,
// s i e x i s t e
void 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 ) ;
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a una nueva l i s t a r e s u l t a d o de d u p 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
PNodo duplicar ( PNodo lista )
{
PNodo nueva = NULL ;
if ( lista ! = NULL ) {
59
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 p a n t a l l a e l c o n t e n i d o de ( l i s t a )
void escribir ( PNodo lista )
{
PNodo ptr = lista ;
while ( ptr ! = NULL ) {
cout < < ptr - > dato < < " " ;
ptr = ptr - > sig ;
}
cout < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e una l i s t a con l o s numeros l e i d o s de t e c l a d o ( en e l mismo
// orden que son i n t r o d u c i d o s ) h a s t a que l e a e l numero 0 ( que no e s
// i n t r o d u c i d o )
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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e l e m e n t o
// i g u a l a ( d t ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
PNodo buscar ( PNodo lista , int dt )
{
PNodo ptr = lista ;
while (( ptr ! = NULL ) & & ( ptr - > dato ! = dt )) {
ptr = ptr - > sig ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o de forma ordenada en ( l i s t a ) , que d e b e e s t a r
// ordenada
void 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 e l e m e n t o i g u a l a ( d t ) , s i e x i s t e
void eliminar_elem ( PNodo & lista , int dt )
60
{
}
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 e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e limina r_mayo r ( PNodo & lista )
{
if ( lista ! = NULL ) {
PNodo ptr_may = lista ; // apunta a l mayor
PNodo ptr = lista - > sig ; // p t r de r e c o r r i d o
while ( ptr ! = NULL ) {
if ( ptr - > dato > ptr_may - > dato ) {
// s i e s mayor
ptr_may = ptr ; // a c t u a l i z a r e l p u n t e r o a l mayor
}
ptr = ptr - > sig ;
// mover l o s p u n t e r o s de r e c o r r i d o
}
if ( ptr_may = = lista ) {
eliminar_nodo ( lista );
// e l i m i n a r e l primero
} else {
eliminar_nodo ( ptr_may - > ant - > sig ); // e l i m i n a r un nodo s i g u i e n t e
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Elimina de ( l i s t a ) t o d o s l o s e l e m e n t o s que sean i g u a l e s a ( d t ) ,
// s i e x i s t e n
void 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
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
do {
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
"B.
"C.
"D.
"E.
"F.
"G.
"H.
"I.
"J.
"K.
"L.
"M.
"N.
"O.
"P.
Insertar Inicio " < < endl ;
Insertar Final " < < endl ;
Situar Posicion " < < endl ;
Insertar Posicion " < < endl ;
Eliminar Primero " < < endl ;
Eliminar Ultimo " < < endl ;
Eliminar Posicion " < < endl ;
Duplicar " < < endl ;
Escribir " < < endl ;
Leer " < < endl ;
Buscar Elemento " < < endl ;
Insertar Ordenado " < < endl ;
Eliminar Elemento " < < endl ;
Eliminar Mayor " < < endl ;
Purgar " < < endl ;
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 p ru eb a _d up l ic ar ( 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 );
i n s e r t a r _ p r i n c i p i o ( lista , dato );
escribir ( lista );
break ;
case 'C ':
leer ( dato );
inse rtar_f inal ( lista , dato );
escribir ( lista );
break ;
case 'D ':
leer ( pos );
aux = situar ( lista , pos );
if ( aux = = NULL ) {
cout < < " Error : posicion erronea " < < endl ;
62
}
} 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 ':
e l i m i n a r _ p r i m e r o ( lista );
escribir ( lista );
break ;
case 'G ':
e li mi n ar _ ul ti m o ( lista );
escribir ( lista );
break ;
case 'H ':
leer ( pos );
eliminar ( lista , pos ) ;
escribir ( lista );
break ;
case 'I ':
p ru eb a _d u pl ic a r ( 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 ':
elim inar_m ayor ( lista );
escribir ( lista );
break ;
case 'P ':
leer ( dato );
purgar ( lista , dato );
escribir ( lista );
break ;
}
} while ( op ! = 'X ' );
destruir ( lista );
63
Tema 3.2: Abstracción en la Gestión de Memoria Dinámica
1. 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 siguiente
lista enlazada:
lista:
◦−−→
◦−−−−→
25
1
-14
5
Diseñe e implemente el TAD polinomio que defina los siguientes métodos públicos, así como un programa
para comprobar su funcionamiento:
Solución: polinomios.hpp
# ifndef po li n om io s _h pp _
# define po li n om io s _h pp _
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
const double E R RO R _P RE C IS IO N = 1 e - 6;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
class Polinomio {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
˜ Polinomio ();
// D e s t r u c t o r
Polinomio ();
// C o n s t r u c t o r por D e f e c t o
Polinomio ( const Polinomio & p );
// C o n s t r u c t o r de c o p i a
Polinomio & operator = ( const Polinomio & p );
// Operador de A s i g n a c i o n
int max_grado () const ;
// D e v u e l v e e l mayor grado d e l p o l i n o m i o a c t u a l
// cuyo c o e f i c i e n t e e s d i s t i n t o de c e r o
void poner ( int e , double c );
// Asigna e l c o e f i c i e n t e ( c ) a l t e r m i n o de grad o ( e )
// d e l p o l i n o m i o a c t u a l
double obtener ( int e ) const ;
// D e v u e l v e e l c o e f i c i e n t e c o r r e s p o n d i e n t e a l
// t e r m i n o de grado ( e ) d e l p o l i n o m i o a c t u a l
double evaluar ( double x ) const ;
// D e v u e l v e e l r e s u l t a d o de e v a l u a r e l p o l i n o m i o a c t u a l
// para un v a l o r de ( x ) e s p e c i f i c a d o como parametro
void derivar ( const Polinomio & a );
// Asigna a l p o l i n o m i o a c t u a l e l r e s u l t a d o de
// c a l c u l a r l a d e r i v a d a d e l p o l i n o m i o ( a )
void sumar ( const Polinomio & a , const Polinomio & b );
// Asigna a l p o l i n o m i o a c t u a l e l r e s u l t a d o de
// sumar l o s p o l i n o m i o s ( a ) y ( b )
void escribir () const ;
// Muestra en p a n t a l l a e l c o n t e n i d o d e l p o l i n o m i o a c t u a l
void leer ();
// Lee de t e c l a d o e l v a l o r d e l p o l i n o m i o a c t u a l
// Lee p a r e s de c o e f i c i e n t e y gr ado h a s t a que e l c o e f i c i e n t e s e a c e r o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
struct Nodo ;
typedef Nodo * PNodo ;
struct Dato {
int exp ;
double coef ;
};
64
};
}
# endif
struct Nodo {
PNodo sig ;
Dato dato ;
};
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
int mg ;
PNodo lista ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Solución: polinomios.cpp
# include " polinomios . hpp "
# include < iostream >
# include < cassert >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A u x i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Valor a b s o l u t o de un numero
inline 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 a n c i a que l o s
// s e p a r a e s l o s u f i c i e n t e m e n t e pequenya
inline bool iguales ( double a , double b ) {
return abs ( a - b ) < = ER RO R _P RE C IS IO N ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
double potencia ( double base , int exp )
{
double res = 1;
for ( int i = 0; i < exp ; + + i ) {
res * = base ;
}
return res ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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
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 )
{
// S i e l c o e f i c i e n t e e s i g u a l a cero , e n t o n c e s s e d e b e
// e l i m i n a r e l e l e m e n t o c o r r e s p o n d i e n t e a e s e e x p o n e n t e s i e s
// que e x i s t e . En o t r o caso , s i ya e s t a b a almacenado , s e
// r e e m p l a z a su v a l o r . En o t r o caso , s e i n s e r t a ordenado por
// e x p o n e n t e .
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 i n r e p e t i c i o n
if ( e > mg ) {
mg = e ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
double Polinomio :: obtener ( int e ) const
{
// S i e l e l e m e n t o no e s t a en l a l i s t a e n t o n c e s su v a l o r e s c e r o
double 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
// Para sumar dos p o l i n o m i o s , c o n s i d e r a m o s e l hecho de que
// ambas l i s t a s s e e n c u e n t r a n o r d e n a d a s . Se suman l o s
// e l e m e n t o s con i g u a l e x p o n e n t e , y s e c o p i a n l o s de
// e x p o n e n t e s 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 ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A u x i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
67
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e x p o n e n t e d e l e l e m e n t o
// i g u a l a ( exp ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
Polinomio :: 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o de forma ordenada en ( l s t ) , que d e b e e s t a r
// ordenada ( s i n r e p e t i c i o n )
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 l e m e n t o cuyo exp e s i g u a l a ( exp ) , s i e x i s t e
// La l i s t a ( l s t ) s e e n c u e n t r a ordenada
void 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 ;
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a una nueva l s t r e s u l t a d o de d u p l i c a r en
// memoria dinamica l a l s t r e c i b i d a como parametro
Polinomio :: PNodo Polinomio :: duplicar ( PNodo lst ) const
{
PNodo nueva = NULL ;
if ( lst ! = NULL ) {
68
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 ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l s t , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l s t ) queda v a c i a
void 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 contiene
un elemento del conjunto. Por ejemplo el conjunto con los elementos {1, 2, 3} puede ser representado por
la siguiente lista enlazada:
lista:
◦−−→
◦−−−−→
1
◦−−−−→
2
3
Diseñe e implemente el siguiente TAD conjunto de números enteros que defina los siguientes métodos
públicos, así como un programa para comprobar su funcionamiento:
69
Solución: conjuntos.hpp
# ifndef con juntos _hpp_
# define con juntos _hpp_
# include < iostream >
namespace umalcc {
class Conjunto {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
˜ Conjunto ();
// D e s t r u c t o r
Conjunto ( const Conjunto & c );
// C o n s t r u c t o r de Copia
Conjunto & operator = ( const Conjunto & c );
// Operador de A s i g n a c i o n
Conjunto ();
// C o n s t r u c t o r por D e f e c t o : c o n j u n t o v a c i o
void clear ();
// Elimina t o d o s l o s e l e m e n t o s d e l c o n j u n t o a c t u a l ( queda v a c i o )
bool es_vacio () const ;
// D e v u e l v e t r u e s i e l c o n j u n t o a c t u a l e s t a v a c i o
void incluir ( int e );
// I n c l u y e e l e l e m e n t o ( e ) en e l c o n j u n t o a c t u a l
void eliminar ( int e );
// Elimina e l e l e m e n t o ( e ) d e l c o n j u n t o a c t u a l
bool pertenece ( int e ) const ;
// D e v u e l v e t r u e s i e l e l e m e n t o ( e ) p e r t e n e c e a l c o n j u n t o a c t u a l
bool e s_subc onjunt o ( const Conjunto & a ) const ;
// D e v u e l v e t r u e s i e l c o n j u n t o a c t u a l e s s u b c o n j u n t o d e l c o n j u n t o ( a )
void union_conj ( const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o a c t u a l e l r e s u l t a d o de
// l a union de l o s c o n j u n t o s ( a ) y ( b )
void interseccion ( const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o a c t u a l e l r e s u l t a d o de
// l a i n t e r s e c c i o n de l o s c o n j u n t o s ( a ) y ( b )
void diferencia ( const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o a c t u a l e l r e s u l t a d o de
// l a d i f e r e n c i a de l o s c o n j u n t o s ( a ) y ( b )
void d i f e r e n c i a _ s i m e t r i c a ( const Conjunto & a , const Conjunto & b );
// Asigna a l c o n j u n t o a c t u a l e l r e s u l t a d o de
// l a d i f e r e n c i a s i m e t r i c a de l o s c o n j u n t o s ( a ) y ( b )
void escribir () const ;
// Muestra en p a n t a l l a e l c o n t e n i d o d e l c o n j u n t o a c t u a l
void leer ();
// Lee de t e c l a d o e l v a l o r d e l c o n j u n t o a c t u a l ,
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Ctes y Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
struct Nodo ;
typedef Nodo * PNodo ;
struct Nodo {
PNodo sig ;
int dato ;
};
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo lista ;
// componentes d e l c o n j u n t o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
};
}
70
# endif
Solución: conjuntos.cpp
# include " conjuntos . hpp "
# include < iostream >
# include < array >
# include < cassert >
using namespace std ;
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ); // i n s e r t a s i n r e p e t i c i o n
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Conjunto :: eliminar ( int e )
{
eliminar_ord ( lista , e );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool Conjunto :: pertenece ( int e ) const
{
return ( buscar_ord ( lista , e ) ! = NULL );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool Conjunto :: es_s ubconj unto ( const Conjunto & a ) const
{
// e s s u b c o n j u n t o s i t o d o s l o s e l e m e n t o s d e l c o n j u n t o a c t u a l
// p e r t e n e c e n tambien a l c o n j u n t o e s p e c i f i c a d o como parametro
PNodo 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 );
// i n s e r t a s i n r e p e t i c i o n
ptr = ptr - > sig ;
}
71
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 );
// i n s e r t a s i n r e p e t i c i o n
}
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 );
// i n s e r t a s i n r e p e t i c i o n
}
ptr = ptr - > sig ;
}
destruir ( lista );
lista = lst ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Conjunto :: d i f e r e n c i a _ s i m e t r i c a ( 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 ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A u x i l i a r e s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e l e m e n t o
// i g u a l a ( d t ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
Conjunto :: 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
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o de forma ordenada en ( l s t ) , que d e b e e s t a r
// ordenada ( s i n r e p e t i c i o n )
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 l e m e n t o cuyo d a t o e s i g u a l a ( d t ) , s i e x i s t e
// La l i s t a ( l s t ) s e e n c u e n t r a ordenada
void 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 ;
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a una nueva l s t r e s u l t a d o de d u p l i c a r en
// memoria dinamica l a l s t r e c i b i d a como parametro
Conjunto :: 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
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l s t , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l s t ) queda v a c i a
void 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 . e s_subc onjunt o ( 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 . d i f e r e n c i a _ s i m e t r i c a ( c1 , c2 );
escribir ( " Diferencia Simetrica : " , c3 );
}
3. 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 procesador
dispone 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 un
procesador con cuatro etapas y dos tareas, la tarea T1 va ejecutándose por la etapa e2 y la tarea T2 va
ejecutándose por la etapa e4.
t1
procesador
e1
e2
t2
e3
e4
Se debe diseñar la estructura de datos necesaria para representar la información del estado del procesador
en cada momento. Para ello, se sigue el esquema mostrado en la siguiente figura. Como se puede observar
cada 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 los
correspondientes nodos de etapa. Cada nodo de etapa contendrá su identificador, el número de la tarea
que 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 puede
observar que la tarea T1 se está ejecutando en la etapa 2 y la tarea T2 se está ejecutando en la etapa 4.
74
procesador
1
2
0
3
1
4
0
2
Es posible que en un determinado momento interese ampliar la potencia de una determinada etapa. Para
ello, se replicará dicha etapa haciendo tantos duplicados de la misma como se desee. Así mismo, es posible
que 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 proporcione los siguientes métodos públicos, así mismo, también se deberá implementar un programa principal
que permita su utilización:
a) El Constructor recibe el número de etapas que tiene un determinado procesador, y crea la estructura
base de étapas sin replicación y todas en estado inicial libre, como se muestra en la siguiente figura
para un procesador de 4 etapas:
procesador
1
2
0
0
3
0
4
0
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, para
la figura anterior:
Etapa: 1
Replica:
Replica:
Etapa: 2
Replica:
Replica:
Etapa: 3
Replica:
Etapa: 4
Replica:
libre
libre
tarea 1
tarea 2
libre
libre
d ) Un método Replicar, que se usará para ampliar la potencia de una determinada etapa del procesador
actual. Recibe como parámetros el identificador de la etapa a replicar y el número de réplicas que
deseamos añadir. Las réplicas añadidas tendrán el estado inicial libre (no tienen asignadas la ejecución
de 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 los
nodos intermedios añadidos. Como se puede observar, todas las réplicas añadidas deben apuntar al
primer nodo intermedio de la etapa siguiente (salvo en la última etapa). La siguiente figura muestra
el resultado de añadir dos réplicas de la etapa 2 a la figura anterior:
procesador
1
2
0
1
3
0
4
2
2
0
2
0
La siguiente figura muestra el resultado de añadir una réplica de la etapa 1 a la figura anterior:
procesador
1
2
0
1
1
2
0
0
2
0
75
3
0
4
2
e) Un método para Compactar que se usará para disminuir el número de réplicas de una etapa del
procesador actual. Para ello, recibe como parámetro el identificador de la etapa a compactar y
elimina 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 de
una etapa (pues sirve de enlace entre una etapa y la siguiente). En caso de que la compactación
requiera eliminar la primera réplica de una etapa (porque esté libre), el puntero al nodo de
etapa del primer nodo de la lista de nodos intermedios pasará a apuntar a un nodo de etapa que
permanezca tras la compactación. Por ejemplo, para la siguiente figura:
procesador
1
2
0
0
1
3
0
4
0
2
0
1
2
2
la siguiente figura es el resultado de compactar la etapa 2 de la figura anterior:
procesador
1
3
0
0
1
4
0
2
0
1
2
2
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 la
siguiente etapa.
Si la tarea es nueva, buscará una réplica libre de la primera etapa del procesador. Si no hay
ré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á terminado
su 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ándose
hasta alguna réplica libre de la siguiente etapa. Si no hay ninguna réplica libre de la siguiente
etapa, entonces lanzará una excepción.
g) Así mismo, también deberá ser posible realizar la copia y asignación (duplicación) de la estructura
de datos que representa a un determinado procesador.
Solución: procesador.hpp
# ifndef pr oc e sa do r _h pp _
# define pr oc e sa do r _h pp _
namespace umalcc {
class Procesador {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
˜ 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 a v a n z a r _ e v a l u a c i o n ( unsigned tarea , bool & ok );
76
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Ctes y Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void destruir ();
void destruir ( PNodo & lista );
void duplicar ( const Procesador & o );
void d uplica r_rest o ( 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 ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ) {}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// c r e a un p r o c e s a d o r con ' n ' e t a p a s s i m p l e s ( s i n 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 );
77
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 ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// c o p i a ( d u p l i c a ) un p r o c e s a d o r
Procesador :: Procesador ( const Procesador & o )
: proc ( NULL )
{
duplicar ( o );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// a s i g n a ( d u p l i c a ) un p r o c e s a d o r
Procesador & Procesador :: operator = ( const Procesador & o )
{
if ( this ! = & o ) {
duplicar ( o );
}
return * this ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// c r e a n r e p l i c a s de una e t a p a
void Procesador :: replicar ( unsigned id_etapa , unsigned n , bool & ok )
{
PNodo ptr = buscar ( id_etapa );
if ( ptr = = NULL ) {
ok = false ;
} else {
ok = true ;
// I n s e r t a r n e t a p a s con i d e n t i f i c a d o r ' i d _ e t a p a ' a l i n i c i o de
// p t r −>s i g , donde e l s i g u i e n t e de cada e t a p a e s i g u a l a l
// s i g u i e n t e de l a e t a p a i n i c i a l
for ( 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 e t a p a
void Procesador :: compactar ( unsigned id_etapa , bool & ok )
{
PNodo ptr = buscar ( id_etapa );
if ( ptr = = NULL ) {
ok = false ;
} else {
ok = true ;
// e l i m i n a r a p a r t i r d e l segundo
PNodo 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 primero
if (( 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 ;
}
}
}
78
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d e s t r u y e una l i s t a de nodos i n t e r m e d i o s
void Procesador :: destruir ( PNodo & lista )
{
while ( lista ! = NULL ) {
PNodo aux = lista ;
lista = lista - > sig ;
delete aux - > et ;
delete aux ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d e s t r u y e un p r o c e s a d o r
void Procesador :: destruir ()
{
while ( proc ! = NULL ) {
assert ( proc - > et ! = NULL );
PNodo aux = proc ;
proc = proc - > et - > sig ;
destruir ( aux );
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d u p l i c a una l i s t a de nodos i n t e r m e d i o s y s u s e t a p a s a s o c i a d a s
// ( a p a r t i r d e l segundo nodo )
void Procesador :: duplicar ( PNodo & lista , PNodo origen , PNodo sig )
{
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 ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d u p l i c a l a s l i s t a s de nodos i n t e r m e d i o s y s u s e t a p a s a s o c i a d a s
// ( a p a r t i r d e l segundo nodo ) para t o d a s l a s e t a p a s d e l p r o c e s a d o r
void Procesador :: d uplica r_rest o ( 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 ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d u p l i c a l a s e t a p a s b a s e d e l p r o c e s a d o r
void 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 ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d u p l i c a un p r o c e s a d o r
void Procesador :: duplicar ( const Procesador & o )
{
destruir ();
if ( o . proc ! = NULL ) {
79
duplicar_base ( o );
dupl icar_r esto ( o );
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// b u s c a una e t a p a en e l p r o c e s a d o r
Procesador :: 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 e t a p a
void 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 ;
}
cout < < endl ;
ptr = ptr - > sig ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// muestra l a l i s t a de e t a p a s y s u s r e p l i c a s
void Procesador :: mostrar () const
{
cout < < " - - - - - - - - - - - - - - " < < endl ;
PNodo ptr = proc ;
while ( ptr ! = NULL ) {
mostrar ( ptr );
cout < < " - - - - - - - - - - - - - - " < < endl ;
ptr = ptr - > et - > sig ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// b u s c a una t a r e a en l a l i s t a de r e p l i c a s de una e t a p a
Procesador :: PNodo Procesador :: buscar_tarea ( PNodo lista , unsigned t ) const
{
PNodo ptr = lista ;
while (( ptr ! = NULL ) & & ( t ! = ptr - > et - > tarea )) {
ptr = ptr - > sig ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// b u s c a una t a r e a en e l p r o c e s a d o r
Procesador :: 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 e v a l u a c i o n de una d e t e r m i n a d a t a r e a
void Procesador :: a v a n z a r _ e v a l u a c i o n ( unsigned t , bool & ok )
{
assert ( t ! = REPLICA_LIBRE );
ok = true ;
PNodo orig = buscar_tarea ( t );
80
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 ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
4. Diseñe un programa que permita utilizar el TAD especificado en el ejercicio anterior.
Solución: main.cpp
# 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 l eer_nu m_etap a ( 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 ;
81
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void c r e a r _ p r o c e s a d o r ( Procesador & p )
{
unsigned ne ;
leer _num_e tapa ( ne );
p = Procesador ( ne );
}
void r eplica r_etap a ( 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 c om pa c ta r_ e ta pa ( Procesador & p )
{
unsigned e ;
bool ok ;
leer_etapa ( e );
p . compactar (e , ok );
if ( ! ok ) {
cout < < " Error al compactar la etapa : " < < e < < endl ;
}
}
void a v a n z a r _ e v a l u a c i o n ( Procesador & p )
{
unsigned t ;
bool ok ;
leer_tarea ( t );
p . a v a n z a r _ e v a l u a c i o n (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 ':
c r e a r _ p r o c e s a d o r ( p );
break ;
case 'B ':
repl icar_e tapa ( p );
break ;
case 'C ':
c om pa c ta r _e ta p a ( p );
break ;
case 'D ':
a v a n z a r _ e v a l u a c i o n ( p );
break ;
case 'E ':
copiar_asig ( p );
break ;
case 'F ':
p . mostrar ();
break ;
}
} while ( op ! = 'X ' );
}
82
Tema 4: Introducción a la Programación Orientada a Objetos
1. Para calcular los sueldos de cada empleado de una factoría, se diseña la siguiente jerarquía de clases
polimórficas:
Factoria
Empleado
Directivo
AgVentas
AgVentas_A
Directivo_A
AgVentas_B
Directivo_B
La clase polimórfica Empleado representa un empleado general de una factoría, tiene un constructor
que permite crear un objeto con el nombre (string) del empleado 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.
• 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 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.
• 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 cantidad 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 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.
• 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 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.
• 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, tiene
un constructor que permite crear un objeto con el nombre (string) del empleado 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.
La clase polimórfica Directivo_A representa un directivo de clase A, empleado de una factoría, tiene
un constructor que permite crear un objeto con el nombre (string) del empleado recibido como
parámetro, y proporciona los siguientes métodos públicos virtuales:
83
• 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, tiene
un constructor que permite crear un objeto con el nombre (string) del empleado 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.
• 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 constructor por defecto permite crear un nuevo objeto de clase Factoria sin ningún empleado, y proporciona
los 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 (de
entrada) a la lista de empleados de la factoría actual. Si la operación es posible o no, entonces
devuelve 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 ventas, y calculará sus sueldos. Así mismo, tambien probará que la clonación de la factoría funciona
adecuadamente.
Solución: empleado.hpp
# ifndef emp leado_ hpp__
# define emp leado_ 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
84
{
}
return nmb ;
}
Empleado :: Empleado ( const Empleado & o )
: nmb ( o . nmb ) {}
Solución: directivo.hpp
# ifndef di re c ti vo _ hp p_ _
# define di re c ti vo _ hp p_ _
# 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 d i r e c t i v o _ a _ h p p _ _
# define d i r e c t i v o _ a _ h p p _ _
# 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 >
85
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 d i r e c t i v o _ b _ h p p _ _
# define d i r e c t i v o _ b _ h p p _ _
# 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 agv entas_ hpp__
# define agv entas_ hpp__
# include < string >
86
# 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 anyadi r_vent as ( 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 :: anya dir_ve ntas ( 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 a g v e n t a s _ a _ h p p _ _
# define a g v e n t a s _ a _ h p p _ _
# 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
87
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 a g v e n t a s _ b _ h p p _ _
# define a g v e n t a s _ b _ h p p _ _
# 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 ) {}
}
88
Solución: factoria.hpp
# ifndef fac toria_ hpp__
# define fac toria_ 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 a n y a d i r _ e m p l e a d o ( 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 :: a n y a d i r _ e m p l e a d o ( 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 >
89
# 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 n ue vo _ di re c ti vo ( 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 - > a n y a d i r _ e m p l e a d o (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 - > anyad ir_ven tas ( v );
} else if ( clase = = " B " ) {
e = new AgVentas_B ( n );
e - > anyad ir_ven tas ( v );
}
f - > a n y a d i r _ e m p l e a d o (e , ok );
}
if ( ! ok ) {
cout < < " Error al añadir : " < < n < < endl ;
delete e ;
}
}
int main ()
{
Factoria * f = new Factoria ;
n ue vo _ di r ec ti v o (f , " Ana " , " A " );
n ue vo _ di r ec ti v o (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 simular el comportamiento de una serie de vehículos, por lo que se establece la siguiente jerarquía
de clases:
90
Vehiculo
Automovil
Bicicleta
Todo objeto de la clase base polimórfica Vehiculo debe guardar en su estado la siguiente información
y 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) del
mismo (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 siempre
true
• 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 constructor:
• DPL: constante simbólica static, de tipo unsigned, que indica la distancia que el automóvil
recorre por litro de combustible (= 50).
• deposito: atributo unsigned que guarda el número de litros de combustible del depósito del
automóvil.
• 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étodos
públicos virtuales:
• tiene_energia(): redefine el método de la clase base, devolviendo true si la cantidad almacenada 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 recorrida
actual 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óvil
en 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 constructor:
• NUM_PLATOS: constante simbólica static, de tipo unsigned, indicando el número de platos que
tiene la bicicleta.
• plato: un unsigned que indica el plato que tiene puesto en este momento la bicicleta (a mayor
tamañ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étodos
públicos virtuales:
91
• mover(): redefine el método de la clase base, de tal forma que la bicicleta se mueve una distancia
igual al valor de plato + 1, es decir, se incrementa la distancia recorrida actual sumándole a la
misma 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 = 4
punteros a objetos de la clase Vehiculo.
Implementar el procedimiento viajar(v, d, t), que recibe un puntero a un objeto de la clase
Vehiculo, un unsigned con la distancia total a recorrer por el vehículo, y devuelve, a través de un
parámetro de salida el tiempo (“minutos”) que el vehículo ha tardado en llegar a su destino (si ha
tenido 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 miembro
mover() 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] apuntando
a é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 pone
mis_vehiculos[3] apuntando a él.
• Para todos los vehiculos que se encuentran en mis_vehiculos, debe calcular el tiempo de duración del viaje para una distancia recorrida de destino 1000 invocando al procedimiento viajar
y, en caso de que el vehículo tuviera energía suficiente, escribe ese tiempo por pantalla (en caso
contrario, se indica con un mensaje por pantalla: El vehículo x no ha podido llegar a su
destino por falta de energía)
• Un ejemplo de ejecución podría ser:
El vehículo 5555JJJ no ha podido llegar a su destino por falta de energía
Tiempo vehículo 6666JJJ: 1000 minutos
Tiempo vehículo 7777JJJ: 500 minutos
Tiempo vehículo 8888JJJ: 334 minutos
Solución: vehiculo.hpp
# ifndef veh iculo_ hpp__
# define veh iculo_ hpp__
# include < string >
namespace umalcc {
class Vehiculo {
public :
Vehiculo ( const std :: string & i );
virtual ˜ Vehiculo ();
virtual std :: string id () const ;
virtual unsigned consul tar_di st () 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 & );
//−−−− A t r i b u t o s −−−−
std :: string ident ;
92
};
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 :: consul tar_di st () 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 ;
}
}
Vehiculo * Vehiculo :: clone () const
{
return new Vehiculo ( * this ) ;
}
Solución: automovil.hpp
# ifndef au to m ov il _ hp p_ _
# define au to m ov il _ hp p_ _
# 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;
//−−−− A t r i b u t o s −−−−
unsigned deposito ;
};
}
93
# 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 bi ci c le ta _ hp p_ _
# define bi ci c le ta _ hp p_ _
# include " vehiculo . hpp "
# include < string >
namespace umalcc {
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;
//−−−− A t r i b u t o s −−−−
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 ()
{
94
}
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
# include
# include
# include
# include
" vehiculo . hpp "
" automovil . hpp "
" bicicleta . hpp "
< iostream >
< 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 - > cons ultar_ dist () < destino ) {
tiempo + + ;
v - > mover ();
}
}
int main ()
{
Vehiculos mis_vehiculos ;
array < unsigned , NUM_VEHICULOS > tiempos ;
Bicicleta * una_bici ;
Automovil * un_coche ;
// Un c o c h e con 10 l i t r o s de g a s o l i n a
un_coche = new Automovil ( " 5555 JJJ " );
un_coche - > repostar (10);
mis_vehiculos [ 0 ] = un_coche ;
// B i c i s con d i s t i n t o s p l a t o s
una_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 i
mis_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 i
una_bici - > cambiar (); // Cambio e l p l a t o de mi segunda b i c i
mis_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 ] - > cons ultar_ dist () > = DIST_DESTINO ) {
cout < < " Tiempo vehículo " < < mis_vehiculos [ i ] - > id () < <
< < tiempos [ i ]
< < " minutos " < < endl ;
} else {
95
": "
}
}
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 ] ;
}
}
3. 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) estacionados
en é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 estacionarse
en 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ículos
estacionados en otro_parking al parking actual.
• ~Parking(): destructor de la clase: libera todos los vehículos almacenados en el parking (los
destruye).
• 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 clase
Vehiculo. Si hay espacio en el parking para estacionar un nuevo vehículo, entonces v se añade al
final de la lista de vehículos estacionados en el parking y el número de vehículos estacionados se
incrementa en 1; finalmente, se debe invocar al método de estacionar sobre este nuevo vehículo
estacionado (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 el
parking.
• extraer(id): busca en la lista de vehículos almacenados en el parking el vehículo con idenfificador id. Si lo encuentra, debe extraer el vehículo del parking y devolver un puntero al objeto
vehí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 al
vehículo con identificador id, si éste está estacionado en el parking. Si no, devuelve una posición
fuera de rango (por ejemplo, el n_v).
• copiar(otro_parking): copia todo el estado de otro_parking (esto es, clona todos los vehículos
almacenados en él y copia su n_v) en el objeto actual. Nota: deben clonarse todos los vehículos
del 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 {
96
class Parking {
// CLASE NO−POLIMORFICA
public :
˜ 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 ;
+ + 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 ())) {
97
++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 a n y a d i r _ v e h i c u l o ( 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 " );
a n y a d i r _ v e h i c u l o ( park , a1 );
a n y a d i r _ v e h i c u l o ( park , b1 );
a n y a d i r _ v e h i c u l o ( park , a2 );
Parking aux = park ;
Vehiculo * v = aux . extraer ( " A1 " );
if ( v ! = NULL ) {
cout < < " Vehiculo : " < < v - > id () < < endl ;
v - > mover ();
}
aux . mostrar ();
park . mostrar ();
delete v ;
}
98
Tema 5: Colecciones
1. 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 mediante
la siguientes operaciones:
Añadir los datos de una persona a la agenda, de tal forma que si la persona ya existe, entonces se
actualiza 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. En
caso de que no exista en la agenda ninguna persona con dicho nombre, entonces se mostrará un
mensaje de error.
Borrar los datos de una determinada persona, a partir de su nombre recibido como parámetro. En
caso de que no exista en la agenda ninguna persona con dicho nombre, entonces se mostrará un
mensaje 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 ( c o n s t Agenda& o ) ;
// Generado automáticamente
// Agenda& o p e r a t o r =( c o n s t 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 ;
//−− A t r i b u t o s −−−−−−−−−−−−−−−−−
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 );
}
}
99
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ;
100
cout
cout
cout
cout
cout
cout
do {
<<
<<
<<
<<
<<
<<
endl ;
" A . Añadir datos de persona " < < endl ;
" B . Mostrar toda la agenda " < < endl ;
" C . Mostrar datos de persona " < < endl ;
" D . Borrar persona " < < endl ;
" X . Fin " < < endl ;
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 6, e implementando 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 () ;
// D e s t r u y e e l o b j e t o y t o d o s s u s r e c u r s o s a s o c i a d o s .
Persona () ;
// Construye una p e r s o n a con nombre y t e l e f o n o v a c í o .
Persona ( const std :: string & n , const std :: string & t ) ;
// Construye una p e r s o n a con e l nombre y e l t e l e f o n o
// segun l o s p a r a m e t r o s r e c i b i d o s .
bool error () const ;
// D e v u e l v e t r u e s i e l o b j e t o a c t u a l e s t a en e s t a d o erroneo ,
// e s d e c i r , e l nombre o e l t e l e f o n o son v a c í o s .
std :: string obtene r_nomb re () const ;
// D e v u e l v e e l v a l o r d e l nombre d e l o b j e t o a c t u a l .
std :: string o b t e n e r _ t el e f o n o () const ;
101
// D e v u e l v e e l v a l o r d e l t e l e f o n o d e l o b j e t o a c t u a 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 :: obte ner_no mbre () const
{
return nombre ;
}
std :: string Persona :: o b t e n e r _ t e l e f o n o () 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 ( ) ;
// D e s t r u y e e l o b j e t o y t o d o s s u s r e c u r s o s a s o c i a d o s .
// Agenda ( ) ;
// Construye una agenda v a c i a .
// Agenda ( c o n s t Agenda& o ) ;
// Construye una agenda como c o p i a de o t r a agenda
// Agenda& o p e r a t o r =( c o n s t Agenda& o ) ;
// Construye una agenda como c o p i a de o t r a agenda
void anyadir ( const Persona & p );
// S i l a p e r s o n a e s p e c i f i c a d a como parametro no e s t a en modo
// erroneo , s i l a p e r s o n a ya s e e n c o n t r a b a en l a agenda ,
// e n t o n c e s l o s nuevos v a l o r e s de l a p e r s o n a r ee mp la za n a l o s
// a n t e r i o r e s , en o t r o c a s o anyade l a p e r s o n a e s p e c i f i c a d a a
// l a agenda a c t u a l .
Persona buscar ( const std :: string & nombre ) const ;
// Busca en l a agenda l a p e r s o n a cuyo nombre s e e s p e c i f i c a
// como parametro , y s i l a e n c u e n t r a , e n t o n c e s d e v u e l v e un o b j e t o
// Persona con l o s v a l o r e s de l a p e r s o n a almacenados . S i no
// l a e n c u e n t r a , e n t o n c e s d e v u e l v e una p e r s o n a en e s t a d o de
// e r r o r .
void eliminar ( const std :: string & nombre , bool & ok );
// Elimina de l a agenda a c t u a l l a p e r s o n a cuyo nombre s e
// e s p e c i f i c a como parametro y ok tomara e l v a l o r t r u e . En c a s o
// de no e x i s t i r , ok tomara e l v a l o r f a l s e .
void mostrar () const ;
// Muestra en p a n t a l l a e l c o n t e n i d o c o m p l e t o de l a agenda .
private :
typedef std :: vector < Persona > Datos ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned buscar ( const Datos & d , const std :: string & nombre ) const ;
102
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ( c o n s t Agenda& o ) : v ( o . v ) {}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Agenda& Agenda : : o p e r a t o r =( c o n s t Agenda& o )
// {
//
i f ( t h i s != &o ) {
//
v = o.v;
// }
// r e t u r n ∗ t h i s ;
// }
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Agenda :: anyadir ( const Persona & p )
{
if ( ! p . error ()) {
unsigned i = buscar (v , p . ob tener_ 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 ] . ob tener_ nombre () < < " "
103
}
}
< < v [ i ] . o b t e ne r _ t e l e f o n o () < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned Agenda :: buscar ( const Datos & d , const std :: string & nombre ) const
{
unsigned i = 0 ;
while (( i < d . size ()) & & ( nombre ! = d [ i ] . obten er_nom bre ())) {
++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 m os tr a r_ pe r so na ( const Persona & p )
{
cout < < " Nombre : " < < p . obtene r_nomb re () < < endl ;
cout < < " telefono : " < < p . o b t e n e r _ t e l e f o n o () < < 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 ();
104
}
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 {
m os tr a r_ p er so n a ( 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 de
agente vacío. Posteriormente se eliminarán del vector aquellos agentes cuyas ventas sean inferiores a la
media 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 ()) ;
}
105
void purgar ( VAgentes & v , double media )
{
// a l t e r a e l orden s e c u e n c i a l de l o s e l e m e n t o s
int i = 0 ;
while ( i < int ( v . size ())) {
if ( v [ i ] . ventas < media ) {
v [ i ] = v [ v . size () - 1 ] ;
v . pop_back () ;
} else {
++i ;
}
}
}
void p ur ga r _o rd e na do ( VAgentes & v , double media )
{
// mantiene e l orden s e c u e n c i a l de l o s e l e m e n t o s
int 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 ambas
matrices. Las matrices se almacenarán en vectores de dos dimensiones (utilizando el tipo vector de la
biblioteca 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 )
106
{
}
int nf , nc ;
cout < < " Introduzca el numero de filas : " ;
cin > > nf ;
cout < < " Introduzca el numero de columnas : " ;
cin > > nc ;
m = Matriz ( nf , Fila ( nc )) ; // c o p i a de l a m a t r i z c o m p l e t a
cout < < " 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 ] ;
}
}
// o t r a o p c i ó n más e f i c i e n t e para l a l e c t u r a de v e c t o r e s
void 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 c o p i a de l a m a t r i z c o m p l e t a
}
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 c o p i a de l a m a t r i z c o m p l e t a
}
}
int main ()
{
Matriz m1 , m2 , m3 ;
leer ( m1 ) ;
leer ( m2 ) ;
multiplicar ( m1 , m2 , m3 ) ;
if ( m3 . size () = = 0) {
cout < < " Error en la mult iplica ció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 balanceados o no. Por ejemplo la siguiente expresión
3 + 5 ∗ ([4] − 67) + [(7)] se encuentra correctamente balanceada, donde los posibles casos de error son los
siguientes:
Un símbolo de apertura no se corresponde con su correspondiente símbolo de cierre. Por ejemplo:
3 + 5 ∗ ([4] − 67] + [(7)]
107
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 pil a_char _hpp_
# define pil a_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 _CORRE SPONDE = 1;
const int FA LTA_AP ERTURA = 2;
108
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 e st a_ b al a nc ea d o ( 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 _APERT URA ;
} else if ( corresponde ( p . top () , exp [ i ] )) {
p . pop ();
} else {
ok = NO_CO RRESPO NDE ;
}
}
}
if ( ok = = CORRECTO & & ! p . empty () ) {
ok = FALTA_CIERRE ;
}
return ok ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
int main ()
{
string exp ;
leer_expr ( exp );
int ok = es ta _ ba la n ce ad o ( exp );
switch ( ok ) {
case CORRECTO :
cout < < " Está balanceado " < < endl ;
break ;
case N O_CORR ESPOND E :
cout < < " Símbolos no corresponden " < < endl ;
break ;
case F ALTA_A PERTUR A :
cout < < " Falta símbolo de apertura " < < endl ;
break ;
case FALTA_CIERRE :
cout < < " Falta símbolo de cierre " < < endl ;
break ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
109
Prácticas de Laboratorio
Práctica 1: Almacenamiento Persistente de Datos
1. 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 guardar
el contenido de la agenda a un fichero.
Se diseñarán versiones para trabajar con tres formatos de ficheros diferentes (donde los símbolos
representan el espacio en blanco y el fin de línea respectivamente):
Opción (A)
nombre_apellidos
nombre_apellidos
···
edad
edad
←←-
Opción (B)
nombre apellidos ←edad ←nombre apellidos ←edad ←···
y
←-
Opción (C)
nombre apellidos
nombre apellidos
···
edad
edad
←←-
Nótese que en la primera opción (A), el nombre de la persona no contiene espacios en blanco, mientras
que en las siguientes opciones (B y C), si es posible que el nombre de la persona contenga espacios en
blanco.
El programa mostrará un menú iterativo para poder seleccionar las acciones deseadas por el usuario del
programa, 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 v a c i a
void inic_agenda ( Agenda & ag )
{
ag . nelms = 0;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// anyade una p e r s o n a a l f i n a l de l a agenda
void a ny ad i r_ pe r so na ( 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 : " ;
110
cin > > p . edad ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e una p e r s o n a y l a anyade a l a agenda ( supone l e c t u r a c o r r e c t a )
void nueva_persona ( Agenda & ag )
{
bool ok ;
Persona p ;
leer_persona ( p );
a ny ad i r_ p er so n a ( ag , p , ok );
if ( ! ok ) {
cout < < " Error al introducir la nueva persona " < < endl ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e s c r i b i r _ p e r s o n a ( const Persona & p )
{
cout < < " Nombre : " < < p . nombre < < endl ;
cout < < " Edad : " < < p . edad < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// e s c r i b e l a agenda en p a n t a l l a
void e sc ri b ir _a g en da ( const Agenda & ag )
{
for ( unsigned i = 0; i < ag . nelms ; + + i ) {
cout < < " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " < < endl ;
e s c r i b i r _ p e r s o n a ( 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 e n t r a d a de f i c h e r o
Persona p ;
fich . open ( nombre_fich . c_str ()); // v i n c u l a l a v b l e de f l u j o con e l f i c h e r o
if ( fich . fail ()) {
ok = false ;
// e r r o r de a p e r t u r a d e 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 agenda
leer_persona ( fich , p );
// l e e una p e r s o n a
while ( ! fich . fail () & & ok ) {
// m i e n t r a s l e c t u r a c o r r e c t a
a ny ad i r_ p er so n a ( ag , p , ok ); // anyade p e r s o n a a l a agenda
leer_persona ( fich , p );
// l e e o t r a p e r s o n a
}
ok = ok & & fich . eof ();
// c o r r e c t o s i a l c a n z a d o Fin−De−F i c h e r o
fich . close ();
// c i e r r a l a v i n c u l a c i o n
}
}
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 ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
111
// FORMATO DEL FICHERO DE SALIDA :
//
// <nombre> <edad> <RC>
// <nombre> <edad> <RC>
//
...
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e s c r i b i r _ p e r s o n a ( ofstream & fich , const Persona & p )
{
fich < < p . nombre < < " " < < p . edad < < endl ;
}
void e sc ri b ir _a g en da ( 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 i n c u l a l a v b l e de f l u j o con e l f i c h e r o
if ( fich . fail ()) {
ok = false ;
// e r r o r de a p e r t u r a d e l f i c h e r o
} else {
unsigned i = 0;
// Para cada e l e m e n t o
while (( i < ag . nelms ) & & ( ! fich . fail ())) { // m i e n t r a s f i c h en buen e s t a d o
e s c r i b i r _ p e r s o n a ( fich , ag . elm [ i ] );
// e s c r i b i r p e r s o n a en f i c h e r o
++i;
}
ok = ! fich . fail ();
// c o r r e c t o s i f l u j o en buen e s t a d o
fich . close ();
// c i e r r a l a v i n c u l a c i o n
}
}
void g uardar _agend a ( const Agenda & ag )
{
bool ok ;
string nombre_fich ;
cout < < " Introduce el nombre del fichero : " ;
cin > > nombre_fich ;
e sc ri b ir _ ag en d a ( 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 ':
e sc ri b ir _ ag en d a ( ag );
break ;
case 'N ':
nueva_persona ( ag );
break ;
112
}
case 'G ':
guar dar_ag enda ( 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 v a c i a
void inic_agenda ( Agenda & ag )
{
ag . nelms = 0;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// anyade una p e r s o n a a l f i n a l de l a agenda
void a ny ad i r_ pe r so na ( 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 s p a c i o s y s a l t o s de l i n e a
getline ( cin , p . nombre ); // l e e una l i n e a c o m p l e t a
cout < < " Introduza edad : " ;
cin > > p . edad ;
// l e e l a edad
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e una p e r s o n a y l a anyade a l a agenda ( supone l e c t u r a c o r r e c t a )
void nueva_persona ( Agenda & ag )
{
bool ok ;
Persona p ;
leer_persona ( p );
a ny ad i r_ p er so n a ( ag , p , ok );
if ( ! ok ) {
cout < < " Error al introducir la nueva persona " < < endl ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e s c r i b i r _ p e r s o n a ( const Persona & p )
{
cout < < " Nombre : " < < p . nombre < < endl ;
cout < < " Edad : " < < p . edad < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
113
// e s c r i b e l a agenda en p a n t a l l a
void e sc ri b ir _a g en da ( const Agenda & ag )
{
for ( unsigned i = 0; i < ag . nelms ; + + i ) {
cout < < " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " < < endl ;
e s c r i b i r _ p e r s o n a ( 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 s p a c i o s y s a l t o s de l i n e a
getline ( fich , p . nombre ); // l e e una l i n e a c o m p l e t a
fich > > p . edad ;
// l e e l a edad
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Otra p o s i b l e i m p l e m e n t a c i o n a l t e r n a t i v a
// v o i d l e e r _ p e r s o n a ( i f s t r e a m& f i c h , Persona& p )
// {
//
g e t l i n e ( f i c h , p . nombre ) ; // l e e una l i n e a c o m p l e t a
//
f i c h >> p . edad ;
// l e e l a edad
//
f i c h . i g n o r e ( 1 0 0 0 , '\ n ' ) ; // e l i m i n a h a s t a 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 e n t r a d a de f i c h e r o
Persona p ;
fich . open ( nombre_fich . c_str ()); // v i n c u l a l a v b l e de f l u j o con e l f i c h e r o
if ( fich . fail ()) {
ok = false ;
// e r r o r de a p e r t u r a d e 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 agenda
leer_persona ( fich , p );
// l e e una p e r s o n a
while ( ! fich . fail () & & ok ) {
// m i e n t r a s l e c t u r a c o r r e c t a
a ny ad i r_ p er so n a ( ag , p , ok ); // anyade p e r s o n a a l a agenda
leer_persona ( fich , p );
// l e e o t r a p e r s o n a
}
ok = ok & & fich . eof ();
// c o r r e c t o s i a l c a n z a d o Fin−De−F i c h e r o
fich . close ();
// c i e r r a l a v i n c u l a c i o n
}
}
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 e s c r i b i r _ p e r s o n a ( ofstream & fich , const Persona & p )
{
fich < < p . nombre < < endl < < p . edad < < endl ;
}
void e sc ri b ir _a g en da ( const string & nombre_fich , const Agenda & ag , bool & ok )
114
{
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 i n c u l a l a v b l e de f l u j o con e l f i c h e r o
if ( fich . fail ()) {
ok = false ;
// e r r o r de a p e r t u r a d e l f i c h e r o
} else {
unsigned i = 0;
// Para cada e l e m e n t o
while (( i < ag . nelms ) & & ( ! fich . fail ())) { // m i e n t r a s f i c h en buen e s t a d o
e s c r i b i r _ p e r s o n a ( fich , ag . elm [ i ] );
// e s c r i b i r p e r s o n a en f i c h e r o
++i;
}
ok = ! fich . fail ();
// c o r r e c t o s i f l u j o en buen e s t a d o
fich . close ();
// c i e r r a l a v i n c u l a c i o n
}
}
void g uardar _agend a ( const Agenda & ag )
{
bool ok ;
string nombre_fich ;
cout < < " Introduce el nombre del fichero : " ;
cin > > nombre_fich ;
e sc ri b ir _ ag en d a ( 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 ':
e sc ri b ir _ ag en d a ( ag );
break ;
case 'N ':
nueva_persona ( ag );
break ;
case 'G ':
guar dar_ag enda ( ag );
break ;
}
} while ( op ! = 'X ' );
}
Solución (C)
# include < iostream >
115
# 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 v a c i a
void inic_agenda ( Agenda & ag )
{
ag . nelms = 0;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// anyade una p e r s o n a a l f i n a l de l a agenda
void a ny ad i r_ pe r so na ( 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 s p a c i o s y s a l t o s de l i n e a
getline ( cin , p . nombre ); // l e e una l i n e a c o m p l e t a
cout < < " Introduza edad : " ;
cin > > p . edad ;
// l e e l a edad
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// l e e una p e r s o n a y l a anyade a l a agenda ( s i l e c t u r a c o r r e c t a )
void nueva_persona ( Agenda & ag )
{
bool ok ;
Persona p ;
leer_persona ( p );
a ny ad i r_ p er so n a ( ag , p , ok );
if ( ! ok ) {
cout < < " Error al introducir la nueva persona " < < endl ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e s c r i b i r _ p e r s o n a ( const Persona & p )
{
cout < < " Nombre : " < < p . nombre < < endl ;
cout < < " Edad : " < < p . edad < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// e s c r i b e l a agenda en p a n t a l l a
void e sc ri b ir _a g en da ( const Agenda & ag )
{
for ( unsigned i = 0; i < ag . nelms ; + + i ) {
cout < < " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " < < endl ;
e s c r i b i r _ p e r s o n a ( ag . elm [ i ] );
}
cout < < " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// FORMATO DEL FICHERO DE ENTRADA:
116
//
// <nombre> <edad> <RC>
// <nombre> <edad> <RC>
//
...
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// b u s c a e l i n d i c e d e l primer d i g i t o en una l i n e a ( s t r i n g )
unsigned bus car_di gitos ( const string & linea )
{
unsigned i = 0;
while (( i < linea . size ()) & & ! isdigit ( linea [ i ] )) {
++i;
}
return i ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// e x t r a e un numero de una cadena a p a r t i r de l a p o s i c i o n i
unsigned 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 i m i n a e s p a c i o s i n i c i a l e s y f i n a l e s en una cadena
void e l i m i n a r _ e s p a c i o s ( 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 , e x t r a e e l nombre y l a edad
void extraer ( const string & linea , string & nombre , unsigned & edad , bool & ok )
{
unsigned i = bu scar_d igitos ( linea );
if ( i > = linea . size ()) {
ok = false ;
} else {
nombre = linea . substr (0 , i );
e l i m i n a r _ e s p a c i o s ( 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 s p a c i o s y s a l t o s de l i n e a
getline ( fich , linea );
// l e e una l i n e a c o m p l e t a
extraer ( linea , p . nombre , p . edad , ok ); // e x t r a e nombre y edad
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void leer_agenda ( const string & nombre_fich , Agenda & ag , bool & ok )
{
ifstream fich ; // f l u j o de e n t r a d a de f i c h e r o
Persona p ;
fich . open ( nombre_fich . c_str ()); // v i n c u l a l a v b l e de f l u j o con e l f i c h e r o
117
if ( fich . fail ()) {
ok = false ;
// e r r o r de a p e r t u r a d e 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 agenda
leer_persona ( fich , p , ok1 );
// l e e una p e r s o n a
while ( ! fich . fail () & & ok1 & & ok2 ) { // m i e n t r a s l e c t u r a c o r r e c t a
a ny ad i r_ p er so n a ( ag , p , ok2 );
// anyade p e r s o n a a l a agenda
leer_persona ( fich , p , ok1 );
// l e e o t r a p e r s o n a
}
ok = ok1 & & ok2 & & fich . eof ();
// c o r r e c t o s i a l c a n z a d o Fin−De−F i c h e r o
fich . close ();
// c i e r r a l a v i n c u l a c i o n
}
}
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 e s c r i b i r _ p e r s o n a ( ofstream & fich , const Persona & p )
{
fich < < p . nombre < < " " < < p . edad < < endl ;
}
void e sc ri b ir _a g en da ( 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 i n c u l a l a v b l e de f l u j o con e l f i c h e r o
if ( fich . fail ()) {
ok = false ;
// e r r o r de a p e r t u r a d e l f i c h e r o
} else {
unsigned i = 0;
// Para cada e l e m e n t o
while (( i < ag . nelms ) & & ( ! fich . fail ())) { // m i e n t r a s f i c h en buen e s t a d o
e s c r i b i r _ p e r s o n a ( fich , ag . elm [ i ] );
// e s c r i b i r p e r s o n a en f i c h e r o
++i;
}
ok = ! fich . fail ();
// c o r r e c t o s i f l u j o en buen e s t a d o
fich . close ();
// c i e r r a l a v i n c u l a c i o n
}
}
void g uardar _agend a ( const Agenda & ag )
{
bool ok ;
string nombre_fich ;
cout < < " Introduce el nombre del fichero : " ;
cin > > nombre_fich ;
e sc ri b ir _ ag en d a ( 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 ;
118
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 ':
e sc ri b ir _ ag en d a ( ag );
break ;
case 'N ':
nueva_persona ( ag );
break ;
case 'G ':
guar dar_ag enda ( ag );
break ;
}
} while ( op ! = 'X ' );
}
119
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 denominador 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 el
cálculo del máximo común divisor (m.c.d.) del numerador y el denominador y su posterior división
por dicho m.c.d.
Para calcular el máximo común divisor de dos numeros enteros positivos n y m, el algoritmo de
Euclides 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 ahora
el valor de r (el resto de la división entera entre n y m calculado anteriormente), y se repite este
proceso 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 ambos
números.
• Para simplificar la determinación del signo de la fracción puede asumirse que el denominador de
la fracción es siempre positivo (por lo que una fracción de signo negativo tendrá un numerador
de 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 en
estado 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, como
sólamente especificando su numerador (en este último caso, se considerará un denominador igual a
1).
Solución: racionales.hpp
# ifndef ra ci o na le s _h pp _
# define ra ci o na le s _h pp _
namespace umalcc {
class Racional {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//~R a c i o n a l ( ) {}
// R a c i o n a l ( c o n s t R a c i o n a l& o ) ;
// R a c i o n a l& o p e r a t o r =( c o n s t R a c i o n a l& o ) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−
Racional () ;
// Construye e l número r a c i o n a l 0 /1
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Racional ( int n ) ;
// Construye e l número r a c i o n a l n/1
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Racional ( int n , int d ) ;
// Construye e l número r a c i o n a l n/d
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool fail () const ;
// D e v u e l v e t r u e s i e l número r a c i o n a l a c t u a l e s t a en e s t a d o e r r o n e o
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void sumar ( const Racional & r1 , const Racional & r2 );
// Asigna a l número r a c i o n a l a c t u a l e l r e s u l t a d o de
// sumar l o s números r a c i o n a l e s ( r1 ) y ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
120
void restar ( const Racional & r1 , const Racional & r2 );
// Asigna a l número r a c i o n a l a c t u a l e l r e s u l t a d o de
// r e s t a r l o s números r a c i o n a l e s ( r1 ) y ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void multiplicar ( const Racional & r1 , const Racional & r2 );
// Asigna a l número r a c i o n a l a c t u a l e l r e s u l t a d o de
// m u l t i p l i c a r l o s números r a c i o n a l e s ( r1 ) y ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void dividir ( const Racional & r1 , const Racional & r2 );
// Asigna a l número r a c i o n a l a c t u a l e l r e s u l t a d o de
// d i v i d i r l o s números r a c i o n a l e s ( r1 ) y ( r2 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void escribir () const ;
// Muestra en p a n t a l l a e l v a l o r d e l número r a c i o n a l a c t u a l
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void leer ();
// Lee de t e c l a d o e l v a l o r d e l número r a c i o n a l a c t u a l
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool igual ( const Racional & r1 ) const ;
// D e v u e l v e t r u e s i e l número r a c i o n a l a c t u a l e s i g u a l a ( r1 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
bool menor ( const Racional & r1 ) const ;
// D e v u e l v e t r u e s i e l número r a c i o n a l a c t u a l e s menor que ( r1 )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void normalizar ();
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
int num ;
// numerador
int denom ; // denominador
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
};
}
# endif
Solución: racionales.cpp
# include " racionales . hpp "
# include < iostream >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Subprogramas A u x i l i a r e s −−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// v a l o r a b s o l u t o de un numero e n t e r o
inline int abs ( int x )
{
if ( x < 0) {
x = -x;
}
return x ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// maximo comun d i v i s o r . a l g o r i t m o de e u c l i d e s
int mcd ( int n , int m )
{
n = abs ( n );
m = abs ( m );
if ( n < m ) {
int x = n ;
n = m;
m = x;
}
while ( m ! = 0) {
121
int r = n % m ;
n = m;
m = r;
}
return n ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// minimo comun m u l t i p l o
// i n l i n e i n t mcm( i n t a , i n t b )
// {
// a = a b s ( a ) ;
// b = a b s ( b ) ;
// r e t u r n ( a / mcd( a , b ) ) ∗ b ;
// }
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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);
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// n o r m a l i z a r un numero r a c i o n a l
void Racional :: normalizar ()
{
if ( denom = = 0) {
// Error denominador c e r o
num = 0;
denom = 0;
} else if ( num = = 0) {
// Forma c a n o n i c a
num = 0;
denom = 1;
} else {
// d i v i d i r numerador y denominador por MCD
int max_com_div = mcd ( num , denom );
num / = max_com_div ;
denom / = max_com_div ;
// s i denominador n e g a t i v o , e n t o n c e s cambiar s i g n o
if ( 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 )
{
//−−−−−−−−−−−−−−−−−−−−−−−−−
122
// 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 e s t a n n o r m a l i z a d o s
return ( 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.
123
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 m u l t i p l i c a c i o n / d i v i s i o n " < < 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 nuevos
métodos añadidos anteriormente.
124
Práctica 3: Tipos Abstractos de Datos (II)
1. Diseñe e implemente un TAD Punto del plano cartesiano, considerando que un Punto describe una determinada posición en el plano cartesiano, especificada por el valor de las componentes X e Y de las
coordenadas cartesianas, y proporciona los siguientes métodos públicos:
Solución: punto.hpp
# ifndef punto_hpp_
# define punto_hpp_
namespace umalcc {
class Punto {
public :
˜ Punto ();
// d e s t r u y e e l o b j e t o a c t u a l y s u s r e c u r s o s a s o c i a d o s .
Punto ();
// c r e a un punto en e l o r i g e n de c o o r d e n a d a s .
Punto ( double x , double y );
// c r e a un punto en l a s c o o r d e n a d a s r e c i b i d a s como p a r a m e t r o s .
Punto ( const Punto & o );
// c r e a un punto c o p i a n d o s u s v a l o r e s d e l o b j e t o r e c i b i d o como
// parametro .
Punto & operator = ( const Punto & o );
// a s i g n a a un o b j e t o punto e l v a l o r de o t r o o b j e t o punto
// r e c i b i d o como parametro .
void desplazar ( double dx , double dy );
// D e s p l a z a e l o b j e t o a c t u a l d e s d e l a p o s i c i o n a c t u a l una
// d e t e r m i n a d a d i s t a n c i a e s p e c i f i c a d a como p a r a m e t r o s en ambos e j e s .
double distancia ( const Punto & o ) const ;
// d e v u e l v e l a d i s t a n c i a a b s o l u t a e n t r e e l o b j e t o a c t u a l y e l
// o b j e t o punto r e c i b i d o como parametro .
double coord_x () const ;
// d e v u e l v e e l v a l o r de l a componente X d e l o b j e t o a c t u a l .
double coord_y () const ;
// d e v u e l v e e l v a l o r de l a componente Y d e l o b j e t o a c t u a 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 ;
}
}
namespace umalcc {
Punto :: ˜ Punto () {}
Punto :: Punto () : x (0) , y (0) {}
Punto :: Punto ( double a , double b ) : x ( a ) , y ( b ) {}
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 ;
}
void Punto :: desplazar ( double dx , double dy ) {
x + = dx ;
y + = dy ;
}
double Punto :: distancia ( const Punto & o ) const {
return sqrt ( sq ( o . y - y ) + sq ( o . x - x ) );
125
}
}
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, considerando que un Segmento es un fragmento de una recta que se encuentra comprendido entre dos Puntos (origen y destino) 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 umalcc {
class Segmento {
public :
˜ Segmento ();
// d e s t r u y e e l o b j e t o a c t u a l y s u s r e c u r s o s a s o c i a d o s .
Segmento ();
// c r e a un o b j e t o Segmento nulo , donde ambos p u n t o s que
// l o d e l i m i t a n s e e n c u e n t r a n en e l o r i g e n de c o o r d e n a d a s .
Segmento ( double x1 , double y1 , double x2 , double y2 );
// c r e a un o b j e t o Segmento según l o s v a l o r e s de l a s 4
// c o o r d e n a d a s de dos p u n t o s e s p e c i f i c a d o s como p a r á m e t r o s .
Segmento ( const Punto & a , const Punto & b );
// c r e a un o b j e t o Segmento según l o s v a l o r e s de dos p u n t o s
// e s p e c i f i c a d o s como p a r á m e t r o s .
Segmento ( const Segmento & o );
// c r e a un Segmento c o p i a n d o s u s v a l o r e s d e l o b j e t o r e c i b i d o
// como parametro .
Segmento & operator = ( const Segmento & o );
// a s i g n a a un o b j e t o Segmento e l v a l o r de o t r o o b j e t o Segmento
// r e c i b i d o como parametro .
void desplazar ( double dx , double dy );
// D e s p l a z a e l o b j e t o a c t u a l d e s d e l a p o s i c i o n a c t u a l una
// d e t e r m i n a d a d i s t a n c i a e s p e c i f i c a d a como p a r a m e t r o s en ambos e j e s .
double longitud () const ;
126
// d e v u e l v e l a l o n g i t u d d e l o b j e t o Segmento .
Punto origen () const ;
// d e v u e l v e e l v a l o r d e l Punto o r i g e n d e l Segmento a c t u a l .
Punto destino () const ;
// d e v u e l v e e l v a l o r d e l Punto d e s t i n o d e l Segmento a c t u a l .
private :
Punto org ;
Punto dst ;
} ;
}
# endif
Solución: segmento.cpp
# include " segmento . hpp "
using namespace std ;
namespace umalcc {
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 & a , const Punto & b )
: org ( a ) , dst ( b ) {}
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 ;
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 ;
cout < < " Destino : " ;
mostrar ( camino . destino ());
cout < < endl ;
cout < < " Longitud : " < < camino . longitud () < < endl ;
}
5. Diseñe e implemente un TAD Polígono del plano cartesiano, considerando que un Polígono es una figura
plana compuesta por una secuencia finita de lados consecutivos determinados por vértices (Puntos) en el
plano cartesiano, y proporciona los siguientes métodos públicos:
127
Solución: poligono.hpp
# ifndef poligono_hpp_
# define poligono_hpp_
# include " punto . hpp "
# include " segmento . hpp "
# include < array >
namespace umalcc {
class Poligono {
public :
˜ Poligono ();
// d e s t r u y e e l o b j e t o a c t u a l y s u s r e c u r s o s a s o c i a d o s .
Poligono ();
// c r e a un o b j e t o P o l i g o n o v a c í o , s i n v é r t i c e s n i l a d o s .
Poligono ( const Poligono & o );
// c r e a un P o l i g o n o c o p i a n d o s u s v a l o r e s d e l o b j e t o r e c i b i d o
// como parametro .
Poligono & operator = ( const Poligono & o );
// a s i g n a a un o b j e t o P o l i g o n o e l v a l o r de o t r o o b j e t o P o l i g o n o
// r e c i b i d o como parametro .
void nuevo_vertice ( const Punto & v );
// a g r e g a un nuevo v é r t i c e a l o b j e t o P o l í g o n o a c t u a l .
void mover_vertice ( int pos , const Punto & v );
// cambia l a p o s i c i o n d e l v e r t i c e e s p e c i f i c a d o en e l primer
// parámetro d e l o b j e t o a c t u a l , por e l nuevo v a l o r
// e s p e c i f i c a d o e l e l segundo parametro .
void desplazar ( double dx , double dy );
// d e s p l a z a e l o b j e t o a c t u a l d e s d e l a p o s i c i ó n a c t u a l una
// d e t e r m i n a d a d i s t a n c i a e s p e c i f i c a d a como p a r á m e t r o s en ambos
// e j e s .
double perimetro () const ;
// d e v u e l v e e l p e r í m e t r o d e l o b j e t o a c t u a l .
Punto vertice ( int pos ) const ;
// d e v u e l v e e l v a l o r d e l v e r t i c e e s p e c i f i c a d o en e l primer
// parámetro .
Segmento lado ( int pos ) const ;
// d e v u e l v e e l v a l o r d e l l a d o e s p e c i f i c a d o en e l primer
// parámetro .
int n_vertices () const ;
// d e v u e l v e e l numero de v e r t i c e s d e l p o l i g o n o a c t u a 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 ;
namespace umalcc {
Poligono :: ˜ Poligono () {}
Poligono :: Poligono () : n_vert (0) , vert () {}
Poligono :: Poligono ( const Poligono & o )
: 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 ;
}
128
}
}
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 );
cout < < " Origen : " ;
mostrar ( camino . vertice (0));
cout < < endl ;
cout < < " Perimetro : " < < camino . perimetro () < < endl ;
}
129
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, especialmente
considerando 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úblicos
que soporten adecuadamente las siguientes operaciones. Diseñe también un programa que permita su
utilización.
Solución: cuenta.hpp
# ifndef cuenta_hpp_
# define cuenta_hpp_
# include < string >
namespace umalcc_1 {
class Cuenta {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//~Cuenta ( ) ;
// Cuenta ( c o n s t Cuenta& o ) ;
// Cuenta& o p e r a t o r =( c o n s t Cuenta& o ) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−
Cuenta () ;
// c r e a una c u e n t a con v a l o r e s por d e f e c t o .
Cuenta ( const std :: string & n , unsigned c , double s ) ;
// c r e a una c u e n t a con l o s v a l o r e s r e c i b i d o s como p a r a m e t r o s .
bool error () const ;
// d e v u e l v e f a l s e s i l a c u e n t a e s c o r r e c t a , y t r u e s i l a c u e n t a
// e s e r r o n e a ( nombre v a c i o o numero de c u e n t a n e g a t i v o o s a l d o
// n e g a t i v o ) .
void mostrar () const ;
// muestra en p a n t a l l a t o d a l a i n f o r m a c i o n a s o c i a d a a l a
// c u e n t a b a n c a r i a . En c a s o de c u e n t a erronea , mostrara un
// mensaje adecuado .
std :: string obtene r_nomb re () const ;
// d e v u e l v e e l v a l o r d e l nombre d e l o b j e t o c u e n t a .
unsigned obt ener_c uenta () const ;
// d e v u e l v e e l v a l o r d e l numero de c u e n t a d e l o b j e t o c u e n t a .
double obtener_saldo () const ;
// d e v u e l v e e l v a l o r d e l s a l d o d e l o b j e t o c u e n t a .
void i ngresa r_sald o ( double inc , bool & ok );
// i n g r e s a r una d e t e r m i n a d a c a n t i d a d de d i n e r o e s p e c i f i c a d a
// como parametro , para sumar a l s a l d o de l a c u e n t a .
void retirar_saldo ( double inc , bool & ok );
// r e t i r a r una d e t e r m i n a d a c a n t i d a d de d i n e r o e s p e c i f i c a d a
// como parametro d e l s a l d o de l a cuenta , c o n s i d e r a n d o que e l
// s a l d o nunca podra s e r n e g a t i v o .
void i n g r e s a r _ i n t e r e s ( double porcentaje , bool & ok );
// i n c r e m e n t a r a e l s a l d o de l a c u e n t a en un d e t e r m i n a d o
// p o r c e n t a j e e s p e c i f i c a d o como parametro .
void r e t i r a r _ c o m i s i o n ( double inc , bool & ok );
// r e t i r a d e l s a l d o una c a n t i d a d e s p e c i f i c a d a como parametro ,
// c o n s i d e r a n d o que s i l a c a n t i d a d a r e t i r a r e s mayor que
// e l s a l d o d i s p o n i b l e , s o l o r e t i r a r a l a c a n t i d a d de s a l d o
// d i s p o n i b l e .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
std :: string nombre ;
unsigned num_cuenta ;
double saldo ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
};
}
# endif
130
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 :: obte ner_no mbre () const
{
return nombre ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned Cuenta :: obt ener_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 :: i ngresa r_sald o ( 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 :: i n g r e s a r _ i n t er e s ( double porcentaje , bool & ok )
{
double cantidad = saldo * porcentaje / 100.0;
ingr esar_s aldo ( cantidad , ok );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Cuenta :: r e t i r a r _ c o m i si o n ( double cantidad , bool & ok )
{
if ( saldo > = cantidad ) {
retirar_saldo ( cantidad , ok );
131
} 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 considerando
múltiples clientes, utilizando para cada uno de ellos el TAD Cuenta, el cual se encargará de la manipulación
de 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. 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úblicos
que 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 P u b l i c o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//~Banco ( ) ;
//Banco ( c o n s t Banco& o ) ;
//Banco& o p e r a t o r =( c o n s t Banco& o ) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−
Banco ();
// c r e a un banco v a c i o , s i n c l i e n t e s , i n i c i a l i z a n d o
// adecuadamente e l c o n t a d o r para a s i g n a r numeros de c u e n t a .
void crear_cuenta ( const std :: string & nombre , unsigned & num , bool & ok );
// c r e a una c u e n t a b a n c a r i a para una d e t e r m i n a d a persona ,
// u t i l i z a n d o su nombre e s p e c i f i c a d o como parametro . El numero
// de c u e n t a s e c a l c u l a a p a r t i r de un v a l o r almacenado en l o s
// a t r i b u t o s d e l banco , que l l e v a una c u e n t a i n c r e m e n t a l de l o s
// numeros de c u e n t a s p r e v i a m e n t e a s i g n a d o s . D e v o l v e r a en un
// parametro de s a l i d a e s t e numero de c u e n t a a s i g n a d o por e l
// banco . S i l a o p e r a c i o n s e r e a l i z o c o r r e c t a o i n c o r r e c t a m e n t e ,
// s e r a n o t i f i c a d o mediante un parametro de s a l i d a .
void e li mi n ar _c u en ta ( unsigned num , bool & ok );
// e l i m i n a una c u e n t a b a n c a r i a a p a r t i r de un numero de c u e n t a
// e s p e c i f i c a d o como parametro . S i l a o p e r a c i o n s e r e a l i z o
// c o r r e c t a o i n c o r r e c t a m e n t e , s e r a n o t i f i c a d o mediante un
// parametro de s a l i d a .
void m os tr a r_ cu e nt as () const ;
// muestra t o d a l a i n f o r m a c i o n almacenada en l a e s t r u c t u r a
// de d a t o s .
void m ostrar _cuent a ( unsigned num , bool & ok ) const ;
// muestra en p a n t a l l a t o d a l a i n f o r m a c i o n a s o c i a d a a l a
// c u e n t a b a n c a r i a cuyo numero de c u e n t a s e e s p e c i f i c a como
// parametro . S i l a o p e r a c i o n s e r e a l i z o c o r r e c t a o
// i n c o r r e c t a m e n t e , s e r a n o t i f i c a d o mediante un parametro de
// s a l i d a .
void m os tr a r_ cu e nt as ( const std :: string & nombre ) const ;
// muestra en p a n t a l l a t o d a l a i n f o r m a c i o n a s o c i a d a a t o d a s
// l a s c u e n t a s b a n c a r i a s de de una p e r s o n a cuyo nombre s e
132
// e s p e c i f i c a como parametro .
void ingreso ( unsigned num , double cantidad , bool & ok );
// i n g r e s a una d e t e r m i n a d a c a n t i d a d de d i n e r o e s p e c i f i c a d a
// como parametro a un d e t e r m i n a d o numero de c u e n t a e s p e c i f i c a d o
// como parametro . S i l a o p e r a c i o n s e r e a l i z o c o r r e c t a o
// i n c o r r e c t a m e n t e , s e r a n o t i f i c a d o 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 d e t e r m i n a d a c a n t i d a d de d i n e r o e s p e c i f i c a d a como
// parametro de un d e t e r m i n a d o numero de c u e n t a e s p e c i f i c a d o como
// parametro , c o n s i d e r a n d o que e l s a l d o nunca podra s e r n e g a t i v o .
// S i l a o p e r a c i o n s e r e a l i z o c o r r e c t a o i n c o r r e c t a m e n t e , s e r a
// n o t i f i c a d o 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 d e t e r m i n a d a c a n t i d a d de d i n e r o e s p e c i f i c a d a
// como parametro d e s d e un numero de c u e n t a o r i g e n a o t r o numero
// de c u e n t a d e s t i n o , ambos e s p e c i f i c a d o s como parametros ,
// c o n s i d e r a n d o que e l s a l d o nunca podra s e r n e g a t i v o . S i l a
// o p e r a c i o n s e r e a l i z o c o r r e c t a o i n c o r r e c t a m e n t e , s e r a
// n o t i f i c a d o mediante un parametro de s a l i d a .
void i n g r e s a r _ i n t e r e s e s ( double porcentaje );
// i n g r e s a l o s i n t e r e s e s en t o d a s l a s c u e n t a s d e l banco , para
// un d e t e r m i n a d o p o r c e n t a j e e s p e c i f i c a d o como parametro .
void g as to s _c om i si on ( double cantidad );
// c a r g a l o s g a s t o s de c o m i s i o n en t o d a s l a s c u e n t a s d e l
// banco , una c a n t i d a d que s e e s p e c i f i c a como parametro . S i
// l a c a n t i d a d a c a r g a r e x c e d e d e l s a l d o que una d e t e r m i n a d a
// c u e n t a posee , e n t o n c e s s e l e r e t i r a r a t o d a l a c a n t i d a d de
// s a l d o que p o s e a .
void g u a r d a r _ c u e n t a s _ f i c h ( const std :: string & nombre_fich , bool & ok ) const ;
// guarda t o d a l a i n f o r m a c i o n almacenada en l a e s t r u c t u r a de
// d a t o s en e l f i c h e r o cuyo nombre s e e s p e c i f i c a como parametro ,
// en un f o r m a t o adecuado para p o s t e r i o r m e n t e pod er r e c u p e r a r l a
// i n f o r m a c i o n almacenada . S i l a o p e r a c i o n s e r e a l i z o c o r r e c t a o
// i n c o r r e c t a m e n t e , s e r a n o t i f i c a d o mediante un parametro de
// s a l i d a .
void c a r g a r _ c u e n t a s _ f i c h ( const std :: string & nombre_fich , bool & ok ) ;
// c a r g a t o d a l a i n f o r m a c i o n de l a e s t r u c t u r a de d a t o s d e s d e
// e l f i c h e r o cuyo nombre s e e s p e c i f i c a como parametro , s i g u i e n d o
// e l f o r m a t o u t i l i z a d o en l a o p e r a c i o n a n t e r i o r . S i l a
// o p e r a c i o n s e r e a l i z o c o r r e c t a o i n c o r r e c t a m e n t e , s e r a
// n o t i f i c a d o mediante un parametro de s a l i d a .
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Ctes y Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
static const unsigned MAX = 256;
typedef std :: array < umalcc_1 :: Cuenta , MAX > Datos ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Metodos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void a nyadir _cuent a ( const umalcc_1 :: Cuenta & cuenta , bool & ok );
void elim_cuenta ( unsigned p , bool & ok );
unsigned buscar ( unsigned num ) const ;
void m o s t r a r _ c u e n t a _ p o s ( unsigned pos ) const ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unsigned cnt_cuentas ;
unsigned ncuentas ;
Datos cuentas ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
};
}
# endif
Solución: banco.cpp
# include " banco . hpp "
# include < iostream >
# include < fstream >
133
# include < cassert >
using namespace std ;
using namespace umalcc_1 ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Subprogramas A u x 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 s p a c i o s y s a l t o s de l i n e a
getline ( fich , nombre ); // l e e e l nombre ( una l i n e a c o m p l e t a )
fich > > cuenta ;
// l e e l a c u e n t a
fich > > saldo ;
// l e e e l s a l d o
c = Cuenta ( nombre , cuenta , saldo );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e sc ri b ir _c u en ta ( ofstream & fich , const Cuenta & c )
{
if ( ! c . error ()) {
fich < < c . obten er_nom bre () < < endl ;
fich < < c . obten er_cue nta () < < endl ;
fich < < c . obtener_saldo () < < endl ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc_2 .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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 )
{
anya dir_cu enta ( Cuenta ( nombre , cnt_cuentas , 0.0) , ok );
if ( ok ) {
num = cnt_cuentas ;
+ + cnt_cuentas ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: el im i na r _c ue n ta ( 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 ] . ingr esar_s aldo ( cantidad , ok );
} else {
ok = false ;
}
}
134
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 s e i n t e n t a r e t i r a r s a l d o , para comprobar
// que hay s u f i c i e n t e s a l d o
cuentas [ po ] . retirar_saldo ( cantidad , ok );
if ( ok ) {
cuentas [ pd ] . in gresar _saldo ( cantidad , ok );
if ( ! ok ) {
cuentas [ po ] . in gresar _saldo ( cantidad , ok );
ok = false ;
}
}
} else {
ok = false ;
}
} else {
ok = false ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: i n g r e s a r _ i n t e r e s e s ( double porcentaje )
{
assert ( porcentaje > 0.0);
bool ok ;
for ( unsigned i = 0; i < ncuentas ; + + i ) {
cuentas [ i ] . i n g r e s ar _ i n t e r e s ( porcentaje , ok );
if ( ! ok ) {
cout < < " Error al ingresar intereses a cuenta : "
< < cuentas [ i ] . obten er_cue nta () < < endl ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: ga st o s_ c om is i on ( double cantidad )
{
assert ( cantidad > 0.0);
bool ok ;
for ( unsigned i = 0; i < ncuentas ; + + i ) {
cuentas [ i ] . r e t i r a r_ c o m i s i o n ( cantidad , ok );
if ( ! ok ) {
cout < < " Error al retirar comisiones a cuenta : "
< < cuentas [ i ] . obten er_cue nta () < < endl ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: mo strar_ cuenta ( unsigned num , bool & ok ) const
{
unsigned p = buscar ( num );
if ( p < ncuentas ) {
m o s t r a r _ c u e n t a _ p o s ( p );
ok = true ;
} else {
ok = false ;
}
}
135
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: mo st r ar _ cu en t as ( const std :: string & nombre ) const
{
for ( unsigned i = 0; i < ncuentas ; + + i ) {
if ( nombre = = cuentas [ i ] . obte ner_no mbre ()) {
m o s t r a r _ c u e n t a _ p o s ( i );
}
}
cout < < " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: mo st r ar _ cu en t as () const
{
for ( unsigned i = 0; i < ncuentas ; + + i ) {
m o s t r a r _ c u e n t a _ p o s ( i );
}
cout < < " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: m o s t r a r _ c u e n t a _ p o s ( unsigned pos ) const
{
assert ( pos < ncuentas );
cout < < " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " < < endl ;
cuentas [ pos ] . mostrar ();
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// FORMATO DEL FICHERO DE ENTRADA:
//
// <cnt_cuentas> <RC>
// <nombre> <RC> <cuenta> <RC> <s a l d o > <RC>
// <nombre> <RC> <cuenta> <RC> <s a l d o > <RC>
//
...
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: c a r g a r _ c u e n t a s _ f i c h ( const std :: string & nombre_fich , bool & ok )
{
ifstream fich ; // f l u j o de e n t r a d a de f i c h e r o
Cuenta c ;
fich . open ( nombre_fich . c_str ()); // v i n c u l a l a v b l e de f l u j o con e l f i c h e r o
if ( fich . fail ()) {
ok = false ;
// e r r o r de a p e r t u r a d e 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 c u e n t a s b a n c a r i a s
fich > > cnt_cuentas ;
// l e e e l c o n t a d o r de c u e n t a s
leer_cuenta ( fich , c );
// l e e una c u e n t a
while ( ! fich . fail () & & ok ) {
// m i e n t r a s l e c t u r a c o r r e c t a
anya dir_cu enta (c , ok );
// anyade c u e n t a a l banco
leer_cuenta ( fich , c );
// l e e o t r a c u e n t a
}
ok = ok & & fich . eof ();
// c o r r e c t o s i a l c a n z a d o Fin−De−F i c h e r o
fich . close ();
// c i e r r a l a v i n c u l a c i o n
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// FORMATO DEL FICHERO DE SALIDA :
//
// <cnt_cuentas> <RC>
// <nombre> <RC> <cuenta> <RC> <s a l d o > <RC>
// <nombre> <RC> <cuenta> <RC> <s a l d o > <RC>
//
...
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: g u a r d a r _ c u e n t a s _ f i c h ( 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 i n c u l a l a v b l e de f l u j o con e l f i c h e r o
if ( fich . fail ()) {
ok = false ;
// e r r o r de a p e r t u r a d e l f i c h e r o
} else {
fich < < cnt_cuentas < < endl ;
// e c r i b e e l c o n t a d o r de c u e n t a s
unsigned i = 0;
// Para cada e l e m e n t o
while (( i < ncuentas ) & & ( ! fich . fail ())) { // m i e n t r a s f i c h en buen e s t a d o
e sc ri b ir _ cu en t a ( fich , cuentas [ i ] );
// e s c r i b i r p e r s o n a en f i c h e r o
136
++i;
}
ok = ! fich . fail ();
fich . close ();
}
// c o r r e c t o s i f l u j o en buen e s t a d o
// c i e r r a l a v i n c u l a c i o n
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Banco :: an yadir_ 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 ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// b u s c a un numero de c u e n t a
unsigned Banco :: buscar ( unsigned num ) const
{
unsigned i = 0;
while (( i < ncuentas )
& & ( num ! = cuentas [ i ] . o btener _cuent a ())) {
++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 l ee r_ n um _c u en ta ( unsigned & n )
{
cout < < " Introduza numero de cuenta : " ;
cin > > n ;
}
void l e e r _ n u m _ c u e n t a _ o ( unsigned & n )
{
cout < < " Introduza numero de cuenta origen : " ;
cin > > n ;
}
void l e e r _ n u m _ c u e n t a _ d ( unsigned & n )
137
{
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 l ee r_ p or ce n ta je ( double & n )
{
do {
cout < < " Introduza porcentaje : " ;
cin > > n ;
} while ( ! ( n > 0.0 & & n < = 100) );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void c a r g a r _ c u e n t a s _ b a n c a r i a s ( Banco & bnk )
{
string nombre_fich ;
bool ok ;
cout < < " Introduce el nombre del fichero : " ;
cin > > nombre_fich ;
bnk . c a r g a r _ c u e n t a s _ f i c h ( nombre_fich , ok );
if ( ! ok ) {
cout < < " Error al cargar datos desde el fichero : "
< < nombre_fich < < endl ;
}
}
void g u a r d a r _ c u e n t a s _ b a n c a r i a s ( const Banco & bnk )
{
string nombre_fich ;
bool ok ;
cout < < " Introduce el nombre del fichero : " ;
cin > > nombre_fich ;
bnk . g u a r d a r _ c u e n t a s _ f i c h ( 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 . mostra r_cuen ta ( ncuenta , ok );
if ( ! ok ) {
cout < < " Error al mostrar cuenta : " < < n < < endl ;
}
} else {
cout < < " Error al crear nueva cuenta para : " < < n < < endl ;
}
}
void e li mi n ar _c u en ta ( Banco & bnk )
{
unsigned n ;
bool ok ;
l ee r_ n um _ cu en t a ( n );
bnk . e li mi n ar _c u en ta (n , ok );
if ( ! ok ) {
cout < < " Error al eliminar cuenta : " < < n < < endl ;
}
}
void i n g r e s a r _ e f e c t i v o ( Banco & bnk )
{
unsigned n ;
138
bool ok ;
double c ;
l ee r_ n um _ cu en t a ( n );
leer_cantidad ( c );
bnk . ingreso (n , c , ok );
if ( ! ok ) {
cout < < " Error al ingresar efectivo en cuenta : " < < n < < endl ;
}
}
void r e t i r a r _ e f e c t i v o ( Banco & bnk )
{
unsigned n ;
bool ok ;
double c ;
l ee r_ n um _ cu en t a ( n );
leer_cantidad ( c );
bnk . retirar (n , c , ok );
if ( ! ok ) {
cout < < " Error al retirar efectivo de cuenta : " < < n < < endl ;
}
}
void t r a n s f e r i r _ e f e c t i v o ( Banco & bnk )
{
unsigned nd , no ;
bool ok ;
double c ;
l e e r _ n u m _ c u e n t a _ d ( nd );
l e e r _ n u m _ c u e n t a _ 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 ;
l ee r_ p or c en ta j e ( p );
bnk . i n g r e s a r _ i n t e r e s e s ( p );
}
void comisiones ( Banco & bnk )
{
double c ;
leer_cantidad ( c );
bnk . g as to s _c om i si on ( c );
}
void m os tr a r_ nc u en ta ( const Banco & bnk )
{
unsigned n ;
bool ok ;
l ee r_ n um _ cu en t a ( n );
bnk . mostra r_cuen ta (n , ok );
if ( ! ok ) {
cout < < " Error al mostrar cuenta : " < < n < < endl ;
}
}
void m ostrar _nombr e ( const Banco & bnk )
{
string n ;
leer_nombre ( n );
bnk . m os tr a r_ cu e nt as ( n );
}
void m o s t r a r _ c o m p l e t o ( const Banco & bnk )
{
bnk . m os tr a r_ cu e nt as ();
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
char menu ()
{
char op ;
cout < < endl ;
cout < < " A . Cargar Cuentas Bancarias " < < endl ;
cout < < " B . Crear Cuenta Bancaria " < < endl ;
139
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
do {
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
"C.
"D.
"E.
"F.
"G.
"H.
"I.
"J.
"K.
"L.
"X.
Eliminar Cuenta Bancaria " < < endl ;
Ingreso de Efectivo en Cuenta Bancaria " < < endl ;
Retirada de Efectivo de Cuenta Bancaria " < < endl ;
Transferencia de Efectivo de Cuenta Bancaria " < < endl ;
Ingresar Intereses en Cuentas Bancarias " < < endl ;
Gastos de Comision de Cuentas Bancarias " < < endl ;
Mostrar Cuentas Bancarias ( num - cuenta ) " < < endl ;
Mostrar Cuentas Bancarias ( nombre ) " < < endl ;
Mostrar Cuentas Bancarias ( completo ) " < < endl ;
Guardar Cuentas Bancarias " < < endl ;
Fin " < < endl ;
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 ':
c a r g a r _ c u e n t a s _ b a n c a r i a s ( bnk );
break ;
case 'B ':
nueva_cuenta ( bnk );
break ;
case 'C ':
e li mi n ar _ cu en t a ( bnk );
break ;
case 'D ':
i n g r e s a r _ e f e c t i v o ( bnk );
break ;
case 'E ':
r e t i r a r _ e f e c t i v o ( bnk );
break ;
case 'F ':
t r a n s f e r i r _ e f e c t i v o ( bnk );
break ;
case 'G ':
intereses ( bnk );
break ;
case 'H ':
comisiones ( bnk );
break ;
case 'I ':
m os tr a r_ n cu en t a ( bnk );
break ;
case 'J ':
most rar_no mbre ( bnk );
break ;
case 'K ':
m o s t r a r _ c o m p l e t o ( bnk );
break ;
case 'L ':
g u a r d a r _ c u e n t a s _ b a n c a r i a s ( 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
permitirá aplicar un determinado interés al saldo, así como cobrar unos gastos de comisión. Considerando
que si la cuenta se encuentra en estado erróneo, la operación será errónea y no se realizará ninguna
operación. Además, si la operación se realizó correcta o incorrectamente, será notificado mediante un
140
pará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á permitir
realizar ingresos y retirar efectivo de una determinada cuenta bancaria, así como realizar transferencias de
efectivo de una cuenta a otra. Además, también permitirá aplicar un determinado interés a los saldos de las
cuentas bancarias existentes, cobrar unos gastos de comisión, y mostrar los datos de las cuentas bancarias
almacenadas (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 nuevos
métodos añadidos anteriormente.
141
Práctica 5: Gestión de Memoria Dinámica
1. 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 un
puntero 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én
un 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 ;
// D e c l a r a c i ó n a d e l a n t a d a d e l t i p o i n c o m p l e t o Nodo
typedef Nodo * PNodo ; // D e f i n i c i ó n de t i p o Puntero a t i p o i n c o m p l e t o Nodo
struct Nodo {
// D e f i n i c i ó n d e l t i p o Nodo
PNodo sig ;
// Enlace a l a s i g u i e n t e e s t r u c t u r a dinámica
int 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 v a c i a
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void destruir ( PNodo & lista ) ;
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l i s t a , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l i s t a ) queda v a c i a
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void i n s e r t a r _ p r i n c i p i o ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o a l p r i n c i p i o de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void i nserta r_fina l ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o a l f i n a l de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo situar ( PNodo lista , int pos ) ;
// D e v u e l v e un p u n t e r o a l nodo que s e e n c u e n t r a en l a p o s i c i o n
// i n d i c a d a por ( pos ) . La p o s i c i o n c e r o ( 0 ) i n d i c a e l primer nodo .
// S i e l nodo no e x i s t e , e n t o n c e s d e v u e l v e NULL
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void insertar_pos ( PNodo & lista , int pos , int dt ) ;
// I n s e r t a en ( l i s t a ) un e l e m e n t o en l a p o s i c i o n i n d i c a d a por ( pos )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e l i m i n a r _ p r i m e r o ( PNodo & lista ) ;
// Elimina e l primer e l e m e n t o de ( l i s t a ) , s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e li mi n ar _u l ti mo ( PNodo & lista ) ;
// Elimina e l u l t i m o e l e m e n t o 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 l e m e n t o de l a p o s i c i o n i n d i c a d a por ( pos ) ,
// s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo duplicar ( PNodo lista ) ;
// D e v u e l v e un p u n t e r o a una nueva l i s t a r e s u l t a d o de d u p 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 p a n t a l l a e l c o n t e n i d o de ( l i s t a )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo leer () ;
// D e v u e l v e una l i s t a con l o s numeros l e i d o s de t e c l a d o ( en e l mismo
// orden que son i n t r o d u c i d o s ) h a s t a que l e a e l numero 0 ( que no e s
// i n t r o d u c i d o )
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
PNodo buscar ( PNodo lista , int dt ) ;
142
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e l e m e n t o
// i g u a l a ( d t ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void insertar_ord ( PNodo & lista , int dt ) ;
// I n s e r t a un e l e m e n t o de forma ordenada en ( l i s t a ) , que d e b e e s t a r ordenada
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void eliminar_elem ( PNodo & lista , int dt ) ;
// Elimina de ( l i s t a ) e l primer e l e m e n t o i g u a l a ( d t ) , s i e x i s t e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void e limina r_mayo r ( PNodo & lista ) ;
// Elimina e l mayor e l e m e n t o 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 ) t o d o s l o s e l e m e n t o s que sean i g u a l e s a ( d t ) ,
// s i e x i s t e n
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
}
# endif
Solución: lista.cpp
# include " lista . hpp "
# include < iostream >
# include < cstddef >
# include < cassert >
using namespace std ;
using namespace umalcc ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e 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 v a c i a
// s e r a i n s e r t a d o en l a l i s t a )
void inicializa ( PNodo & lista )
{
lista = NULL ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e s t r u y e t o d o s l o s e l e m e n t o s de l a l i s t a , l i b e r a n d o
// t o d o s l o s nodos de memoria dinamica . ( l i s t a ) queda v a c i a
void destruir ( PNodo & lista )
{
while ( lista ! = NULL ) {
PNodo ptr = lista ;
lista = lista - > sig ;
delete ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o a l p r i n c i p i o de ( l i s t a )
void i n s e r t a r _ p r i n c i p i o ( PNodo & lista , int dt )
{
PNodo ptr = new Nodo ;
ptr - > dato = dt ;
ptr - > sig = lista ;
lista = ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o a l f i n a l de ( l i s t a )
void i nserta r_fina l ( 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 ) {
143
act = act - > sig ;
}
act - > sig = ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que s e e n c u e n t r a en l a p o s i c i o n
// i n d i c a d a por ( pos ) . La p o s i c i o n c e r o ( 0 ) i n d i c a e l primer nodo .
// S i e l nodo no e x i s t e , e n t o n c e s d e v u e l v e NULL
PNodo situar ( PNodo lista , int pos )
{
PNodo ptr = lista ;
while (( ptr ! = NULL ) & & ( pos > 0)) {
ptr = ptr - > sig ;
- - pos ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a en ( l i s t a ) un e l e m e n t o en l a p o s i c i o n i n d i c a d a 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 e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e l i m i n a r _ p r i m e r o ( PNodo & lista )
{
if ( lista ! = NULL ) {
PNodo ptr = lista ;
lista = lista - > sig ;
delete ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Elimina e l u l t i m o e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e li mi n ar _u l ti mo ( 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 l e m e n t o de l a p o s i c i o n i n d i c a d a por ( pos ) ,
// s i e x i s t e
void eliminar_pos ( PNodo & lista , int pos )
{
if ( lista ! = NULL ) {
if ( pos < 1) {
144
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 ;
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a una nueva l i s t a r e s u l t a d o de d u p 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
PNodo 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 p a n t a l l a e l c o n t e n i d o de ( l i s t a )
void escribir ( PNodo lista )
{
PNodo ptr = lista ;
while ( ptr ! = NULL ) {
cout < < ptr - > dato < < " " ;
ptr = ptr - > sig ;
}
cout < < endl ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e una l i s t a con l o s numeros l e i d o s de t e c l a d o ( en e l mismo
// orden que son i n t r o d u c i d o s ) h a s t a que l e a e l numero 0 ( que no e s
// i n t r o d u c i d o )
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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// D e v u e l v e un p u n t e r o a l nodo que c o n t i e n e e l e l e m e n t o
// i g u a l a ( d t ) . S i no s e e n c u e n t r a , e n t o n c e s d e v u e l v e NULL
PNodo buscar ( PNodo lista , int dt )
{
145
PNodo ptr = lista ;
while (( ptr ! = NULL ) & & ( ptr - > dato ! = dt )) {
ptr = ptr - > sig ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// I n s e r t a un e l e m e n t o de forma ordenada en ( l i s t a ) , que d e b e e s t a r
// ordenada
void 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 e l e m e n t o i g u a l a ( d t ) , s i e x i s t e
void 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 e l e m e n t o de ( l i s t a ) , s i e x i s t e
void e limina r_mayo r ( PNodo & lista )
{
if ( lista ! = NULL ) {
PNodo ant_may = NULL ;
// a n t e r i o r a l mayor
PNodo ptr_may = lista ; // apunta a l mayor
PNodo ant = lista ;
// a n t e r i o r a l p t r
PNodo ptr = lista - > sig ; // p t r de r e c o r r i d o
while ( ptr ! = NULL ) {
if ( ptr - > dato > ptr_may - > dato ) {
// s i e s mayor
ant_may = ant ; // a c t u a l i z a r a n t e r i o r a l mayor
ptr_may = ptr ; // a c t u a l i z a r e l p u n t e r o a l mayor
}
ant = ptr ;
// mover l o s p u n t e r o s de r e c o r r i d o
ptr = ptr - > sig ;
}
if ( ptr_may = = lista ) {
lista = lista - > sig ;
} else {
ant_may - > sig = ptr_may - > sig ;
}
delete ptr_may ;
}
146
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Elimina de ( l i s t a ) t o d o s l o s e l e m e n t o s que sean i g u a l e s a ( d t ) ,
// s i e x i s t e n
void 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 )
{
147
cout < < " Introduzca posicion : " ;
cin > > pos ;
}
void p ru eb a _d up l ic ar ( 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 );
i n s e r t a r _ p r i n c i p i o ( lista , dato );
escribir ( lista );
break ;
case 'C ':
leer ( dato );
inse rtar_f inal ( 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 ':
e l i m i n a r _ p r i m e r o ( lista );
escribir ( lista );
break ;
case 'G ':
e li mi n ar _ ul ti m o ( lista );
escribir ( lista );
break ;
case 'H ':
leer ( pos );
eliminar_pos ( lista , pos ) ;
escribir ( lista );
break ;
case 'I ':
p ru eb a _d u pl ic a r ( lista );
break ;
case 'J ':
escribir ( lista );
break ;
case 'K ':
148
}
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 ':
elim inar_m ayor ( lista );
escribir ( lista );
break ;
case 'P ':
leer ( dato );
purgar ( lista , dato );
escribir ( lista );
break ;
}
} while ( op ! = 'X ' );
destruir ( lista );
149
Práctica 6: Abstracción en la Gestión de Memoria Dinámica (I)
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 () ;
// D e s t r u y e e l o b j e t o y t o d o s s u s r e c u r s o s a s o c i a d o s .
Persona () ;
// Construye una p e r s o n a con nombre y t e l e f o n o v a c í o .
Persona ( const std :: string & n , const std :: string & t ) ;
// Construye una p e r s o n a con e l nombre y e l t e l e f o n o
// segun l o s p a r a m e t r o s r e c i b i d o s .
bool error () const ;
// D e v u e l v e t r u e s i e l o b j e t o a c t u a l e s t a en e s t a d o erroneo ,
// e s d e c i r , e l nombre o e l t e l e f o n o son v a c í o s .
std :: string obtene r_nomb re () const ;
// D e v u e l v e e l v a l o r d e l nombre d e l o b j e t o a c t u a l .
std :: string o b t e n e r _ t el e f o n o () const ;
// D e v u e l v e e l v a l o r d e l t e l e f o n o d e l o b j e t o a c t u a 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 :: obte ner_no mbre () const
{
return nombre ;
}
std :: string Persona :: o b t e n e r _ t e l e f o n o () 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 puede
implementar 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 hash
aplicada al nombre de la persona, y posteriormente se añade la persona a la lista enlazada que se
encuentra 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ón
hash aplicada al nombre de la persona, y se busca la persona en la lista enlazada que se encuentra
en la posición indicada por el número hash calculado (véase ejemplo a continuación).
150
Cuando se quiere borrar a una determinada persona, se calcula el número que proporciona la función
hash aplicada al nombre de la persona, y se elimina la persona con ese nombre de la lista enlazada que
se 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ámetro
especifica 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 ana
proporciona el valor 0, para el nombre juan proporciona el valor 2 y para los nombres lola y jaime
proporciona el valor 4, tendríamos la estructura que se muestra a continuación:
nelms
6
elms
0
pepe
maria
ana
1
30
22
35
lola
jaime
23
37
2
juan
3
27
4
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 () ;
// D e s t r u y e e l o b j e t o y t o d o s s u s r e c u r s o s a s o c i a d o s .
Agenda () ;
// Construye una agenda v a c i a .
Agenda ( const Agenda & o ) ;
// Construye una agenda como c o p i a de o t r a agenda
Agenda & operator = ( const Agenda & o ) ;
// Construye una agenda como c o p i a de o t r a agenda
void anyadir ( const Persona & p );
// S i l a p e r s o n a e s p e c i f i c a d a como parametro no e s t a en modo
// erroneo , s i l a p e r s o n a ya s e e n c o n t r a b a en l a agenda ,
// e n t o n c e s l o s nuevos v a l o r e s de l a p e r s o n a r ee mp la za n a l o s
// a n t e r i o r e s , en o t r o c a s o anyade l a p e r s o n a e s p e c i f i c a d a a
// l a agenda a c t u a l .
Persona buscar ( const std :: string & nombre ) const ;
// Busca en l a agenda l a p e r s o n a cuyo nombre s e e s p e c i f i c a
// como parametro , y s i l a e n c u e n t r a , e n t o n c e s d e v u e l v e un o b j e t o
// Persona con l o s v a l o r e s de l a p e r s o n a almacenados . S i no
// l a e n c u e n t r a , e n t o n c e s d e v u e l v e una p e r s o n a en e s t a d o de
// e r r o r .
void eliminar ( const std :: string & nombre , bool & ok );
// Elimina de l a agenda a c t u a l l a p e r s o n a cuyo nombre s e
// e s p e c i f i c a como parametro y ok tomara e l v a l o r t r u e . En c a s o
// de no e x i s t i r , ok tomara e l v a l o r f a l s e .
void mostrar () const ;
151
// Muestra en p a n t a l l a e l c o n t e n i d o c o m p l e t o 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 i n s e r t a r _ p r i n c i p i o ( 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 ] );
152
}
}
return * this ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Agenda :: anyadir ( const Persona & p )
{
if ( ! p . error ()) {
unsigned h = hash ( p . obte ner_no mbre () , v . size ());
PNodo ptr = buscar ( v [ h ] , p . obten er_nom bre ());
if ( ptr ! = NULL ) {
ptr - > per = p ;
} else {
i n s e r t a r _ p r i n c i p i o ( 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 ;
153
}
return nueva ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Agenda :: PNodo Agenda :: buscar ( PNodo lista , const std :: string & nombre ) const
{
PNodo ptr = lista ;
while (( ptr ! = NULL ) & & ( nombre ! = ptr - > per . obtene r_nomb re ())) {
ptr = ptr - > sig ;
}
return ptr ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Agenda :: i n s e r t a r _ p r i n c i p i o ( 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 . obt ener_n ombre () = = nombre ) {
PNodo ptr = lista ;
lista = lista - > sig ;
delete ptr ;
ok = true ;
} else {
PNodo ant = lista ;
PNodo act = ant - > sig ;
while (( act ! = NULL ) & & ( act - > per . obte ner_no mbre () ! = 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 . obtene r_nomb re () < < " "
< < ptr - > per . ob t e n e r _ t e l e f o n o () < < 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 )
{
154
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 m os tr a r_ pe r so na ( const Persona & p )
{
cout < < " Nombre : " < < p . obtene r_nomb re () < < endl ;
cout < < " telefono : " < < p . o b t e n e r _ t e l e f o n o () < < 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 {
m os tr a r_ p er so n a ( p );
}
break ;
case 'D ':
leer_nombre ( n );
ag . eliminar (n , ok );
if ( ! ok ) {
cout < < " Error , persona no encontrada " < < endl ;
}
break ;
}
} while ( op ! = 'X ' );
}
155
Práctica 7: Abstracción en la Gestión de Memoria Dinámica (II)
1. 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 nulas
no serán almacenadas.
Así, defina la clase MatrizDispersa en el espacio de nombres umalcc_aux que represente dicha abstracción
y 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, se
puede acceder a la lista enlazada ordenada (ascendentemente por número de columna) donde se encuentran
los elementos pertenecientes a dicha fila y a la columna especificada en el nodo cuyo valor es distinto de
cero. Por ejemplo, la siguiente figura representa la siguiente matriz:
nfil
4
ncol
4
filas
0
0 40
1 60
3 90

40 60 0
 0 0 0

 50 0 75
0 67 83
2
0 50
2 75

90
0 

0 
0
3
1 67
2 83
con las siguientes especificaciones adicionales:
El método obtener permite conocer el valor de un determinado elemento de la matriz especificado
por su fila y columna correspondiente. En caso de que dicho elemento no esté almacenado, entonces
su valor es cero.
El método poner permite asignar un determinado valor a un determinado elemento de la matriz
especificado por su fila y columna correspondiente.
Solo se almacenarán los elementos de valor distinto de cero, considerando que si un elemento no
está almacenado, es que su valor es cero. Si una fila no tiene elementos distintos de cero, el nodo
correspondiente 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 otro
caso 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 correspondiente
de dicha lista.
Solución: matdisp.hpp
# ifndef matdisp_hpp_
# define matdisp_hpp_
namespace umalcc_aux {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
const double E R RO R _P RE C IS IO N = 1 e - 6;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
class Ma trizDi spersa {
public :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
˜ Matriz Disper sa ();
// D e s t r u c t o r
Matr izDisp ersa ();
// C o n s t r u c t o r por D e f e c t o : m a t r i z v a c i a
Matr izDisp ersa ( int nfils , int ncols );
// C o n s t r u c t o r e s p e c i f i c o : c r e a m a t r i z de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0
156
Matr izDisp ersa ( const Ma trizDi spersa & m );
// C o n s t r u c t o r de c o p i a
Matr izDisp ersa & operator = ( const Mat rizDis persa & m );
// Operador de A s i g n a c i o n
void clear ( int nfils , int ncols );
// Elimina t o d o s l o s e l e m e n t o s de l a m a t r i z a c t u a l , y a s i g n a
// a l a m a t r i z a c t u a l una m a t r i z de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0
int nfils () const ;
// D e v u e l v e e l numero de f i l a s de l a m a t r i z a c t u a l
int ncols () const ;
// D e v u e l v e e l numero de columnas de l a m a t r i z a c t u a l
void poner ( int f , int c , double val );
// PRECOND: (0 <= f && f < n f i l s ( ) && 0 <= c && c < n c o l s ( ) )
// Asigna e l v a l o r ( v a l ) a l e l e m e n t o de l a f i l a ( f )
// y columna ( c ) de l a m a t r i z a c t u a l
double obtener ( int f , int c ) const ;
// PRECOND: ( f < n f i l s ( ) && c < n c o l s ( ) )
// D e v u e l v e e l v a l o r d e l e l e m e n t o de l a f i l a ( f )
// y columna ( c ) de l a m a t r i z a c t u a l
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Tipos P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ) ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ;
157
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres anonimo . Es una p a r t e p r i v a d a de l a
// i m p l e m e n t a c i o n . No e s a c c e s i b l e d e s d e f u e r a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace {
//−−−−−−−−−−−−−−−−−−−−−−−−−
// Valor a b s o l u t o de un numero
inline 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 a n c i a que l o s
// s e p a r a e s l o s u f i c i e n t e m e n t e pequenya
inline bool iguales ( double a , double b )
{
return abs ( a - b ) < = ER RO R _P RE C IS IO N ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace umalcc_aux {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− Elem −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void M atrizD ispers a :: destruir ( PElem & lista ) const
{
while ( lista ! = NULL ) {
PElem ptr = lista ;
lista = lista - > sig ;
delete ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa :: PElem Matriz Disper sa :: 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa :: PElem Matriz Disper sa :: 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d e v u e l v e e l p u n t e r o a l nodo que ha c r e a d o ( o a l que ya e x i s t i a )
void M atrizD ispers a :: insertar_ord ( PElem & lista , int c , PElem & elem ) const
{
if (( lista = = NULL ) | | ( c < lista - > columna )){
elem = new Elem ;
158
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 {
elem = ant - > sig ;
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void M atrizD ispers a :: 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 ;
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− F i l a −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void M atrizD ispers a :: destruir ( PFila & lista ) const
{
while ( lista ! = NULL ) {
PFila ptr = lista ;
lista = lista - > sig ;
destruir ( ptr - > elems );
delete ptr ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa :: PFila Matriz Disper sa :: 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 ;
159
}
u - > sig = NULL ;
}
return nueva ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa :: PFila Matriz Disper sa :: 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// d e v u e l v e e l p u n t e r o a l nodo que ha c r e a d o ( o a l que ya e x i s t i a )
void M atrizD ispers a :: insertar_ord ( PFila & lista , int f , PFila & elem ) const
{
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 M atrizD ispers a :: 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 ;
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
160
// e l i m i n a e l e l e m e n t o [ f ] [ c ] s i e x i s t e .
// s i f i l a v a c i a , e n t o n c e s e l i m i n a f i l a
void M atrizD ispers a :: 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 ); // a q u i hace r e c o r r i d o d o b l e
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// i n s e r t a r e l e m e n t o [ f ] [ c ] . S i no e x i s t e f i l a , l a c r e a
// s i ya e x i s t e e l elemento , s u s t i t u y e e l v a l o r , en
// o t r o caso , i n s e r t a e l e l e m e n t o
void M atrizD ispers a :: insertar ( int f , int c , double val )
{
assert ( f < nfils () & & c < ncols ());
PFila fil ;
insertar_ord ( filas , f , fil );
PElem elem ;
insertar_ord ( fil - > elems , c , elem );
elem - > valor = val ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− M a t r i z D i s p e r s a −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa :: ˜ Matriz Disper sa () { destruir ( filas ); }
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa :: Matr izDispersa () : nfilas (0) , ncolumnas (0) , filas ( NULL ) {}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa :: Matr izDispersa ( int nf , int nc )
: nfilas ( nf ) , ncolumnas ( nc ) , filas ( NULL ) {}
//−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa :: Matr izDispersa ( const Ma trizDi spersa & m )
: nfilas ( m . nfilas ) , ncolumnas ( m . ncolumnas ) , filas ( duplicar ( m . filas )) {}
//−−−−−−−−−−−−−−−−−−−−−−−−−
Matr izDisp ersa & Mat rizDis persa :: operator = ( const Mat rizDis persa & m )
{
if ( this ! = & m ) {
destruir ( filas );
nfilas = m . nfilas ;
ncolumnas = m . ncolumnas ;
filas = duplicar ( m . filas );
}
return * this ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−
void M atrizD ispers a :: clear ( int nf , int nc )
{
destruir ( filas );
nfilas = nf ;
ncolumnas = nc ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
int Matriz Disper sa :: nfils () const
{
return nfilas ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
int Matriz Disper sa :: ncols () const
{
return ncolumnas ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// poner un v a l o r en [ f ] [ c ] , s i v a l e s cero , e n t o n c e s l o e l i m i n a
void M atrizD ispers a :: poner ( int f , int c , double val )
{
assert ( f < nfils () & & c < ncols ());
if ( iguales ( val , 0.0)) {
eliminar (f , c );
} else {
161
}
}
insertar (f ,c , val );
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// b u s c a e l elemento , s i no e x i s t e , e n t o n c e s v a l o r c e r o
// en o t r o caso , d e v u e l v e e l v a l o r d e l e l e m e n t o
double Matr izDisp ersa :: 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 ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
2. 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ón
la 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 :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// ~M a t r i z ( ) ;
// D e s t r u c t o r
Matriz ();
// C o n s t r u c t o r por D e f e c t o : m a t r i z v a c i a
Matriz ( int nfils , int ncols );
// C o n s t r u c t o r e s p e c i f i c o : c r e a m a t r i z de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0
// M a t r i z ( c o n s t M a t r i z& m) ;
// C o n s t r u c t o r de c o p i a
// M a t r i z& o p e r a t o r =( c o n s t M a t r i z& m) ;
// Operador de A s i g n a c i o n
void clear ( int nfils , int ncols );
// Elimina t o d o s l o s e l e m e n t o s de l a m a t r i z a c t u a l , y a s i g n a
// a l a m a t r i z a c t u a l una m a t r i z de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0
int nfils () const ;
// D e v u e l v e e l numero de f i l a s de l a m a t r i z a c t u a l
int ncols () const ;
// D e v u e l v e e l numero de columnas de l a m a t r i z a c t u a l
void poner ( int f , int c , double val );
// PRECOND: (0 <= f && f < n f i l s ( ) && 0 <= c && c < n c o l s ( ) )
// Asigna e l v a l o r ( v a l ) a l e l e m e n t o de l a f i l a ( f )
// y columna ( c ) de l a m a t r i z a c t u a l
double obtener ( int f , int c ) const ;
// PRECOND: ( f < n f i l s ( ) && c < n c o l s ( ) )
// D e v u e l v e e l v a l o r d e l e l e m e n t o de l a f i l a ( f )
// y columna ( c ) de l a m a t r i z a c t u a l
void sumar ( const Matriz & a , const Matriz & b );
// Asigna a l a m a t r i z a c t u a l e l r e s u l t a d o de
// sumar l a s m a t r i c e s ( a ) y ( b )
void restar ( const Matriz & a , const Matriz & b );
// Asigna a l a m a t r i z a c t u a l e l r e s u l t a d o de
// r e s t a r l a s m a t r i c e s ( a ) y ( b )
void multiplicar ( const Matriz & a , const Matriz & b );
// Asigna a l a m a t r i z a c t u a l e l r e s u l t a d o de
// m u l t i p l i c a r l a s m a t r i c e s ( a ) y ( b )
void escribir () const ;
// Muestra en p a n t a l l a e l c o n t e n i d o de l a m a t r i z a c t u a l
162
void leer ();
// Lee de t e c l a d o e l v a l o r de l a m a t r i z a c t u a l ,
// Lee n f i l s , n c o l s y l o s v a l o r e s de l o s e l e m e n t o s
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
private :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−− A t r i b u t o s P r i v a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
umalcc_aux :: Matriz Disper sa base ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
};
}
# endif
Solución: matriz.cpp
# include " matriz . hpp "
# include < iostream >
# include < iomanip >
# include < cassert >
# include " matdisp . hpp "
using namespace std ;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// E s p a c i o de nombres umalcc .
// Aqui r e s i d e l a i m p l e m e n t a c i o n de l a p a r t e p u b l i c a d e l modulo
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
namespace umalcc {
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Generados automaticamente por e l c o m p i l a d o r
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// ~M a t r i z ( ) ;
// D e s t r u c t o r
// M a t r i z ( c o n s t M a t r i z& m) ;
// C o n s t r u c t o r de c o p i a
// M a t r i z& o p e r a t o r =( c o n s t M a t r i z& m) ;
// Operador de A s i g n a c i o n
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 ) {
163
}
}
}
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 ));
}
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 columnas
clear ( nf , nc );
for ( int f = 0; f < nfils (); + + f ) {
for ( int c = 0; c < ncols (); + + c ) {
double x ;
cin > > x ; // l e e cada e l e m e n t o de l a m a t r i z
poner (f ,c , x );
}
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
3. Implemente un programa principal que permita comprobar el funcionamiento del tipo abstracto de datos
Matriz definido previamente.
Solución: main.cpp
164
# 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 < < " Multip licaci on : " < < endl ;
m5 . escribir ();
165
Práctica 8: Introducción a la Programación Orientada a Objetos
1. Se desea implementar una jerarquía de elementos gráficos como la de la siguiente figura:
ElementoGrafico
Punto
Linea
LineaVertical
Cuadrado
LineaHorizontal
La clase polimórfica ElementoGrafico representa un elemento gráfico que puede imprimirse por
pantalla. Tiene un constructor por defecto que permite crear el objeto y proporciona los siguientes
mé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 el
elemento 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 crear
el 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, que
puede imprimirse en pantalla. Suministra un constructor por defecto para crear la línea e inicializarla
con 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 para
escribir 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 concreto
una 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 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 horizontal en pantalla de la longitud almacenada en su estado: se
deben escribir en pantalla tantos caracteres ’-’ como indique su longitud, seguidos por un salto
de línea.
La clase polimórfica LineaVertical representa a un elemento gráfico especializado, en concreto una
línea vertical, que puede imprimirse en pantalla (como una secuencia de caracteres ’|’ dispuestos
verticalmente, es decir, separados por un ’\n’). Suministra un constructor por defecto para crear
la línea e inicializarla con 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.
166
• pintar(): pinta una línea vertical en pantalla de la longitud almacenada en su estado: se deben
escribir en pantalla tantos caracteres ’|’ seguidos de saltos de línea como indique su longitud.
La clase polimórfica Cuadrado representa a un elemento gráfico especializado, en concreto un cuadrado, que puede imprimirse en pantalla (empleando caracteres |, ’-’, ’ ’ y ’\n’ dispuestos en pantalla
de manera que simulen los lados de un cuadrado). Suministra un constructor por defecto para crear
el cuadrado e inicializar su lado a cero y un constructor extendido que inicializa el cuadrado con un
determinado 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 recibida
como parámetro.
Desarrolle un programa principal que declare un array de objetos polimórficos de las distintas clases
polimórficas (Punto, LineaHorizontal, LineaVertical y Cuadrado) de la jerarquía de ElementoGrafico
y los escriba en pantalla invocando al método virtual pintar().
Solución: elemento_grafico.hpp
# ifndef e l e m e n t o _ g r a f i c o _ h p p _ _
# define e l e m e n t o _ g r a f i c o _ h p p _ _
namespace umalcc {
class El em e nt o Gr af i co {
public :
E le me n to G ra fi c o ();
virtual ˜ E l em en t oG ra fic o ();
virtual void pintar () const ;
virtual El e me nt o Gr af i co * clonar () const ;
protected :
E le me n to G ra fi c o ( const El em e nt oG r af i co & o );
private :
E le me n to G ra fi c o & operator = ( const El e me nt o Gr af i co & o );
};
}
# endif
Solución: elemento_grafico.cpp
# include " e l e m e n t o _ g r a f i c o . hpp "
namespace umalcc {
E le me n to G ra fi c o :: E le m en t oGra f ic o () {}
E le me n to G ra fi c o :: ˜ El e me n to Gr a fi co () {}
void E le me n to Gr a fi co :: pintar () const {}
E le me n to G ra fi c o * E l em en t oG ra f ic o :: clonar () const
{
return new E l em e nt oG r af ic o ( * this );
}
}
E le me n to G ra fi c o :: E le m en t oGra f ic o ( const El e me nt o Gr a fi co & o ) { ( void ) o ; }
Solución: punto.hpp
# ifndef punto_hpp__
# define punto_hpp__
# include " e l e m e n t o _ g r a f i c o . hpp "
namespace umalcc {
class Punto : public El e ment o Gr af i co {
public :
Punto ();
167
virtual ˜ Punto ();
virtual void pintar () const ;
virtual Punto * clonar () const ;
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 () : E l em e nt oGr af ic o () {}
Punto :: ˜ Punto () {}
void Punto :: pintar () const
{
cout < < " . " < < endl ;
}
Punto * Punto :: clonar () const
{
return new Punto ( * this );
}
}
Punto :: Punto ( const Punto & o ) : E le m en to G ra fi c o ( o ) {}
Solución: linea.hpp
# ifndef linea_hpp__
# define linea_hpp__
# include " e l e m e n t o _ g r a f i c o . hpp "
namespace umalcc {
class Linea : public El e ment o Gr af i co {
public :
Linea ();
Linea ( unsigned l );
virtual ˜ Linea ();
virtual unsigned c o n s ul t a r _ l o n g i t u d () const ;
virtual void c a m b i a r _ l o n g i t u d ( 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 () : E l em e nt oGr af ic o () , longitud (0) {}
Linea :: Linea ( unsigned l ) : E le m en to G ra fi c o () , longitud ( l ) {}
168
Linea :: ˜ Linea () {}
unsigned Linea :: c o n s u l t a r _ l o n g i t u d () const
{
return longitud ;
}
void Linea :: c a m b i a r _ l o n g i t u d ( unsigned l )
{
longitud = l ;
}
Linea * Linea :: clonar () const
{
return new Linea ( * this );
}
}
Linea :: Linea ( const Linea & o ) : E le m en to G ra fi c o ( o ) , longitud ( o . longitud ) {}
Solución: linea_horizontal.hpp
# ifndef l i n e a _ h o r i z o n t a l _ h p p _ _
# define l i n e a _ h o r i z o n t a l _ h p p _ _
# include " linea . hpp "
namespace umalcc {
class Li ne a Ho r iz on t al : public Linea {
public :
L in ea H or i zo nt a l ();
L in ea H or i zo nt a l ( unsigned l );
virtual ˜ L i ne aH o ri zo nta l ();
virtual void pintar () const ;
virtual Li n ea Ho r iz on t al * clonar () const ;
protected :
L in ea H or i zo nt a l ( const Li ne a Ho ri z on t al & o );
private :
L in ea H or i zo nt a l & operator = ( const Li n ea Ho r iz on t al & o );
};
}
# endif
Solución: linea_horizontal.cpp
# include " l i n e a _ h o r i z o n t a l . hpp "
# include < iostream >
using namespace std ;
namespace umalcc {
L in ea H or i zo nt a l :: L in e aH o rizo n ta l () : Linea () {}
L in ea H or i zo nt a l :: L in e aH o rizo n ta l ( unsigned l ) : Linea ( l ) {}
L in ea H or i zo nt a l :: ˜ Li n ea H or iz o nt al () {}
void L in ea H or iz o nt al :: pintar () const
{
for ( unsigned i = 0; i < c o n s u l t a r _ l o n g i t u d (); i + + ) {
cout < < " -" ;
}
cout < < endl ;
}
L in ea H or i zo nt a l * L i ne aH o ri zo n ta l :: clonar () const
{
return new L i ne a Ho ri z on ta l ( * this );
}
L in ea H or i zo nt a l :: L in e aH o rizo n ta l ( const Li n ea Ho r iz o nt al & o ): Linea ( o ) {}
169
}
Solución: linea_vertical.hpp
# ifndef l i n e a _ v e r t i c a l _ h p p _ _
# define l i n e a _ v e r t i c a l _ h p p _ _
# 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_ vertic al . 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 < c o n s u l t a r _ l o n g i t u d (); i + + ){
cout < < " | " < < endl ;
}
}
LineaVertical * LineaVertical :: clonar () const
{
return new LineaVertical ( * this );
}
}
LineaVertical :: LineaVertical ( const LineaVertical & o ) : Linea ( o ) {}
Solución: cuadrado.hpp
# ifndef cua drado_ hpp__
# define cua drado_ hpp__
# include " e l e m e n t o _ g r a f i c o . hpp "
namespace umalcc {
class Cuadrado : public E l em en t oG r af ic o {
public :
Cuadrado ();
Cuadrado ( unsigned l );
virtual ˜ Cuadrado ();
virtual unsigned consul tar_la do () const ;
virtual void asignar_lado ( unsigned l );
virtual void pintar () const ;
170
virtual Cuadrado * clonar () const ;
protected :
Cuadrado ( const Cuadrado & o );
private :
unsigned lado ;
//−−
Cuadrado & operator = ( const Cuadrado & o );
};
}
# endif
Solución: cuadrado.cpp
# include " cuadrado . hpp "
# include < iostream >
using namespace std ;
namespace umalcc {
Cuadrado :: Cuadrado () : E lem en to G ra fi c o () , lado (0) {}
Cuadrado :: Cuadrado ( unsigned l ) : El em e nt o Gr af i co () , lado ( l ) {}
Cuadrado :: ˜ Cuadrado () {}
void Cuadrado :: asignar_lado ( unsigned l )
{
lado = l ;
}
unsigned Cuadrado :: consul tar_la do () const
{
return lado ;
}
void Cuadrado :: pintar () const
{
// l a d o s u p e r i o r
for ( unsigned i = 0; i < lado ; i + + ){
cout < < " -" ;
}
cout < < endl ;
// l a d o s l a t e r a l e s
for ( unsigned i = 0; i < lado - 2; i + + ){
cout < < " | " ;
for ( unsigned j = 0; j < lado - 2; j + + ){
cout < < " " ;
}
cout < < " | " < < endl ;
}
// l a d o i n f e r i o r
for ( unsigned i = 0; i < lado ; i + + ){
cout < < " -" ;
}
cout < < endl ;
}
Cuadrado * Cuadrado :: clonar () const
{
return new Cuadrado ( * this );
}
}
Cuadrado :: Cuadrado ( const Cuadrado & o ) : El em e nt oG r af ic o ( o ) , lado ( o . lado ) {}
# include
# include
# include
# include
# include
Solución: main.cpp
" e l e m e n t o _ g r a f i c o . hpp "
" punto . hpp "
" l i n e a _ h o r i z o n t a l . hpp "
" linea_ vertic al . hpp "
" cuadrado . hpp "
171
# include < iostream >
# include < array >
using namespace std ;
using namespace umalcc ;
const int MAX = 4;
typedef array < E le m en t oG ra f ic o * , MAX > AEGraficos ;
int main ()
{
AEGraficos lista ;
lista [ 0 ]
lista [ 1 ]
lista [ 2 ]
lista [ 3 ]
=
=
=
=
new
new
new
new
Punto ;
L in e aH or i zont a l (10);
LineaVertical (5);
Cuadrado (6);
for ( unsigned i = 0; i < lista . size (); i + + ){
lista [ i ] - > pintar ();
}
for ( unsigned i = 0; i < lista . size (); i + + ){
delete lista [ i ] ;
}
}
2. 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 especializados (clases derivadas de Robot) en el ensamblaje de cada una de las piezas que componen el Androide
final, tal como la cabeza, el tronco, los brazos y las piernas. Además, también se dispone de un robot que
permite ensamblar la identificación de cada androide ensamblado.
Robot
RIdent
RCabeza
RTronco
RBrazos
RPiernas
En este primer ejercicio, el soporte donde ensamblar el androide es un simple string, donde se pueden ir
añadiendo las piezas que ensambla cada robot. Así, con objeto de simplificar el proceso y enfocar en los
conceptos de POO (herencia, polimorfismo y vinculación dinamica), cada robot especializado ensambla
una determinada pieza, representada por el caracter de su inicial: C, T, B, P, de una forma muy simple
en el objeto a construir, añadiendo simplemente el carácter que representa a la pieza al objeto de tipo
string. Por ejemplo, los dos primeros androides completamente ensamblados serían dos string con los
valores "ID1:CTBP" e "ID2:CTBP", considerando que cada identificación irá incrementando el valor de un
número de serie (contador).
La clase polimórfica Robot representa un robot general de ensamblaje, tiene un constructor por
defecto 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ámetro
de entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación de
ensamblaje se ha realizado correctamente. Las clases derivadas deberán redefinir este método
para 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 un
androide (un símbolo inicial de identificación, seguido por un número de serie y del símbolo dospuntos), 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.
172
• 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 de
ensamblaje se ha realizado correctamente. Este método asigna la secuencia de identificación (el
símbolo, el número de serie y los dos puntos) al objeto que se está ensamblando, y posteriormente
incrementará 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 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ámetro
de entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación de
ensamblaje se ha realizado correctamente. Este método añade el símbolo de la cabeza (C) al
objeto 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 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ámetro
de entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación de
ensamblaje se ha realizado correctamente. Este método añade el símbolo del tronco (T) al objeto
que se está ensamblando.
La clase polimórfica RBrazos representa un robot especializado en ensamblar los brazos de un androide (un carácter B), tiene un constructor por defecto 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ámetro
de entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación de
ensamblaje se ha realizado correctamente. Este método añade el símbolo de los brazos (B) al
objeto que se está ensamblando.
La clase polimórfica RPiernas representa un robot especializado en ensamblar las piernas de un
androide (un carácter P), tiene un constructor por defecto 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ámetro
de entrada/salida, y un parámetro ok, de tipo bool, de salida, para devolver si la operación de
ensamblaje se ha realizado correctamente. Este método añade el símbolo de las piernas (P) al
objeto que se está ensamblando.
Finalmente, el programa principal creará los 5 robots de ensamblaje especializados necesarios, los
almacenará 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 cantidad
de androides, considerando que cada objeto a ensamblar se va pasando de robot en robot en la cadena
de 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 );
173
};
}
# 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;
} 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 );
174
}
}
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 :
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
175
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 ) {}
}
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 ;
176
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 + = " P " ;
ok = true ;
}
RPiernas :: RPiernas ( const RPiernas & r ) : Robot ( r ) {}
}
Solución: main.cpp
# include < iostream >
# include < string >
# include < array >
# include
# include
# include
# include
# include
# include
" robot . hpp "
" rident . hpp "
" rcabeza . hpp "
" rtronco . hpp "
" rbrazos . hpp "
" 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 ] ;
}
177
}
3. 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:
ID1
o
/|\
/ \
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 {
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 ;
178
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 + " \ 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 );
179
}
}
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 () ;
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
180
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 );
}
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 ) {}
}
181
Solución: main.cpp
# include < iostream >
# include < string >
# include < array >
# include
# include
# include
# include
# include
# include
" robot . hpp "
" rident . hpp "
" rcabeza . hpp "
" rtronco . hpp "
" rbrazos . hpp "
" 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 ] ;
}
}
4. 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 el
ensamblaje de piezas (de tipo string) en determinadas posiciones (fila y columna) de un plano-2D (un
array 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 ensamblar
las piezas adecuadas en este Objeto2D, pudiéndose mostrar el resultado final.
ID1
o
/|\
/ \
La clase no-polimórfica Objeto2D representa una superficie 2D donde es posible ensamblar piezas
diversas (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, y
proporciona los siguientes métodos públicos:
• Tanto el constructor de copia, como el operador de asignación serán generados automáticamente
por el compilador.
• id(i): recibe como parámetro y almacena el identificador asociado al objeto que se está ensamblando.
• id(): devuelve el identificador que ha sido previamente asignado al objeto actual.
182
• 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 objeto
ensamblado.
• ensamblar_pieza(f, c, p, ok): recibe la fila y columna indicando la posición donde ensamblar
la pieza (string) recibida como tercer parámetro, y si todo es correcto, situa cada carácter de la
pieza en el sitio especificado. Finalmente, un parámetro ok, de tipo bool, de salida, indicará si la
operación de ensamblaje se ha realizado correctamente. Además, es deseable que vaya registrando
el tamaño del objeto que se está ensamblando.
Solución: objeto2d.hpp
# ifndef objeto2d_hpp_
# define objeto2d_hpp_
# include < string >
# include < array >
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 ( c o n s t Objeto2D& o ) ; // g e n e r a d o automaticamente
// Objeto2D& o p e r a t o r =( c o n s t Objeto2D& o ) ; // g e n e r a d o automaticamente
void id ( const std :: string & i ) ;
std :: string id () const ;
void e ns am b la r_ p ie za ( 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 :: e n sa mb l ar _pi ez a ( 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 ) {
183
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 ;
}
}
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_
184
# 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
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
185
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 . e ns a mb l ar _p i ez a (0 , 1 , " o " , ok );
}
RCabeza :: RCabeza ( const RCabeza & r ) : Robot ( r ) {}
}
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 . e ns a mb l ar _p i ez a (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 ;
186
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 );
}
void RBrazos :: ensamblar ( Objeto2D & objeto , bool & ok )
{
objeto . e ns a mb l ar _p i ez a (1 , 0 , " / " , ok );
if ( ok ) { objeto . e ns a mb l ar _p i ez a (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 . e ns a mb l ar _p i ez a (2 , 0 , " / " , ok );
if ( ok ) { objeto . e ns a mb l ar _p i ez a (2 , 2 , " \\ " , ok ); }
}
RPiernas :: RPiernas ( const RPiernas & r ) : Robot ( r ) {}
}
187
Solución: main.cpp
# include < iostream >
# include < string >
# include < array >
# include
# include
# include
# include
# include
# include
# include
" objeto2d . hpp "
" robot . hpp "
" rident . hpp "
" rcabeza . hpp "
" rtronco . hpp "
" rbrazos . hpp "
" 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 ;
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 ] ;
}
}
5. 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 Objeto2D
entre 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ón
fuera de la factoría.
La clase no-polimórfica Factoria representa una factoría con un almacen de como máximo 10
Objeto2D ensamblados, y una cadena de Robot con los 5 robots de ensamblaje especializados, tiene
un constructor que permite crear un objeto con el símbolo inicial de identificación (string) recibido
como parámetro, de tal forma que todos los androides ensamblados tendrán el mismo símbolo base
de identificación y construye los 5 robots especializados en la cadena de ensamblaje. Además, la clase
proporciona los siguientes métodos públicos:
• Se debe implementar el constructor de copia y el operador de asignación, que permitan copiar
la estructura de datos de la clase.
• construir(ok): si hay espacio en el almacen, entonces ensambla completamente un nuevo androide y lo almacena adecuadamente. Si la operación es posible o no, entonces devuelve true o
false, respectivamente, en el parámetro de salida.
• mostrar_almacen(): muestra en pantalla a todos los androides ensamblados que se encuentran
en el almacen.
188
• obtener_nobjs(): devuelve la cantidad de androides ensamblados que se encuentran en el almacen.
• extraer(): extrae del almacen y devuelve un Objeto2D con un androide ensamblado que se
encuentre en el almacen. Si no hay ningún androide ensamblado en el almacen, entonces devuelve
un Objeto2D vacío.
El programa principal creará una factoría, y construirá adecuadamente una determinada cantidad de
androides, que serán almacenados en el almacen de la factoría. Finalmente, extraerá los androides
almacenados 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Ó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 ( c o n s t Objeto2D& o ) ; // g e n e r a d o automaticamente
// Objeto2D& o p e r a t o r =( c o n s t Objeto2D& o ) ; // g e n e r a d o automaticamente
void id ( const std :: string & i ) ;
std :: string id () const ;
void e ns am b la r_ p ie za ( 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 :: e n sa mb l ar _pi ez a ( 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;
}
189
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 ;
}
}
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
190
# 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
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
191
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 . e ns a mb l ar _p i ez a (0 , 1 , " o " , ok );
}
RCabeza :: RCabeza ( const RCabeza & r ) : Robot ( r ) {}
}
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 . e ns a mb l ar _p i ez a (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 ;
192
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 );
}
void RBrazos :: ensamblar ( Objeto2D & objeto , bool & ok )
{
objeto . e ns a mb l ar _p i ez a (1 , 0 , " / " , ok );
if ( ok ) { objeto . e ns a mb l ar _p i ez a (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 . e ns a mb l ar _p i ez a (2 , 0 , " / " , ok );
if ( ok ) { objeto . e ns a mb l ar _p i ez a (2 , 2 , " \\ " , ok ); }
}
RPiernas :: RPiernas ( const RPiernas & r ) : Robot ( r ) {}
}
193
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ÓRFICA
static 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 ) ;
Factoria & operator = ( const Factoria & o );
void construir ( bool & ok ) ;
void m os tr a r_ al m ac en () const ;
unsigned obtener_nobjs () const ;
Objeto2D extraer () ;
private :
void clonar_robots ( const Factoria & o ) ;
void copiar_objs ( const Factoria & o ) ;
void d es tr u ir _r o bo ts () ;
void d e s t r u i r _ a l m a c e n () ;
};
}
# 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 ()
{
d es tr u ir _ ro bo t s ();
}
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 ) {
d es tr u ir _ ro bo t s ();
copiar_objs ( o );
clonar_robots ( o );
}
return * this ;
}
void Factoria :: construir ( bool & ok )
{
194
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 :: m o st ra r _a lma ce n () const
{
for ( unsigned j = 0; j < nobjs ; + + j ) {
almacen [ j ] . mostrar ();
}
}
unsigned Factoria :: obtener_nobjs () const
{
return nobjs ;
}
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 :: d e st ru i r_ rob ot s ()
{
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 ) {
195
}
}
cout < < " Error de construcción " < < endl ;
}
while ( factoria . obtener_nobjs () > 0) {
Objeto2D obj = factoria . extraer ();
cout < < " Androide : " ;
obj . mostrar ();
}
196
Práctica 9: La Clase Vector de la Biblioteca Estándar
1. Defina e implemente la clase Hotel (dentro del espacio de nombres umalcc) que defina las siguientes estructuras de datos y proporcione los siguientes métodos públicos para gestionar la ocupación de habitaciones
y 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 del
cliente (cadena de caracteres) que se encuentra alojado.
Hotel
habitaciones
0
0
nombre
1
···
2
···
1
···
···
···
2
···
···
···
3
···
···
···
4
···
···
···
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 tal
forma que el vector que representa las habitaciones del hotel se creará con tantas filas como indique el
pará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 formato
adecuadamente legible.
d ) Alojar(⇓ nombre, ⇑ planta, ⇑ n_hab, ⇑ ok):
Comprueba si hay habitaciones disponibles, en cuyo caso alojará adecuadamente a dicho cliente en alguna
habitación que no esté ocupada. ok tomará el valor true, y planta y n_hab tomarán el valor de la planta
y 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 determinada
habitación, lo desalojará de ella borrando su nombre (a ""), y ok tomará el valor true. En otro caso, ok
tomará el valor false.
Notas:
a)
b)
c)
d)
⇓ Especifica un parámetro de entrada y ⇑ especifica un parámetro de salida.
El parámetro nombre es de tipo “cadena de caracteres”.
El parámetro ok es de tipo “lógico” (“boolean”).
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 :
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// ~ H o t e l ( ) {}
// D e s t r u c c i o n por d e f e c t o
Hotel ( unsigned n_plantas , unsigned n_habs );
void Mostrar () const ;
void Alojar ( const std :: string & nombre ,
unsigned & planta , unsigned & n_hab , bool & ok );
197
void Desalojar ( const std :: string & nombre , bool & ok );
void A nyadir _Plant a ( bool & ok );
void E li mi n ar _P l an ta ( bool & ok );
void E x t e n d e r _ H a b i t a c i o n e s ( 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 b u s c a r _ h a b _ l i b r e ( 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;
198
}
}
ok = ( f < hab . size ());
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Hotel :: b u s c a r _ h a b _ l i b r e ( 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 )
{
b u s c a r _ h a b _ l i b r e ( 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 :: An yadir_ 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
//
F i 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 :: El im i na r _P la n ta ( bool & ok )
{
ok = false ;
if (( hab . size () > 1) & & ( planta_vacia ( hab . size () - 1))) {
hab . pop_back ();
ok = true ;
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
void Hotel :: E x t e n d e r _ H a b i t a c i o n e s ( 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.
199
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 ;
200
}
case 'C ':
leer_cliente ( nombre );
hotel . Desalojar ( nombre , ok );
check_ok ( ok , " Desalojar " );
break ;
case 'D ':
hotel . Any adir_P lanta ( ok );
check_ok ( ok , " Añadir_Planta " );
break ;
case 'E ':
hotel . El im i na r_ P lant a ( ok );
check_ok ( ok , " El i mi na r _P la n ta " );
break ;
case 'F ':
leer_num ( n_habs , " Introduzca el nuevo numero de habitaciones por planta : " );
hotel . E x t e n d e r _ H a b i t a c i o n e s ( n_habs , ok );
check_ok ( ok , " E x t e n d e r _ H a b i t a c i o n e s " );
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, a
continuación de las ya existentes, con tantas habitaciones como haya en la última planta, y
ok tomará el valor true. En otro caso, ok tomará el valor false. Estas nuevas habitaciones
se 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 estado
disponible, entonces elimina la última planta del hotel y ok tomará el valor true. En otro
caso, 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 es
menor que el valor del parámetro n_habs, entonces añade a cada planta tantas habitaciones
como sea necesario para que cada planta tenga el nuevo número de habitaciones especificado
por el valor del parámetro n_habs, y ok tomará el valor true. En otro caso, ok tomará el
valor 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 nuevos
métodos añadidos anteriormente.
201
Prácticas de Autoevaluación
Gestión de Factoría de Androides
La 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 clase
La estructura de datos interna de la clase Pieza almacena la información relativa a una
determinada 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
id
2
C-123-4567
Código
0
1
2
3
4
5
Descripción
Cabeza
Tronco
Brazo-Izq
Brazo-Dch
Pierna-Izq
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ódigo
de 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 y
androide.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 Androide almacena la información relativa a
la composición de un determinado androide, compuesta por su identificador (de tipo
string), y de un array (piezas) de 6 cadenas de caracteres (string), de tal forma que
el identificador de cada pieza que compone el androide se almacenará en el índice que
se corresponde con el código de la pieza. Por ejemplo, el identificador de la cabeza se
almacenará en la posición 0 del array, el tronco en la posición 1, el brazo izquierdo en
la posición 2, y así sucesivamente, según la tabla de códigos especificada en la clase
Pieza.
202
id
piezas
0
1
2
3
4
5
B-987-6734
A-251-4245
C-251-9682
C-123-4567
C-123-2563
A-762-8230
C-762-8274
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 las
piezas 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 el
có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 ese
componente 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 adecuadamente (código e identificador ) en el parámetro de salida p. Si el código es erróneo, o el componente
especificado 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-6734
0 A-251-4245
1 C-251-9682
2 C-123-4567
3 C-123-2563
4 A-762-8230
5 C-762-8274
Androide ERROR
0
1
2
3
4
5
La clase Factoría
Defina e implemente en el espacio de nombres umalcc la clase Factoria (en los ficheros factoria.hpp y
factoria.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 de
androides 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 en
un vector1 de elementos de tipo Androide. Además, tiene un segundo atributo, piezas, que es un puntero a
nodos que se encuentran organizados como una lista enlazada, donde cada nodo de la lista enlazada contiene
un objeto de la clase Pieza. Por ejemplo:
el alumno lo desea, obteniendo menor puntuación, podrá utilizar una estructura de array-incompleto de máximo 10 elementos
en lugar del tipo vector.
1 Si
203
Factoria
androides
B-987-6734
A-765-9823
D-987-6734
A-251-4245
C-251-9682
C-123-4567
C-123-2563
A-762-8230
C-762-8274
A-232-8822
A-232-8923
A-213-1233
A-213-9232
A-621-9234
A-621-9213
A-251-2312
C-213-9213
F-912-2139
F-912-2138
F-912-8923
F-912-8213
piezas
•
•
-
-
3
F-732-2193
•
-
0
A-823-9332
•
-
1
A-824-8455
/
2
A-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 y
la lista de piezas vacía.
Factoria(const Factoria& obj);
Androide B-987-6734
0 A-251-4245
1 C-251-9682
2 C-123-4567
3 C-123-2563
4 A-762-8230
5 C-762-8274
Androide A-765-9823
0 A-232-8822
1 A-232-8923
2 A-213-1233
3 A-213-9232
4 A-621-9234
5 A-621-9213
Androide D-987-6734
0 A-251-2312
1 C-213-9213
2 F-912-2139
3 F-912-2138
4 F-912-8923
5 F-912-8213
Piezas
3 F-732-2193
0 A-823-9332
1 A-824-8455
2 A-213-2372
// 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 formato mostrado en la figura superior, la información del estado interno
del 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ámetro
id, entonces crea una pieza con los parámetros especificados, y si la pieza creada NO es errónea, entonces
la inserta al final en la lista de piezas, y asigna true al parámetro ok. En otro caso, asigna false al
pará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 del
pará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 creado NO 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 hasta
completarlo.
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 del
parámetro id, añadiéndolas a la lista de piezas, también elimina del vector de androides aquel androide
cuyo identificador sea igual al valor del parámetro id, y asigna true al parámetro ok. En otro caso, asigna
false al parámetro ok.
204
El programa Principal
Así mismo, el alumno puede utilizar el programa principal que se proporciona (en el fichero main_androides.cpp
que 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 principal que se suministra, de tal forma que el alumno pueda comprobar su corrección.
205
Gestión de Tareas Periódicas
La 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 clase
La estructura de datos interna de la clase Tarea almacena la información relativa a una
determinada tarea periódica del sistema, tal como su identificador (de tipo string), el
código de la tarea (de tipo int), el periodo de ejecución (en segundos) de la tarea (de
tipo 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 entero
mayor o igual a cero, donde el valor cero indica la mayor prioridad (de tipo int), el tiempo
próximo de ejecución (en segundos) que indica cuando será ejecutada próximamente la
tarea (de tipo int) y un determinado valor que representa un número entero (de tipo
int).
Tarea
identificador
código
periodo
límite
prioridad
próximo
valor
Tarea-01
1
5
30
0
10
2
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 en
el mismo orden que los atributos en la figura anterior.
// Tarea(const Tarea& obj);
// Tarea& operator=(const Tarea& obj);
// Constructor de copia
// 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 objeto
actual. 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 valor
del 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 ejecuta
la tarea actual según lo especificado a continuación:
206
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.hpp
y 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 y
ejecución de tareas periódicas del sistema, para ello utiliza la clase Tarea definida anteriormente. Así, la clase
Planificador contiene un atributo que almacena el valor del tiempo_actual de la ejecución en segundos (de
tipo int). Además, tiene un segundo atributo, tareas, que es un vector de punteros a nodos que se encuentran
organizados como listas enlazadas ordenadas, donde cada nodo de la lista enlazada contiene un objeto de la
clase Tarea.
Cada tarea se encontrará en la lista enlazada que comienza en el elemento del vector cuyo índice es igual
a la prioridad de la tarea, y se encontrará ordenada según el valor de su atributo próximo. Por ejemplo:
Planificador
tiempo_actual
1
tareas
0
•
1
/
2
/
3
/
4
/
5
/
6
/
7
•
-
•
Tarea-07
···
prio: 0
prox: 1
-
•
Tarea-03
···
prio: 0
prox: 1
-
•
Tarea-05
···
prio: 7
prox: 1
-
/
Tarea-02
···
prio: 7
prox: 4
-
/
Tarea-09
···
prio: 0
prox: 3
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 de
tareas 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: 1
Tarea-07 2 7 30
Tarea-03 1 3 30
Tarea-09 1 5
2
Vacio
Vacio
Vacio
Vacio
Vacio
Vacio
Tarea-05 1 4 30
Tarea-02 3 3
2
0
0
0
1
1
3
32
2
8 **
7
7
1
4
4
2 **
207
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 valor
del atributo tiempo_actual, y NO existe en el sistema una tarea con identificador igual al especificado
por el parámetro id, entonces crea una tarea con los parámetros especificados, y si la tarea creada NO es
errónea, entonces la inserta de forma ordenada (según el valor del parámetro prox ) en la lista de tareas
cuyo índice es igual al valor del parámetro prio, y asigna true al parámetro ok. En otro caso, asigna false
al parámetro ok.
Nota: debe asegurarse de que la lista de tareas con la prioridad especificada ha sido creada adecuadamente
en 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ámetro
id, 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án
ser 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, y
false 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 la
clase Tarea).
Nota: en caso de que los últimos elementos del vector de tareas sean listas vacías, estos elementos deberán
ser 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, se
extrae la tarea del principio de la lista enlazada correspondiente, entonces se ejecuta la tarea (invocando
al método ejecutar() de la clase Tarea), y se vuelve a insertar de forma ordenada (según su nuevo tiempo
pró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.cpp
que 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_tareas.txt) con la salida esperada para el programa principal
que se suministra, de tal forma que el alumno pueda comprobar su corrección.
208
Descargar