• No se han encontrado resultados

Programación II. Relación de Ejercicios. Sonido e Imagen. Tema 1: Almacenamiento en Memoria Secundaria. Ficheros 2

N/A
N/A
Protected

Academic year: 2021

Share "Programación II. Relación de Ejercicios. Sonido e Imagen. Tema 1: Almacenamiento en Memoria Secundaria. Ficheros 2"

Copied!
46
0
0

Texto completo

(1)

Programación II

Relación de Ejercicios

Sonido e Imagen

UNIVERSIDAD DE MÁLAGA

Dpto. Lenguajes y CC. Computación E.T.S.I. Telecomunicación

Contenido

Tema 1: Almacenamiento en Memoria Secundaria. Ficheros 2

Tema 2: Tipos Abstractos de Datos 3

Tema 2.1: Programacion Modular. . . 3

Tema 2.2: Tipos Abstractos de Datos. . . 4

Tema 3: Gestión de Memoria Dinámica 8 Tema 3.1: Listas Enlazadas . . . 8

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

Tema 4: Introducción a la Programación Orientada a Objetos 16 Tema 5: Colecciones 20 Prácticas de Laboratorio 21 Práctica 1: Almacenamiento Persistente de Datos . . . 21

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

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

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

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

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

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

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

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

Prácticas de Autoevaluación 40 Gestión de Factoría de Androides . . . 40

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

cc Esta obra se encuentra bajo una licenciaReconocimiento-NoComercial-CompartirIgual 4.0 Internacional(CC BY-NC-SA 4.0) de Creative Commons. Véasehttp://creativecommons.org/licenses/by-nc-sa/4.0/deed.es_ES

(2)

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.

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óncod) y recuperar

la información original en un fichero de texto (extensióntxt).

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: Cadena de caracteres.

Edad int. Género char(M/F). Arte char(S/N). Deporte char(S/N). Libros char(S/N). Música char(S/N).

La información correspondiente a cada persona se leerá del teclado. El proceso finalizará cuando se teclee

un campo Nombreque esté vacío.

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). 5. Codifique un programa que cree un fichero para contener los datos relativos a los artículos de un almacén.

Para cada artículo habrá de guardar la siguiente información:

Código del artículo Numérico

Nombre del artículo Cadena de caracteres

Existencias Numérico

Precio Numérico

Se deberá pedir datos de cada artículo por teclado hasta que se teclee 0 (cero) como código de artículo. 6. Escriba un programa que tome como entrada el fichero del ejercicio anterior y una condición sobre los

camposexistenciaso 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.

(3)

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 tipoComplejo, así como los siguientes subprogramas:

void sumar ( Complejo& r, const Complejo& a, const Complejo& b) ;

// Devuelve un numero complejo ( 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 complejos ( a ) y ( b ) .

void restar ( Complejo& r, const Complejo& a, const Complejo& b) ;

// Devuelve un numero complejo ( 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 complejos ( a ) y ( b ) .

void multiplicar ( Complejo& r, const Complejo& a, const Complejo& b) ;

// Devuelve un numero complejo ( 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 complejos ( a ) y ( b ) .

void dividir ( Complejo& r, const Complejo& a, const Complejo& b) ;

// Devuelve un numero complejo ( 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 complejos ( a ) y ( b ) .

bool iguales (const Complejo& a, const Complejo& b) ;

// Devuelve t r u e s i l o s numeros complejos ( a ) y ( b ) son i g u a l e s . void escribir (const Complejo& a) ;

// Muestra en p a n t a l l a e l numero complejo ( a ) void leer ( Complejo& a) ;

// Lee de t e c l a d o e l v a l o r d e l numero complejo ( a ) . // Lee l a p a r t e r e a l y l a p a r t e imaginaria d e l numero

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

deberá definir el tipoRacional, así como los subprogramas adecuados teniendo en cuenta las siguientes

consideraciones:

Los números racionales se representan mediante fracciones, donde tanto el numerador como

denomi-nador son de tipoint).

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 positivosnym, el algoritmo de

Euclides funciona como se indica a continuación:

a) Sin < m, entonces se intercambian los valores denym(para asegurarnos quensiempre sea mayor o igual quem).

b) Si el valor demes distinto de0, entonces sear el resto de la división entera entren ym; después modificamos los valores denymde la siguiente forma:ntoma ahora el valor demymtoma ahora el valor der (el resto de la división entera entren y mcalculado anteriormente), y se repite este proceso especificado hasta que el valor demsea igual a0.

c) Finalmente, cuando el proceso iterativo acaba, el valor denes 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.

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).

void sumar ( Racional& r, const Racional& r1 , const Racional& r2 );

// Asigna a l numero 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 numeros r a c i o n a l e s ( r1 ) y ( r2 )

(4)

// Asigna a l numero 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 numeros 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 numero 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 numeros 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 numero 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 numeros 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 numero 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 numero r a c i o n a l ( r ) bool igual (const Racional& r1 , const Racional& r2 );

// Devuelve t r u e s i e l numero r a c i o n a l ( r1 ) es i g u a l a ( r2 ) bool menor (const Racional& r1 , const Racional& r2 );

// Devuelve t r u e s i e l numero r a c i o n a l ( r1 ) es menor que ( r2 )

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:

double evaluar (const Polinomio& a, double x);

// Devuelve e l r e s u l t a d o de e v a l u a r e l polinomio ( 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);

// PRECOND: (&r != &a )

// Devuelve un polinomio ( r ) que c on 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 derivada d e l polinomio ( a )

void sumar ( Polinomio& r, const Polinomio& a, const Polinomio& b);

// PRECOND: ((& r != &a)&&(&r != &b ) )

// Devuelve un polinomio ( 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 polinomios ( a ) y ( b )

void escribir (const Polinomio& a) ;

// Muestra en p a n t a l l a e l contenido d e l polinomio ( a ) void leer ( Polinomio& a) ;

// Lee de t e c l a d o e l v a l o r d e l polinomio ( a )

// Lee pares de c o e f i c i e n t e y grado hasta que e l c o e f i c i e n t e sea cero

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: class Complejo {

public:

Complejo () ;

// Constructor por Defecto

Complejo (double parte_real , double parte_imag ) ;

// Constructor e s p e c i f i c o double parte_real () const ;

// Devuelve l a p a r t e r e a l d e l numero complejo double parte_imag () const ;

// Devuelve l a p a r t e imaginaria d e l numero complejo void sumar (const Complejo& a, const Complejo& b) ;

// Asigna a l numero complejo ( a c t u a l ) e l r e s u l t a d o de // sumar l o s numeros complejos ( a ) y ( b ) .

void restar (const Complejo& a, const Complejo& b) ;

// Asigna a l numero complejo ( 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 complejos ( a ) y ( b ) .

void multiplicar (const Complejo& a, const Complejo& b) ;

// Asigna a l numero complejo ( 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 complejos ( a ) y ( b ) . void dividir (const Complejo& a, const Complejo& b) ;

// Asigna a l numero complejo ( 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 complejos ( a ) y ( b ) .

bool igual (const Complejo& b) const ;

// Devuelve t r u e s i e l numero complejo ( a c t u a l ) es // i g u a l a l numero complejo ( b )

void escribir () const ;

(5)

void leer () ;

// Lee de t e c l a d o e l v a l o r d e l numero complejo ( a c t u a l ) . // Lee l a p a r t e r e a l y l a p a r t e imaginaria d e l numero

} ;

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

public:

˜ Polinomio ();

// Destructor

Polinomio ();

// Constructor por Defecto

Polinomio (const Polinomio& p);

// Constructor de copia

Polinomio& operator=(const Polinomio& p);

// Operador de Asignacion int max_grado () const;

// Devuelve e l mayor grado d e l polinomio a c t u a l // cuyo c o e f i c i e n t e es d i s t i n t o de cero

void poner (int e, double c);

// Asigna e l c o e f i c i e n t e ( c ) a l termino de grado ( e ) // d e l polinomio a c t u a l

double obtener (int e) const;

// Devuelve 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 // termino de grado ( e ) d e l polinomio a c t u a l double evaluar (double x) const;

// Devuelve e l r e s u l t a d o de e v a l u a r e l polinomio 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);

// PRECOND: ( t h i s != &a )

// Asigna a l polinomio 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 derivada d e l polinomio ( a ) void sumar (const Polinomio& a, const Polinomio& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) // Asigna a l polinomio a c t u a l e l r e s u l t a d o de // sumar l o s polinomios ( a ) y ( b )

void escribir () const;

// Muestra en p a n t a l l a e l contenido d e l polinomio 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 polinomio a c t u a l

// Lee pares de c o e f i c i e n t e y grado hasta que e l c o e f i c i e n t e sea cero

};

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:

class Conjunto {

public:

˜ Conjunto ();

// Destructor

Conjunto ();

// Constructor por Defecto : conjunto vacio

Conjunto (const Conjunto& c);

// Constructor de copia

Conjunto& operator=(const Conjunto& c);

// Operador de Asignacion void clear ();

// Elimina todos l o s elementos d e l conjunto a c t u a l ( queda vacio ) bool es_vacio () const;

// Devuelve t r u e s i e l conjunto a c t u a l e s t a vacio void incluir (int e);

// I n c l u y e e l elemento ( e ) en e l conjunto a c t u a l ( s i n r e p e t i c i o n ) void eliminar (int e);

// Elimina e l elemento ( e ) d e l conjunto a c t u a l bool pertenece (int e) const;

// Devuelve t r u e s i e l elemento ( e ) p e rt e n ec e a l conjunto a c t u a l bool es_subconjunto (const Conjunto& a) const;

// Devuelve t r u e s i e l conjunto a c t u a l es subconjunto d e l conjunto ( a ) void union_conj (const Conjunto& a, const Conjunto& b);

(6)

// Asigna a l conjunto 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 conjuntos ( a ) y ( b )

void interseccion (const Conjunto& a, const Conjunto& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) // Asigna a l conjunto 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 conjuntos ( a ) y ( b ) void diferencia (const Conjunto& a, const Conjunto& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) // Asigna a l conjunto 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 conjuntos ( a ) y ( b )

void diferencia_simetrica (const Conjunto& a, const Conjunto& b);

// Asigna a l conjunto 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 conjuntos ( a ) y ( b ) void escribir () const;

// Muestra en p a n t a l l a e l contenido d e l conjunto 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 conjunto actual ,

};

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

métodos públicos: class Matriz { public: ˜ Matriz (); // Destructor Matriz ();

// Constructor por Defecto : matriz vacia

Matriz (int nfils , int ncols );

// Constructor e s p e c i f i c o : crea matriz de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0

Matriz (const Matriz& m);

// Constructor de copia

Matriz& operator=(const Matriz& m);

// Operador de Asignacion void clear (int nfils , int ncols );

// Elimina todos l o s elementos de l a matriz actual , y asigna

// a l a matriz a c t u a l una matriz de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0 int nfils () const;

// Devuelve e l numero de f i l a s de l a matriz a c t u a l int ncols () const;

// Devuelve e l numero de columnas de l a matriz 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 elemento de l a f i l a ( f )

// y columna ( c ) de l a matriz 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 ( ) )

// Devuelve e l v a l o r d e l elemento de l a f i l a ( f ) // y columna ( c ) de l a matriz a c t u a l

void sumar (const Matriz& a, const Matriz& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) // Asigna a l a matriz a c t u a l e l r e s u l t a d o de // sumar l a s matrices ( a ) y ( b )

void restar (const Matriz& a, const Matriz& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) // Asigna a l a matriz 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 matrices ( a ) y ( b )

void multiplicar (const Matriz& a, const Matriz& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) // Asigna a l a matriz 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 matrices ( a ) y ( b )

void escribir () const;

// Muestra en p a n t a l l a e l contenido de l a matriz 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 matriz actual , // 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 elementos

};

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

(7)

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:

class ListaInt {

public:

˜ ListaInt () ;

// Destructor

ListaInt () ;

// Constructor por Defecto

ListaInt (const ListaInt& o) ;

// Constructor de copia

ListaInt& operator = (const ListaInt& o) ;

// Operador de Asignacion bool llena () const ;

// Devuelve t r u e s i e l numero de elementos almacenados // alcanza l a capacidad maxima de almacenamiento int size () const ;

// Devuelve e l numero de elementos almacenados void clear () ;

// Elimina todos l o s elementos de l a l i s t a a c t u a l ( queda vacia ) void insertar (int pos , int dato ) ;

// PRECOND: ( ! l l e n a ( ) && 0 <= pos && pos <= s i z e ( ) ) // I n s e r t a ( dato ) 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: (0 <= pos && pos < s i z e ( ) )

// Elimina de l a l i s t a a c t u a l e l elemento que ocupa l a p o s i c i o n ( pos ) int acceder (int pos ) const ;

// PRECOND: (0 <= pos && pos < s i z e ( ) )

// Devuelve e l elemento 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: (0 <= pos && pos < s i z e ( ) )

// Asigna ( dato ) a l elemento 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 )

(8)

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 tipoPNodocomo un

puntero a un registro en memoria dinámica de tipo Nodo que contiene un enlace al siguiente nodo, así

como un dato de tipoint. 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

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 vacia void destruir ( PNodo& lista ) ;

// Destruye todos l o s elementos de l a l i s t a , l i b e r a n d o // todos l o s nodos de memoria dinamica . ( l i s t a ) queda vacia void escribir ( PNodo lista ) ;

// Muestra en p a n t a l l a e l contenido de ( l i s t a )

PNodo buscar ( PNodo lista , int dt) ;

// Devuelve un puntero a l nodo que co n t i en e e l elemento // i g u a l a ( dt ) . Si no se encuentra , entonces d e v u e l v e NULL void insertar_principio ( PNodo& lista , int dt) ;

// I n s e r t a un elemento a l p r i n c i p i o de ( l i s t a ) void insertar_final ( PNodo& lista , int dt) ;

// I n s e r t a un elemento a l f i n a l de ( l i s t a ) void insertar_ord ( PNodo& lista , int dt) ;

// I n s e r t a un elemento de forma ordenada en ( l i s t a ) , que debe e s t a r ordenada void eliminar_primero ( PNodo& lista ) ;

// Elimina e l primer elemento de ( l i s t a ) , s i e x i s t e void eliminar_ultimo ( PNodo& lista ) ;

// Elimina e l ultimo elemento de ( l i s t a ) , s i e x i s t e void eliminar_elem ( PNodo& lista , int dt) ;

// Elimina de ( l i s t a ) e l primer elemento i g u a l a ( dt ) , s i e x i s t e

PNodo situar ( PNodo lista , int pos ) ;

// Devuelve un puntero a l nodo que se encuentra en l a p o s i c i o n // indicada por ( pos ) . La p o s i c i o n cero (0) i n d i c a e l primer nodo . // Si e l nodo no e x i s t e , entonces 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 elemento en l a p o s i c i o n indicada por ( pos ) void eliminar ( PNodo& lista , int pos ) ;

// Elimina de ( l i s t a ) e l elemento de l a p o s i c i o n indicada por ( pos ) , s i e x i s t e

PNodo duplicar ( PNodo lista ) ;

// Devuelve un puntero a una nueva l i s t a r e 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 leer () ;

// Devuelve 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 ) hasta que l e a e l numero 0 ( que no es // i n t r o d u c i d o )

void eliminar_mayor ( PNodo& lista ) ;

// Elimina e l mayor elemento de ( l i s t a ) , s i e x i s t e void purgar ( PNodo& lista , int dt) ;

// Elimina de ( l i s t a ) todos l o s elementos que sean i g u a l e s a ( dt ) , s i e x i s t e n 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

(9)

Diseñe un módulo(programación modular) que proporcione soporte adecuado a la manipulación de

con-juntos de números enteros implementados mediante listas enlazadas en memoria dinámica (véase figura

anterior). El módulo deberá definir el tipoConjuntocomo un registro con un campo de tipoPNodo, que se

define como un tipo puntero a un registro en memoria dinámica de tipoNodoque contiene un enlace al

si-guiente nodo, así como un dato de tipoint. 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. void inicializar ( Conjunto& c);

// I n i c i a l i z a ( c ) a un conjunto vacio void destruir ( Conjunto& c);

// Destruye todos l o s elementos d e l conjunto , l i b e r a n d o // todos l o s nodos de memoria dinamica . ( c ) queda vacio bool es_vacio (const Conjunto& c) ;

// Devuelve t r u e s i e l conjunto ( c ) e s t a vacio void incluir ( Conjunto& c, int e);

// I n c l u y e e l elemento ( e ) en e l conjunto ( c ) ( s i n r e p e t i c i o n ) void eliminar ( Conjunto& c, int e);

// Elimina e l elemento ( e ) d e l conjunto ( c ) bool pertenece (const Conjunto& c, int e) ;

// Devuelve t r u e s i e l elemento ( e ) p e rt e n ec e a l conjunto ( c ) void escribir (const Conjunto& c) ;

// Muestra en p a n t a l l a e l contenido d e l conjunto ( c ) void leer ( Conjunto& c);

// Lee de t e c l a d o e l v a l o r d e l conjunto ( c )

bool es_subconjunto (const Conjunto& a, const Conjunto& b) ;

// Devuelve t r u e s i e l conjunto ( a ) es subconjunto d e l conjunto ( b ) void union_conj ( Conjunto& c, const Conjunto& a, const Conjunto& b);

// Asigna a l conjunto ( c ) e l r e s u l t a d o de

// l a union de l o s conjuntos ( 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 conjunto ( 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 conjuntos ( 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 conjunto ( 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 conjuntos ( a ) y ( b ) ( d u p l i c a l o s nodos )

void diferencia_simetrica ( Conjunto& c, const Conjunto& a, const Conjunto& b);

// Asigna a l conjunto ( 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 conjuntos ( a ) y ( b ) ( d u p l i c a l o s nodos ) void copiar ( Conjunto& d, const Conjunto& o) ;

// Copia ( d u p l i c a ) e l conjunto ( o ) en e l conjunto ( d )

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.

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 PNodocomo un puntero a un registro en memoria dinámica de tipoNodoque 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

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 vacia void destruir ( PNodo& lista ) ;

// Destruye todos l o s elementos de l a l i s t a , l i b e r a n d o // todos l o s nodos de memoria dinamica . ( l i s t a ) queda vacia void escribir ( PNodo lista ) ;

// Muestra en p a n t a l l a e l contenido de ( l i s t a )

PNodo buscar ( PNodo lista , int dt) ;

// Devuelve un puntero a l nodo que co n t i en e e l elemento // i g u a l a ( dt ) . Si no se encuentra , entonces d e v u e l v e NULL

(10)

void insertar_principio ( PNodo& lista , int dt) ;

// I n s e r t a un elemento a l p r i n c i p i o de ( l i s t a ) void insertar_final ( PNodo& lista , int dt) ;

// I n s e r t a un elemento a l f i n a l de ( l i s t a ) void insertar_ord ( PNodo& lista , int dt) ;

// I n s e r t a un elemento de forma ordenada en ( l i s t a ) , que debe e s t a r ordenada void eliminar_primero ( PNodo& lista ) ;

// Elimina e l primer elemento de ( l i s t a ) , s i e x i s t e void eliminar_ultimo ( PNodo& lista ) ;

// Elimina e l ultimo elemento de ( l i s t a ) , s i e x i s t e void eliminar_elem ( PNodo& lista , int dt) ;

// Elimina de ( l i s t a ) e l primer elemento i g u a l a ( dt ) , s i e x i s t e

PNodo situar ( PNodo lista , int pos ) ;

// Devuelve un puntero a l nodo que se encuentra en l a p o s i c i o n // indicada por ( pos ) . La p o s i c i o n cero (0) i n d i c a e l primer nodo . // Si e l nodo no e x i s t e , entonces 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 elemento en l a p o s i c i o n indicada por ( pos ) void eliminar ( PNodo& lista , int pos ) ;

// Elimina de ( l i s t a ) e l elemento de l a p o s i c i o n indicada por ( pos ) , s i e x i s t e

PNodo duplicar ( PNodo lista ) ;

// Devuelve un puntero a una nueva l i s t a r e 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 leer () ;

// Devuelve 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 ) hasta que l e a e l numero 0 ( que no es // i n t r o d u c i d o )

void eliminar_mayor ( PNodo& lista ) ;

// Elimina e l mayor elemento de ( l i s t a ) , s i e x i s t e void purgar ( PNodo& lista , int dt) ;

// Elimina de ( l i s t a ) todos l o s elementos que sean i g u a l e s a ( dt ) , s i e x i s t e n

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

1. Un polinomio enxde 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:

class Polinomio {

public:

˜ Polinomio ();

// Destructor

Polinomio ();

// Constructor por Defecto

Polinomio (const Polinomio& p);

// Constructor de copia

Polinomio& operator=(const Polinomio& p);

// Operador de Asignacion int max_grado () const;

// Devuelve e l mayor grado d e l polinomio a c t u a l // cuyo c o e f i c i e n t e es d i s t i n t o de cero

void poner (int e, double c);

// Asigna e l c o e f i c i e n t e ( c ) a l termino de grado ( e ) // d e l polinomio a c t u a l

double obtener (int e) const;

// Devuelve 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 // termino de grado ( e ) d e l polinomio a c t u a l double evaluar (double x) const;

// Devuelve e l r e s u l t a d o de e v a l u a r e l polinomio 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);

(11)

// Asigna a l polinomio 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 derivada d e l polinomio ( a ) void sumar (const Polinomio& a, const Polinomio& b);

// Asigna a l polinomio a c t u a l e l r e s u l t a d o de // sumar l o s polinomios ( a ) y ( b )

void escribir () const;

// Muestra en p a n t a l l a e l contenido d e l polinomio 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 polinomio a c t u a l

// Lee pares de c o e f i c i e n t e y grado hasta que e l c o e f i c i e n t e sea cero

};

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:

class Conjunto {

public:

˜ Conjunto ();

// Destructor

Conjunto ();

// Constructor por Defecto : conjunto vacio

Conjunto (const Conjunto& c);

// Constructor de copia

Conjunto& operator=(const Conjunto& c);

// Operador de Asignacion void clear ();

// Elimina todos l o s elementos d e l conjunto a c t u a l ( queda vacio ) bool es_vacio () const;

// Devuelve t r u e s i e l conjunto a c t u a l e s t a vacio void incluir (int e);

// I n c l u y e e l elemento ( e ) en e l conjunto a c t u a l ( s i n r e p e t i c i o n ) void eliminar (int e);

// Elimina e l elemento ( e ) d e l conjunto a c t u a l bool pertenece (int e) const;

// Devuelve t r u e s i e l elemento ( e ) p e rt e n ec e a l conjunto a c t u a l bool es_subconjunto (const Conjunto& a) const;

// Devuelve t r u e s i e l conjunto a c t u a l es subconjunto d e l conjunto ( a ) void union_conj (const Conjunto& a, const Conjunto& b);

// Asigna a l conjunto 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 conjuntos ( a ) y ( b )

void interseccion (const Conjunto& a, const Conjunto& b);

// Asigna a l conjunto 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 conjuntos ( a ) y ( b ) void diferencia (const Conjunto& a, const Conjunto& b);

// Asigna a l conjunto 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 conjuntos ( a ) y ( b )

void diferencia_simetrica (const Conjunto& a, const Conjunto& b);

// Asigna a l conjunto 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 conjuntos ( a ) y ( b ) void escribir () const;

// Muestra en p a n t a l l a e l contenido d e l conjunto 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 conjunto actual ,

};

3. Hay muchas aplicaciones en las que se deben almacenar en la memoria matrices de grandes dimensiones. Si la mayoría de los elementos de la matriz son ceros, ésta, en lugar de almacenarse en un array bidimensional, se puede representar más eficientemente utilizando listas enlazadas donde los elementos nulos y filas nulas

(12)

Así, defina la claseMatrizDispersaen el espacio de nombresumalcc_auxque represente dicha abstracción y proporcione las siguientes operaciones:

class MatrizDispersa {

public:

˜ MatrizDispersa ();

// Destructor

MatrizDispersa ();

// Constructor por Defecto : matriz vacia

MatrizDispersa (int nfils , int ncols );

// Constructor e s p e c i f i c o : crea matriz de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0

MatrizDispersa (const MatrizDispersa& m);

// Constructor de copia

MatrizDispersa& operator=(const MatrizDispersa& m);

// Operador de Asignacion void clear (int nfils , int ncols );

// Elimina todos l o s elementos de l a matriz actual , y asigna

// a l a matriz a c t u a l una matriz de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0 int nfils () const;

// Devuelve e l numero de f i l a s de l a matriz a c t u a l int ncols () const;

// Devuelve e l numero de columnas de l a matriz 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 elemento de l a f i l a ( f )

// y columna ( c ) de l a matriz 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 ( ) )

// Devuelve e l v a l o r d e l elemento de l a f i l a ( f ) // y columna ( c ) de l a matriz a c t u a l

};

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:

0 2 3 0 40 1 60 3 90 0 50 2 75 1 67 2 83 4 4 nfil ncol filas     40 60 0 90 0 0 0 0 50 0 75 0 0 67 83 0    

con las siguientes especificaciones adicionales:

El método obtenerpermite 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.

(13)

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.

4. Se debe diseñar e implementar el tipo abstracto de datosMatrizde 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 MatrizDispersarealizada en el ejercicio anterior.

class Matriz {

public:

˜ Matriz ();

// Destructor

Matriz ();

// Constructor por Defecto : matriz vacia

Matriz (int nfils , int ncols );

// Constructor e s p e c i f i c o : crea matriz de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0

Matriz (const Matriz& m);

// Constructor de copia

Matriz& operator=(const Matriz& m);

// Operador de Asignacion void clear (int nfils , int ncols );

// Elimina todos l o s elementos de l a matriz actual , y asigna

// a l a matriz a c t u a l una matriz de ( n f i l s ) x ( n c o l s ) con v a l o r e s 0 int nfils () const;

// Devuelve e l numero de f i l a s de l a matriz a c t u a l int ncols () const;

// Devuelve e l numero de columnas de l a matriz 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 elemento de l a f i l a ( f )

// y columna ( c ) de l a matriz 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 ( ) )

// Devuelve e l v a l o r d e l elemento de l a f i l a ( f ) // y columna ( c ) de l a matriz a c t u a l

void sumar (const Matriz& a, const Matriz& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) ; // Asigna a l a matriz a c t u a l e l r e s u l t a d o de // sumar l a s matrices ( a ) y ( b )

void restar (const Matriz& a, const Matriz& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) ; // Asigna a l a matriz 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 matrices ( a ) y ( b )

void multiplicar (const Matriz& a, const Matriz& b);

// PRECOND: ( ( t h i s != &a)&&( t h i s != &b ) ) ; // Asigna a l a matriz 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 matrices ( a ) y ( b )

void escribir () const;

// Muestra en p a n t a l l a e l contenido de l a matriz 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 matriz actual , // 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 elementos

};

5. Implemente un programa principal que permita comprobar el funcionamiento del tipo abstracto de datos Matrizdefinido previamente.

6. Se dispone de un procesador con varias etapas, y de unas determinadas tareas que se ejecutarán pasando sucesivamente por todas las etapas del procesador, desde la primera hasta la última. Como el 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 tareaT1 va ejecutándose por la etapae2 y la tareaT2 va

ejecutándose por la etapae4.

procesador

e1 e2 e3 e4

t1 t2

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

(14)

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 tareaT1 se está ejecutando en la etapa 2 y la tareaT2 se está ejecutando en la etapa 4.

0 1 1 2 0 3 2 4 procesador

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 TADProcesador que implemente la estructura de datos especificada anteriormente, y que

propor-cione los siguientes métodos públicos, así mismo, también se deberá implementar un programa principal que permita su utilización:

a) ElConstructorrecibe 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: 0 1 0 2 0 3 0 4 procesador

b) ElDestructorlibera todos los recursos asociados al objeto que está siendo destruido.

c) El métodoMostrar muestra en pantalla la estructura interna de un procesador. Por ejemplo, para

la figura anterior: Etapa: 1 Replica: libre Replica: libre Etapa: 2 Replica: tarea 1 Replica: tarea 2 Etapa: 3 Replica: libre Etapa: 4 Replica: libre

d) Un métodoReplicar, 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 iniciallibre(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:

0 1 1 2 0 3 2 4 0 2 0 2 procesador

(15)

0 1 1 2 0 3 2 4 0 2 0 2 0 1 procesador

e) Un método para Compactar que se usará para disminuir el número de réplicas de una etapa 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:

0 1 0 2 0 3 0 4 2 2 1 2 0 1 procesador

la siguiente figura es el resultado de compactar la etapa 2 de la figura anterior: 0 1 0 3 0 4 2 2 1 2 0 1 procesador

f) El métodoAvanzarEvaluacionintenta 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.

(16)

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: AgVentas AgVentas_A AgVentas_B Empleado Directivo Directivo_A Directivo_B Factoria

La clase polimórficaEmpleadorepresenta 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úblicosvirtuales:

• 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úblicosvirtuales:

• 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 deeuros recibida como parámetro a la

canti-dad total de ventas que acumula este agente de ventas.

• ventas(): devuelve la cantidad total de ventas que acumula este agente de ventas.

La clase polimórficaAgVentas_Arepresenta un agente de ventas de claseA, 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úblicosvirtuales:

• 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órficaAgVentas_Brepresenta un agente de ventas de claseB, 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úblicosvirtuales:

• 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úblicosvirtuales:

• clone(): devuelve un puntero a un nuevo objeto creado como copia del objeto actual.

La clase polimórficaDirectivo_Arepresenta un directivo de claseA, empleado de una factoría, tiene

un constructor que permite crear un objeto con el nombre (string) del empleado recibido como

(17)

• 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órficaDirectivo_Brepresenta un directivo de claseB, 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úblicosvirtuales:

• 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órficaFactoriarepresenta una factoría con un máximo de 100 empleados, su

construc-tor por defecto permite crear un nuevo objeto de claseFactoriasin ningún empleado, y proporciona

los siguientes métodos públicosvirtuales:

• 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

devuelvetrue ofalse, 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_AyAgVentas_B) y ventas acumuladas a los agentes de ven-tas, y calculará sus sueldos. Así mismo, tambien probará que la clonación de la factoría funciona adecuadamente.

2. Se desea simular el comportamiento de una serie de vehículos, por lo que se establece la siguiente jerarquía de clases:

Vehiculo

Bicicleta Automovil

Todo objeto de la clase base polimórficaVehiculodebe 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 coniy sudistanciaa cero.

Además, el comportamiento de los objetos Vehículoqueda definido por los siguientes métodos

pú-blicos virtuales:

• id(): devuelve el indentificador del vehículo

• consultar_dist(): devuelve ununsignedcon 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 objetoVehiculo, 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:

(18)

La clase derivada polimórficaAutomovilañade los siguientes atributos y define el siguiente construc-tor:

• DPL: constante simbólica static, de tipo unsigned, que indica la distancia que el automó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 ai, sudistanciaa 0 y sudepositoa 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, devolviendotrue si la cantidad

almace-nada en eldepositoes 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 deDPL, es decir, se incrementa la distancia recorrida

actual sumándole a la misma el valor almacenado en la constante miembroDPL.

• repostar(ltr): incrementa la cantidad de combustible almacenada en eldepositodel automóvil

enltrlitros.

• clone(): devuelve un puntero a un objetoAutomovil, copia del automóvil actual.

La clase derivada polimórficaBicicletaañade los siguientes atributos y define el siguiente

construc-tor:

• NUM_PLATOS: constante simbólicastatic, de tipounsigned, indicando el número de platos que tiene la bicicleta.

• plato: ununsignedque 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 ai, sudistanciaa 0 y suplatoa 0.

Además, el comportamiento de los objetos Bicicleta queda definido por los siguientes métodos

públicos virtuales:

• mover(): redefine el método de la clase base, de tal forma que la bicicleta se mueve una distancia

igual al valor deplato + 1, es decir, se incrementa la distancia recorrida actual sumándole a la

misma el valor deplato + 1.

• cambiar(): cambia el valor delplato, sumándole 1 y aplicando posteriormente% NUM_PLATOS

(el valor del plato siempre estará entre0yNUM_PLATOS - 1).

• clone(): devuelve un puntero a un objetoBicicleta, copia de la bicicleta actual.

El programa principal debe definir el tipo Vehiculoscomo un tipo array de NUM_VEHICULOS = 4

punteros a objetos de la claseVehiculo.

Implementar el procedimiento viajar(v, d, t), que recibe un puntero a un objeto de la clase

Vehiculo, ununsignedcon ladistanciatotal 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 eltiempoa 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 objetoVehiculo) ytiempose incrementa en 1.

Implementar el programa principal (main), con las siguientes características:

• Declara un array mis_vehiculosde tipoVehiculos.

• Crea un objetoAutomovil, con identificador"5555JJJ"y 50 litros de gasolina y ponemis_vehiculos[0]

apuntando a él.

• Crea un objeto Bicicleta, con identificador "6666JJJ"y pone mis_vehiculos[1]apuntando

a él.

• Crea un objetoBicicleta, con identificador"7777JJJ", cambia su plato y ponemis_vehiculos[2]

apuntando a él.

• Crea un objeto Bicicleta, con identificador "8888JJJ", cambia su plato dos veces y pone

(19)

• Para todos los vehiculos que se encuentran enmis_vehiculos, debe calcular el tiempo de

dura-ción del viaje para una distancia recorrida de destino 1000 invocando al procedimientoviajar

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

3. Dada la jerarquía de clases deVehiculodel ejercicio anterior, se debe desarrollar la claseno-polimórfica

Parkingpara gestionar un parking con un máximo deMAX = 100vehículos (de cualquier tipo) estacionados en él.

Los objetos de la claseParkingdeben 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 deMAXpunteros a objetos de la claseVehiculo.

• n_v: número de vehículos estacionados en el parking.

Además, la claseParkingdebe 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_parkingal 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 claseParking.

• 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, entoncesvse 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 deestacionarsobre este nuevo vehículo

estacionado (para que su distancia recorrida se ponga a 0);okdebe ponerse atrueen ese caso.

Si no hay espacio para estacionar en el parking, se devuelve falsea través deok.

• 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

idenfifi-cadorid. 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 devuelveNULL.

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 identificadorid, si éste está estacionado en el parking. Si no, devuelve una posición

fuera de rango (por ejemplo, eln_v).

• copiar(otro_parking): copia todo el estado deotro_parking(esto es, clona todos los vehículos

almacenados en él y copia sun_v) en el objeto actual. Nota: deben clonarse todos los vehículos

del objetootro_parkingpara 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.

(20)

Tema 5: Colecciones

1. Diseñe un programa que utilice el tipovector 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.

2. Realice el ejercicio anterior, utilizando el TADPersonadefinido en la práctica 6, e implementando el TAD

Agenda de la misma práctica convectoren vez de con una lista enlazada.

3. Diseñe un programa que lea y almacene en un vectorde 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.

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).

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)]

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:

(21)

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 y ←

-representan el espacio en blanco y el fin de línea respectivamente):

Opción (A) Opción (B) Opción (C)

nombre_apellidos edad ← -nombre_apellidos edad ← -· -· -· nombre apellidos ← -edad ← -nombre apellidos ← -edad ← -· -· -·

nombre apellidos edad ←

-nombre apellidos edad ← -· -· -·

Nótese que en la primera opción (A), el nombre de la persona no contiene espacios en blanco, 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:

# include <iostream> # include <fstream> # include <string> # include <array> # include <cctype> using namespace std; struct Persona { string nombre ; unsigned edad ; };

const unsigned MAX = 100;

typedef array<Persona , MAX> APers ;

struct Agenda {

unsigned nelms ; APers elm ; };

// . . . a completar por e l alumno . . . . char menu ()

{

char op;

cout << endl;

cout << "C. Cargar Agenda desde Fichero " << endl;

cout << "G. Guardar Agenda en Fichero " << endl;

cout << "M. Mostrar Agenda en Pantalla " << endl;

cout << "A. Anadir Persona a la Agenda " << endl;

cout << "X. Fin " << endl;

do {

cout << endl << " Opcion : ";

cin >> op;

op = char( toupper (op ));

} while (!(( op == 'C')||(op == 'G')||(op == 'M')||(op == 'A')||(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 );

(22)

break; case 'G': guardar_agenda (ag ); break; case 'M': escribir_agenda (ag ); break; case 'A': nueva_persona (ag ); break; } } while (op != 'X'); }

(23)

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

1. Diseñe e implemente un TAD para números racionales. Se deberán seguir las siguientes consideraciones: Los números racionales se representan mediante fracciones, donde tanto el numerador como

denomi-nador son de tipoint).

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 positivosnym, el algoritmo de

Euclides funciona como se indica a continuación:

a) Sin < m, entonces se intercambian los valores denym(para asegurarnos quensiempre sea mayor o igual quem).

b) Si el valor demes distinto de0, entonces sear el resto de la división entera entren ym; después modificamos los valores denymde la siguiente forma:ntoma ahora el valor demymtoma ahora el valor der (el resto de la división entera entren y mcalculado anteriormente), y se repite este proceso especificado hasta que el valor demsea igual a0.

c) Finalmente, cuando el proceso iterativo acaba, el valor denes 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). class Racional { public: Racional () ; // Construye e l numero r a c i o n a l 0/1 Racional (int n) ; // Construye e l numero r a c i o n a l n/1

Racional (int n, int d) ;

// Construye e l numero r a c i o n a l n/d bool fail () const;

// Devuelve t r u e s i e l numero r a c i o n a l a c t u a l e s t a en estado erroneo void multiplicar (const Racional& r1 , const Racional& r2 );

// Asigna a l numero 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 numeros 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 numero 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 numero r a c i o n a l a c t u a l private: void normalizar (); };

2. Diseñe un programa que permita utilizar el TAD especificado en el ejercicio anterior.

3. Añada de forma incremental los siguientes métodos públicos al TADRacional realizado anteriormente:

class Racional {

public:

// . . .

void dividir (const Racional& r1 , const Racional& r2 );

// Asigna a l numero 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 numeros r a c i o n a l e s ( r1 ) y ( r2 )

(24)

void sumar (const Racional& r1 , const Racional& r2 );

// Asigna a l numero 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 numeros r a c i o n a l e s ( r1 ) y ( r2 )

void restar (const Racional& r1 , const Racional& r2 );

// Asigna a l numero 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 numeros r a c i o n a l e s ( r1 ) y ( r2 )

bool igual (const Racional& r1) const;

// Devuelve t r u e s i e l numero r a c i o n a l a c t u a l es i g u a l a ( r1 ) bool menor (const Racional& r1) const;

// Devuelve t r u e s i e l numero r a c i o n a l a c t u a l es menor que ( r1 )

};

4. Modifique el programa que utiliza el TADRacional especificado anteriormente para que utilice los nuevos

Referencias

Documento similar

1. LAS GARANTÍAS CONSTITUCIONALES.—2. C) La reforma constitucional de 1994. D) Las tres etapas del amparo argentino. F) Las vías previas al amparo. H) La acción es judicial en

Para luchar contra este lamenta- ble estado de cosas, que, por otra parte, no es privativo de Italia, pues otros países también lo su- fren con más o menos intensidad, el

Volviendo a la jurisprudencia del Tribunal de Justicia, conviene recor- dar que, con el tiempo, este órgano se vio en la necesidad de determinar si los actos de los Estados

Entre nosotros anda un escritor de cosas de filología, paisano de Costa, que no deja de tener ingenio y garbo; pero cuyas obras tienen de todo menos de ciencia, y aun

Número de tarea: 2 Número de Historia de usuario: 2 Nombre de la tarea: Desarrollo de la funcionalidad para aplicar filtros lineales Tipo de tarea: configuración - desarrollo

A continuación, se presentan el enunciado que deberá resolver y sustentar por medio de video, representando la función y su respuesta en GeoGebra.. Estudiante

The LOMCE specifies that the education system must promote “Values that are pillars of democracy and human rights, including, in any case, the prevention of gender violence

• En 2023, se espera recoger el 70% respecto a lo que se destinó al mercado. Si no se cumplen los objetivos en 2023 o 2027, se implantará en todo el territorio nacional una zona