Departamento de Lenguajes y Ciencias de la Computación. I...

37
Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas ___________________________________________________________________________ Laboratorio de Programación Módulos Pág 1 10 MÓDULOS Contenido _____________________________________________________________________ 10.1.- Introducción. 10.1.1.- Ventajas de la modularización de programas. 10.1.2.- Creación de un proyecto con Dev-C++. 10.2.- Módulos de biblioteca. 10.2.1.- Espacios de nombres. 10.2.2.- Módulos de Definición. 10.2.3.- Módulos de Implementación. 10.2.4.- Ejemplo. El módulo Mcomplejo. 10.3.- Compilación separada. 10.4.- Estructuras de Datos Avanzadas. 10.4.1.- Pilas. 10.4.2.- Colas. 10.4.3.- Árboles Binarios. 10.5.- Un Ejemplo Completo. Ejercicios _____________________________________________________________________ 10.1.- Introducción Para entender el concepto de módulo, piénsese que se nos encargara diseñar un automóvil. Seguramente lo haríamos definiendo las distintas partes independientes que lo constituyen (carrocería, motor, sistema eléctrico, transmisión, etc.) así como la manera de conectar estos sistemas entre sí. La definición de estos sistemas (módulos) se hace de manera que sean lo más independientes posible unos de otros. Esta es la esencia de una buena modularidad. Igualmente, cualquier programa real está compuesto por varias partes separadas. Hasta ahora hemos utilizado los procedimientos y funciones para escribir estas partes en las que dividimos la solución a un problema. El uso de módulos pretende ser un paso más en la metodología del diseño descendente, permitiendo definir por separado las distintas partes de un programa y las interfaces entre ellas. Además, un módulo permite agrupar elementos que compartan alguna afinidad.

Transcript of Departamento de Lenguajes y Ciencias de la Computación. I...

Page 1: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 1

10 MÓDULOS

Contenido_____________________________________________________________________

10.1.- Introducción.10.1.1.- Ventajas de la modularización de programas.10.1.2.- Creación de un proyecto con Dev-C++.

10.2.- Módulos de biblioteca.10.2.1.- Espacios de nombres.10.2.2.- Módulos de Definición.10.2.3.- Módulos de Implementación.10.2.4.- Ejemplo. El módulo Mcomplejo.

10.3.- Compilación separada.10.4.- Estructuras de Datos Avanzadas.

10.4.1.- Pilas.10.4.2.- Colas.10.4.3.- Árboles Binarios.

10.5.- Un Ejemplo Completo.Ejercicios

_____________________________________________________________________

10.1.- IntroducciónPara entender el concepto de módulo, piénsese que se nos encargara diseñar un automóvil.Seguramente lo haríamos definiendo las distintas partes independientes que lo constituyen(carrocería, motor, sistema eléctrico, transmisión, etc.) así como la manera de conectar estossistemas entre sí. La definición de estos sistemas (módulos) se hace de manera que sean lomás independientes posible unos de otros. Esta es la esencia de una buena modularidad.

Igualmente, cualquier programa real está compuesto por varias partes separadas.Hasta ahora hemos utilizado los procedimientos y funciones para escribir estas partes en lasque dividimos la solución a un problema. El uso de módulos pretende ser un paso más en lametodología del diseño descendente, permitiendo definir por separado las distintas partes deun programa y las interfaces entre ellas. Además, un módulo permite agrupar elementos quecompartan alguna afinidad.

Page 2: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 2

Algunos lenguajes de programación ofrecen directamente el concepto de módulo.Aunque C++ no es uno de ellos, sí que ofrece las herramientas necesarias para poder enfocarun problema mediante la modularidad. Estas herramientas son la división de un programa endistintos ficheros fuente y los espacios de nombres.

10.1.1.- Ventajas de la modularización de programas

Escribir un programa como una colección de módulos ofrece muchas ventajas:

• Los módulos son una herramienta potente para crear grandes programas. Unprogramador puede diseñar un programa grande como un conjunto de módulos,relacionados entre sí mediante interfaces definidas apropiadamente. Escribir y depurarel programa es más fácil porque el programador puede trabajar con un módulo cadavez, usando los servicios facilitados por otros módulos pero ignorando los detalles decómo estos módulos trabajan (principio de abstracción). Este tipo de diseño modulares particularmente necesario cuando el programa se está desarrollando entre unconjunto de programadores.

• Ayudar a que el programa sea más fácil de modificar. Puesto que los detalles deimplementación de un módulo se ocultan al resto de módulos se pueden cambiardetalles de un módulo sin afectar al resto.

• Hacer los programas más portables. El programador puede ocultar los detallesdependientes de la máquina en un módulo, de forma que cuando se transporte a otroordenador, sólo debe preocuparse de dichos aspectos.

• Hacer posible la compilación separada. El programa se divide en trozos, que elcompilador puede procesar separadamente. De esta forma, un cambio en un módulosolo requiere volver a compilar dicho módulo, no el programa completo.

• Permiten desarrollar bibliotecas1 con código reutilizable. Ello conlleva no solo unahorro de trabajo, sino además un aumento de la fiabilidad del programa, pues dichasbibliotecas estarán más probadas que si la parte de la biblioteca que se usa secodificara de nuevo.

10.1.2.- Creación de un proyecto con Dev-C++.

Nosotros escribiremos cada uno de los módulos con los que trabajemos en un fichero fuentedistinto. Para hacer esto es necesario conocer cómo poder combinar varios ficheros fuentespara crear un programa.

Para poder trabajar con varios ficheros fuente en Dev-C++ es necesario crearpreviamente un proyecto. Para ello se utiliza la opción New Project del menú File. Alseleccionarla nos sale una ventana como la de la Figura 1. Para nuestros ejemplos utilizaremosla opción Empty Project y pulsaremos OK, tras lo cual se nos pedirá el nombre del proyecto.Una vez elegido un nombre se nos pregunta el directorio donde se desea guardar el fichero deproyecto. Este fichero, que tiene extensión dev, es el que usa el compilador para guardar todala información sobre el proyecto (ficheros fuente que lo componen, opciones de compilacióndel proyecto, etc.).

1 Puesto que su nombre en inglés es library en ocasiones se traduce como librería.

Page 3: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 3

Figura 1

Una vez guardado el fichero de proyecto se nos muestra una pantalla como la de laFigura 2. En ella se puede observar que a la izquierda aparece una pequeña ventana con elnombre del proyecto (en este caso complejos) del cual sale el nombre de cada uno de losficheros fuente que forman el proyecto. Como acabamos de crearlo solo hay un fichero pordefecto que se denomina Untitled.

Figura 2

Page 4: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 4

Podemos crear nuevos ficheros fuente dentro del proyecto con la opción New Unit inProject del menú Project. La Figura 3 muestra un proyecto que consta de tres ficheros fuentes:principal.cpp, complejo.h y complejo.cpp. Con las opciones respectivas del menúProject también se pueden agregar ficheros fuente ya existentes o eliminar del proyecto unfichero fuente.

Figura 3

Una vez creado el proyecto se puede compilar con la opción Compile del menú Executetal como lo habíamos hecho hasta ahora cuando sólo usábamos un fichero fuente. Una vezcompilados todos los ficheros, se procede al enlazado automático de los distintos ficherosobjeto que se han generado para crear el ejecutable.

Un programa consistirá en un módulo de programa (el programa principal) ycualquier número de módulos de biblioteca desde los cuales el módulo de programa importaentidades (constantes, tipos, variables y procedimientos). Estos módulos de biblioteca a su vezpueden importar de otros módulos de biblioteca. El compilador proporciona una colecciónbásica de módulos de biblioteca (stdlib, iostream, etc.) además de los cuales, elprogramador también puede escribir sus propios módulos de biblioteca adicionales, parausarlos en uno o en varios programas. Esto es precisamente lo que vamos a estudiar en estetema. Tendremos por tanto:

• Módulos de programa: son unidades de programa completas que pueden importarrecursos (constantes, variables, procedimientos..) desde módulos de biblioteca. Sonmódulos de programa aquellos con los que hemos estado practicando hasta elmomento ya que contienen la función main().

Page 5: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 5

• Módulos de Biblioteca: están constituidos por dos partes, el módulo de definición yel módulo de implementación.

Los módulos usan listas de importación para controlar los recursos externos que vana utilizar.

10.2.- Módulos de bibliotecaLos módulos de biblioteca se usan para exportar recursos a otros módulos. Un módulo

de biblioteca consta de dos partes, la parte de definición y la parte de implementación. Laparte de definición contiene sólo las definiciones de entidades o servicios que el móduloexporta, es decir, define la interfaz del módulo de biblioteca con el resto del programa. Laparte de implementación describe cómo implementar los servicios o entidades indicados en laparte de definición. La primera es también llamada fichero de cabecera y, aunque no esobligatorio, lo normal es darle a este fichero la extensión .h (header en inglés). La segunda, laparte de implementación, tienen extensión .cpp y también es llamada cuerpo del módulo.

El fichero de cabecera contiene definiciones, no declaraciones. Las definiciones sonsimilares a las declaraciones, pero proporcionan menos información. La definición de unprocedimiento consiste únicamente en la cabecera del procedimiento seguido de punto ycoma, omitiendo su cuerpo.

Ejemplo: Los parámetros de las funciones trigonométricas en la biblioteca <math.h>deben ser expresados en radianes, no en grados. Los programas que miden ángulos en gradosnecesitan convertir de grados a radianes y viceversa (llamaremos a estas funcionesgradosAradianes y radianesAgrados). Debido a que estas funciones pueden ser útiles enmás de un programa, tiene sentido crear un módulo de biblioteca llamadoconversiónAngulos que exporte las dos funciones. El fichero de cabecera sería:

conversionAngulos.h

El fichero de cabecera especifica qué servicios proporciona el módulo, en nuestrocaso, las funciones gradosAradianes y radianesAgrados.

La líneas:#ifndef _conversionangulos_h_#define _conversionangulos_h_

Son directivas de compilación, es decir, no son sentencias ejecutables sino informaciónadicional que se le proporciona al compilador. En este caso, lo que se está diciendo es:

/* declara funciones para la conversion entre angulos */#ifndef _conversionangulos_h_ // para evitar inclusión duplicada#define _conversionangulos_h_

double gradosAradianes (double grad); /* convierte un ángulo de grados a radianes */double radianesAgrados (double rad);/* convierte un ángulo de radianes a grados */

#endif

Page 6: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 6

Si no esta definida la “macro” _conversionangulos_h_ defínela. Si ya lo estabano hagas nada (puesto que no hay nada después de la directiva #endif).

Esta macro suele consistir en el nombre del fichero pero empezando y acabando por‘_’ y sustituyendo el ‘.’ del nombre del fichero por otro ‘_ ‘.

Este tipo de sentencias se suele incluir en todos los ficheros de cabecera para impedirque se produzcan errores de compilación cuando un fichero de cabecera es importado dosveces por el mismo módulo (esto suele ocurrir cuando un módulo importa un fichero decabecera que a su vez importa otro fichero de cabecera). De esta forma, la segunda vez que seincluye el fichero de cabecera el compilador se salta todas las definiciones puesto que ya estádeclarada la macro correspondiente.

A un módulo que importa una entidad exportada por un módulo de biblioteca se ledenomina cliente del módulo de biblioteca. El siguiente programa, calculaTercerLado, esun cliente del módulo de biblioteca conversionAngulos, del cual importa la funcióngradosARadianes (calculaTercerLado es también cliente de los módulos de bibliotecaiostream, stdlib y math).

Esto se puede representar gráficamente de la siguiente forma:

Donde las flechas indican “utiliza”. Sin embargo, el uso de las bibliotecas estándar nose suele representar, con lo que quedaría:

Para poder utilizar las funciones que ofrece el fichero de cabecera, el programa clientedebe incluir dicho fichero de cabecera. Esto se hace de forma similar a como lo habíamoshecho hasta ahora con los ficheros de biblioteca estándar como iostream o stdlib perosustituyendo los paréntesis angulares por comillas dobles. Esto indica al compilador que esefichero de cabecera es nuestro y que, por tanto, debe buscarlo en otros directorios distintos alos directorios en los que busca los ficheros de cabecera estándar. En general, los ficheros decabecera se buscan en el mismo directorio donde esté el archivo que los incluya excepto quese diga lo contrario en las opciones de compilación del proyecto.

El programa principal de la aplicación es el que se muestra a continuación:

calculatercerlado

conversionAngulos iostream stdlib math

calculatercerlado

conversionAngulos

Page 7: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 7

calculaTercerLado.cpp

Hemos de darnos cuenta de que calculaTercerLado no sabe nada de como funcionagradosAradianes. La parte de implementación de un módulo de biblioteca "llena los huecos"dejados por la parte de definición. Los procedimientos cuyas definiciones aparecen en la partede definición deben tener declaraciones completas en la parte de implementación. La parte deimplementación de conversionangulos sería:

conversionAngulos.cpp

#include "conversionangulos.h"const double pi=3.14159;

double gradosAradianes (double grad) /* convierte un ángulo de grados a radianes */{ return (pi * grad) / 180.0;}

double radianesAgrados (double rad)/* convierte un ángulo de radianes a grados */{ return 180 * rad / pi;}

/*calcula la longitud del tercer lado de un triángulo a partir de lalongitud de los otros dos lados y el ángulo formado entre ellos*/#include <iostream.h>#include <stdlib.h>#include <math.h>#include "conversionangulos.h"

void main (){ double lado1, lado2, lado3, angulo; cout << "Introduce la longitud de un lado "; cin >> lado1; cout << "Introduce la longitud del otro lado "; cin >> lado2; cout << "Introduce el angulo que forman en grados "; cin >> angulo;

lado3 = sqrt (lado1*lado1 + lado2*lado2 -2.0 * lado1*lado2 * cos (gradosAradianes(angulo))); cout << "La longitud del lado 3 es " << lado3 << endl; system ("pause"); return 0;}

Page 8: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 8

Lo primero que se debe hacer al escribir la parte de implementación es incluir elfichero de cabecera mediante la directiva #include "conversionangulos.h". De esta formanos aseguramos que todas las definiciones del fichero de cabecera estén accesibles en la partede implementación. Además de "llenar los huecos" dejados en la parte de definición delmódulo, la parte de implemetación puede declarar entidades no mencionadas en la parte dedefinición (en nuestro caso la constante pi). Estas entidades son locales al módulo deimplementación: no son visibles fuera del módulo.

10.2.1.- Espacios de nombres.

Un espacio de nombres se utiliza para expresar una agrupación lógica. Es decir, sialgunas declaraciones pertenecen, de forma lógica, al mismo grupo, de acuerdo con algúncriterio, se pueden poner en el mismo espacio de nombres. Un espacio de nombres es unámbito, por lo cual, si un nombre se declara dentro de un espacio de nombres podrá ser visibledentro de ese espacio de nombres con las reglas habituales de ámbitos. Sin embargo, para usarese nombre fuera del espacio de nombres hay que utilizar el nombre del espacio de nombresseguido de la expresión “::” a la cual seguirá el nombre que queremos utilizar. Esto es muyútil para programas grandes donde puede ser que tengamos varios subprogramas con elmismo nombre. Poner delante el nombre del espacio de nombres (lo que se denomina,cualificar el nombre) nos evitaría entrar en conflictos.

Para definir un espacio de nombres se utilizará la palabra namespace seguida delidentificador que queramos asignarle. A continuación encerramos entre llaves todo el espaciode nombres.

Los espacios de nombres proporcionan una herramienta excelente para laprogramación modular. De esta forma nuestro ejemplo se escribiría de la siguiente forma:

Donde hemos introducido el espacio de nombres Mconversionangulos para indicarque es el espacio de nombres donde se encuentran las declaraciones del móduloconversionangulos.

En el programa principal tenemos tres opciones a la hora de llamar a la funcióngradosAradianes. La primera es simplemente poner el espacio de nombres delante de lafunción: Mconversionangulos::gradosAradianes con lo que la sentencia correspondientequedaría como:

/* declara funciones para la conversión entre ángulos */#ifndef _conversionangulos_h_ // para evitar inclusión duplicada#define _conversionangulos_h_

namespace Mconversionangulos {

double gradosAradianes (double grad); /* convierte un ángulo de grados a radianes */double radianesAgrados (double rad);/* convierte un ángulo de radianes a grados */}#endif

Page 9: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 9

lado3 = sqrt (lado1*lado1 + lado2*lado2

-2.0 * lado1*lado2 *cos (Mconversionangulos::gradosAradianes(angulo)));

La segunda opción es hacer una declaración de uso mediante la instrucción using:using Mconversionangulos::gradosAradianes; /* importa del móduloMconversionangulos la función gradosAradianes */

Con lo cual, ya podemos utilizar la función sin tener que cualificarla. Esto esparticularmente útil cuando el nombre que se está usando se utiliza muchas veces.

La tercera opción es importar con una sola sentencia todo el espacio de nombres. Esese caso tendríamos que poner using namespace Mconversionangulos; con lo que ahoratodos los identificadores del espacio de nombres son visibles sin tener que estar cualificados.Esta opción, aunque cómoda, puede no ser la más aconsejable puesto que si importamos dosespacios de nombres que exportan el mismo identificador volveríamos a entrar en conflicto(con lo cual los espacios de nombres perderían su sentido).

Por último, en el módulo de implementación, se puede volver a definir el mismoespacio de nombres para implementar cada una de las operaciones definidas en el fichero decabecera:

conversionangulos.cpp

#include "conversionangulos.h"namespace Mconversionangulos{const double pi=3.14159;

double gradosAradianes (double grad) /* convierte un ángulo de grados a radianes */{ return (pi * grad) / 180.0;}

double radianesAgrados (double rad)/* convierte un ángulo de radianes a grados */{ return 180 * rad / pi;}} // fin del módulo

Page 10: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 10

10.2.2.- Módulos de definición.

Un módulo de definición contiene definiciones de constantes, tipos, variables yprocedimientos. Las definiciones son similares a las declaraciones, pero pueden tener menosinformación.

- Constantes.

Son idénticas a las declaraciones de constantes normales.

- Tipos.

Nosotros nos ceñiremos a los denominados tipos transparentes, en los cuales, laestructura del tipo es visible en los módulos que lo importen. Por ejemplo:

struct Complejo { float p_real, p_imag;};

Un módulo que importe el tipo complejo importa automáticamente los nombres de suscampos p_real y p_imag. Sin embargo, para seguir una metodología de diseño correcta, esconveniente que cuando se defina un tipo, también se definan todos los procedimientos ofunciones que manejen ese tipo. De esta forma, el módulo cliente de este tipo es independientede su implementación, de forma que si realiza un cambio en la implementación del tipo o desus operaciones, el módulo cliente no se vea afectado.

- Variables.

Las definiciones de variables son idénticas a las declaraciones de variables normales.Estas variables son globales, por lo que se uso sólo es recomendable en casos muy concretos.

- Procedimientos y funciones.

La definición de un procedimiento o función consta de la cabecera del mismo. Ladeclaración completa debe aparecer en el módulo de implementación. No es necesario ponerlenombre a los parámetros, basta con indicar su tipo.

10.2.3.- Módulos de implementación.

Al igual que los módulos de programa, los módulos de implementación puedencontener tanto listas de importación como declaraciones. Mediante listas de importación unmódulo de implementación puede importar entidades de otros módulos de biblioteca.

Las declaraciones sirven para dos propósitos:

• Especificar los aspectos indefinidos en el módulo de definición.

• Declarar entidades que sean estrictamente locales al módulo de implementación.

Cualquier entidad declarada en la parte de definición de un módulo de biblioteca esvisible en la parte de implementación al incluir el fichero de cabecera.

Un módulo de implementación puede tener declaraciones de 4 clases de entidades:

Page 11: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 11

- Constantes.

Las constantes definidas en la parte de definición son visibles en la parte deimplementación. Todas las constantes declaradas en un módulo de implementación son localesa dicho módulo; no son visibles fuera del módulo de implementación.

- Tipos.

Los tipos definidos en la parte de definición del módulo son visibles en la parte deimplementación. Si es necesario, se pueden definir nuevos tipos que son locales al módulo deimplementación.

- Variables.

Las variables declaradas en la parte de definición no pueden volver a ser declaradas enla parte de implementación puesto que son visibles en ésta. Todas las variables declaradas enla parte de implementación son locales a ésta.

- Procedimientos y funciones.

La parte de implementación de un módulo debe contener una declaración completa detodos los procedimientos y funciones cuya definición aparece en el fichero de cabecera. Habráque respetar estrictamente la forma en que se definieron, es decir, habrá que declarar el mismonúmero de parámetros y los mismos tipos para ellos.

10.2.4.- Ejemplo. El módulo Mcomplejo.

A continuación se muestra un programa que utiliza un módulo de bibliotecadenominado Mcomplejo que exporta el tipo de datos complejo así como algunas operacionesque se pueden realizar con este tipo de datos. La estructura del programa sería la siguiente:

La parte de definición del módulo complejo (Mcomplejo.h) sería:

principal

Mcomplejo

Page 12: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 12

La parte de implementación (Mcomplejo.cpp) quedaría como:

// declara el tipo de datos Complejo y algunas operaciones#ifndef _Mcomplejo_h_#define _Mcomplejo_h_namespace Mcomplejo{

struct Complejo { float p_real, p_imag; }; // números complejos

void asignar (Complejo& c, float real, float imag); // asigna a c el número complejo formado por real e imag void sumar (Complejo& res, Complejo x, Complejo y); // suma x + y asignado el resultado a res void escribir (Complejo x); // escribe por pantalla el valor de x}#endif

#include "Mcomplejo.h"#include <iostream.h>

namespace Mcomplejo{

void asignar (Complejo& c, float real, float imag)// asigna a c el número complejo formado por real e imag{ c.p_real = real; c.p_imag = imag;}

void sumar (Complejo& res, Complejo x, Complejo y)// suma x + y asignado el resultado a res{ res.p_real = x.p_real + y.p_real; res.p_imag = x.p_imag + y.p_imag;}

void escribir (Complejo x)// escribe por pantalla el valor de x{ cout << x.p_real << " + " << x.p_imag << "i";}

} // fin del módulo

Page 13: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 13

El programa principal (principal.cpp) sería el siguiente:

10.3.- Compilación SeparadaUna de las ventajas del diseño modular es poder compilar módulos de programa y de

biblioteca de forma separada. El compilador chequea que cada entidad importada de unmódulo de biblioteca sea usada de forma consistente con su definición en el módulo (para ellousa la información contenida en la parte de definición del módulo de biblioteca).

La compilación separada nos proporciona la ventaja de que cuando cambiamos unprograma sólo necesitamos recompilar los módulos afectados, no todos los módulos delprograma.

Cuando cambiemos un módulo de programa sólo necesitamos recompilar dichomódulo y volver a enlazar (“linkar”) el programa completo; sin embargo, si cambiamos laparte de definición de un módulo debemos recompilar la parte de implementación de éste ytodos los módulos que importen algo de dicha biblioteca. En Dev C++ todo este proceso estásimplificado de modo que es el sistema el que determina qué módulos necesitan serrecompilados como resultado de los cambios hechos al programa. La opción Rebuild All delmenú Execute recompila todos los ficheros fuente del proyecto tanto si han sido modificadoscomo si no.

#include <stdlib.h>#include <iostream.h>#include "complejo.h"

// programa cliente del modulo Mcomplejo.

// Lista de importación:using Mcomplejo::Complejo;using Mcomplejo::asignar;using Mcomplejo::sumar;using Mcomplejo::escribir; // equivalente a using namespace Mcomplejo;

int main(){ Complejo c1, c2, c3; // declara 3 números complejos asignar (c1, 1.0, 2.0); asignar (c2, 2.0, 4.5); sumar (c3, c1, c2); // c3 = c1 + c2 escribir (c3); cout << endl;

system("pause"); return 0;}

Page 14: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 14

10.4.- Estructuras de Datos Avanzadas.En el tema de gestión dinámica de memoria se estudió como implementar una lista

enlazada. En este tema estudiaremos otros tipos de estructuras de datos así como suimplementación mediante módulos de biblioteca.

10.4.1. Pilas.

Una pila es una estructura de datos homogénea (elementos del mismo tipo), secuencialy de tamaño variable. Sólo es posible un modo de acceso a esta estructura: a través de lacabeza de la pila. De este modo podemos añadir un elemento a la cabeza de la pila o extraerun elemento de la cabeza de la pila. Debido a que las operaciones de extracción e inserción serealizan por el mismo extremo, el último elemento en ser añadido será el primero en serextraído; por ello a estas estructuras se las conoce con el nombre de LIFO (last-in, first-out;último en entrar, primero en salir).

Otras operaciones posibles sobre la pila son la creación de una pila vacía, lainterrogación de la misma para determinar si contiene o no algún elemento y la destrucción dela pila.

Para implementar una pila como una estructura dinámica de datos se usan listasenlazadas, las operaciones de extracción e inserción en la lista (pila) se hacen siempre sobre lacabeza de la misma.

La estrucutura de datos usada para representar una pila que almacene elementos detipo int es la siguiente:

Cabeza

Pila

Insertar

Extraer

Page 15: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 15

En este caso se mantiene un sólo puntero de tipo TPila que apunte a la cabeza de lapila de elementos. A continuación se muestra el módulo de implementación del tipo de datospila.

#ifndef _MPila_h_ // para evitar inclusión duplicada#define _MPila_h_// Modulo MPila// Exporta el tipo TPila, pila de enteros y los procedimientos// crearPila, destruirPila, pilaVacia, meterPila y sacarPila

namespace MPila{

struct NodoPila { int elemento; NodoPila * sig; };

typedef NodoPila* TPila;

TPila crearPila (); // Crea la Pila void destruirPila (TPila& pila); // libera la memoria bool pilaVacia (TPila pila); // comprueba si la pila está vacía void meterPila (TPila& pila, int valor); // introduce valor en la pila void sacarPila (TPila& pila, int & valor); // saca el valor de la cima de la pila}#endif

Page 16: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 16

#include <stdlib.h>#include <iostream.h>#include "mpila.h"// Implementa las operaciones para manejar el tipo TPilanamespace MPila{ TPila crearPila () { return NULL; } bool pilaVacia (TPila pila) { return (pila == NULL); } void destruirPila (TPila & pila) { TPila ptr; while (pila != NULL) { ptr = pila; pila= pila->sig; delete ptr; } } void meterPila (TPila& pila, int valor) { TPila ptr; ptr = new NodoPila; ptr->elemento = valor; ptr->sig = pila; pila = ptr; }

void sacarPila (TPila& pila, int& valor) { TPila ptr; if (pilaVacia (pila)) { cout << "Error en la pila. Pila Vacia " << endl; } else { ptr = pila; valor = pila->elemento; pila= pila->sig; delete ptr; } }}

Page 17: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 17

Por último mostramos un programa sencillo que usa el tipo de datos pila. Simplementelee números enteros hasta leer un cero y a continuación los muestra en orden inverso:

#include <stdlib.h>#include <iostream.h>#include "mpila.h"

using namespace MPila;

int main(){ TPila p; int n;

p= crearPila ();

cout <<"Introduzca un numero (0 para terminar)" <<endl; cin >> n; while (n != 0) { meterPila (p,n); cout <<"Introduzca un numero (0 para terminar)" <<endl; cin >>n; }

cout <<"Los numeros al reves son:" <<endl; while ( !pilaVacia(p) ) { sacarPila (p,n); cout << n << endl; }

destruirPila (p);

system ("pause"); return 0;}

Page 18: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 18

10.4.2. Colas.

En muchas aplicaciones se cumple el hecho de que el primer proceso que solicita unservicio o recurso es el primero en ser servido. Para retirar elementos (servicios, recursos) enel mismo orden en que fueron solicitados, se necesitan unas estructuras de datos abstractasque mantengan una secuencia de valores y permitan añadir nuevos elementos por un extremoy retirarlos por el otro. Esta estructura recibe el nombre de cola.

En las colas el elemento que entró el primero sale también el primero, por ello se leconoce también como listas FIFO (first-in, first-out; primero en entrar, primero en salir.)

Se define la cola, como una estructura de datos homogénea de tamaño variable quesoporta el siguiente modo de acceso: inserción por un extremo y extracción por el opuesto.Operaciones posibles sobre la cola son la creación de una cola vacía, la determinación de sí lacola está o no vacía y la destrucción de la cola.

De igual modo que se ha visto para la pila, una cola se puede implementar haciendouso de las estructuras dinámicas de datos. En este caso, se simula mediante una lista enlazadaque mantiene dos punteros, uno llamado frente por donde se van extrayendo los elementosmás antiguos de la cola, y otro llamado final, que señala al extremo por el cual se iránañadiendo elementos a la cola. De esta forma, el puntero final nos garantiza que cada vez quese tenga que extraer un elemento de la cola, no sea necesario recorrer ésta desde el principio,lo cual sería altamente ineficiente para colas largas. Las operaciones de insertar y extraer de lacola tienen acceso directo a los nodos de la cola en los que se van a realizar estas operaciones.

La diferencia con las pilas reside en el modo de entrada y salida de los datos, en lascolas las inserciones se realizan al final de la lista, no al principio.

FrenteFinal

Cola

Extraer Añadir

Page 19: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 19

MCola.h

#ifndef _MCola_h_ // para evitar inclusión duplicada#define _MCola_h_// Modulo MCola// Exporta el tipo TCola, Cola de enteros y los procedimientos// crearCola, destruirCola, ColaVacia, meterCola y sacarCola

namespace MCola{

struct NodoCola { int elemento; NodoCola * sig; };

typedef NodoCola * TPuntero ;

struct TCola { TPuntero frente, final; };

TCola crearCola (); // Crea la Cola void destruirCola (TCola& cola); // libera la memoria bool colaVacia (TCola cola); // comprueba si la Cola está vacía void meterCola (TCola& cola, int valor); // introduce valor al final de la Cola void sacarCola (TCola& cola, int & valor); // saca el valor del frente de la Cola}

#endif

Page 20: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 20

La implementación de las operaciones de la cola (MCola.cpp) serían las siguientes:

#include <stdlib.h>#include <iostream.h>#include "MCola.h"

// Implementa las operaciones para manejar el tipo TColanamespace MCola{

TCola crearCola () { TCola cola; cola.frente = NULL; cola.final = NULL; }

void destruirCola (TCola & cola) { TPuntero ptr; while ( cola.frente != NULL ) { ptr = cola.frente; cola.frente = cola.frente->sig; delete ptr; } }

bool colaVacia (TCola cola) { return (cola.frente == NULL); }

void meterCola (TCola& cola, int valor) { TPuntero ptr; ptr = new NodoCola; ptr->elemento = valor; ptr ->sig = NULL; if (colaVacia(cola) ) { // si es el primero frente y final lo apuntan cola.frente = ptr; } else { cola.final->sig = ptr; } cola.final = ptr; }

Page 21: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 21

10.4.3. Árboles Binarios.

Las estructuras dinámicas vistas hasta ahora son lineales (listas enlazadas, pilas, colas).Estas estructuras tienen grandes ventajas en cuanto a flexibilidad sobre las representacionescontiguas, pero tienen un punto débil: son listas secuenciales, es decir, están dispuestas deforma que es necesario recorrer cada posición al menos una vez (cada elemento tiene unsucesor). Mediante los árboles binarios se introduce el concepto de estructura de bifurcación,donde cada elemento puede tener más de un posible 'siguiente', con lo cual es posible resolveralgunos problemas de difícil solución cuando se usan estructuras dinámicas lineales.

El árbol es una estructura muy usada en todos los ámbitos de la informática ya que seadapta a la representación natural de informaciones homogéneas organizadas y de una grancomodidad y rapidez de manipulación. Las estructuras tipo árbol se usan para representardatos con una relación jerárquica entre sus elementos, como son árboles genealógicos, tablas,etc.

Un árbol se define como un conjunto finito de uno o más nodos relacionados de lasiguiente forma:

void sacarCola (TCola& cola, int& valor) { TPuntero ptr; if (colaVacia (cola)) { cout << "Error en la Cola. Cola Vacia " << endl; } else { ptr = cola.frente; valor = ptr->elemento; cola.frente= cola.frente->sig; delete ptr; if (cola.frente == NULL) // era el último { cola.final = NULL; } } }

}// fin del módulo MCola

Page 22: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 22

• Hay un nodo especial llamado raíz del árbol, que proporciona un punto de entrada ala estructura.

• Los nodos restantes se subdividen en m>=0 conjuntos disjuntos, cada uno de loscuales es a su vez un árbol. Estos árboles se llaman subárboles del raíz.

Nótese que esta definición es recursiva, se define un árbol en función de otros árboles.

La representación y terminología de los árboles se realiza con las típicas notaciones delas relaciones familiares en los árboles genealógicos: padre, hijo, hermano, ascendiente,descendiente. Junto a estos conceptos se definen otros tales como raíz, nodo, hoja, camino,nivel, profundidad, etc., con los cuales se supone familiarizado al alumno.

7 8 6

1

2

4 5

9

3

Un Árbol Binario se define como un conjunto de 0 ó más nodos tales que:

• Existe un nodo llamado raíz del árbol.

• Cada nodo puede tener 0,1, ó 2 subárboles conocidos como subárbol izquierdo ysubárbol derecho.

Un árbol binario puede ser representado fácilmente eligiendo las estructuras de datosadecuadas. Un árbol general puede transformarse en un árbol binario aplicando determinadosalgoritmos de conversión, el resto del epígrafe se centrará en el estudio de los árboles binarios.

La representación dinámica de un árbol binario utiliza variables punteros y asignacióndinámica de espacios de memoria. Cada nodo del árbol contiene al menos los siguientescampos:

• Campo de datos que almacena el tipo de datos.

• Puntero al subárbol izquierdo.

• Puntero al subárbol derecho.

Una implementación en C++ es la que se muestra a continuación:

struct NodoArbol { int elemento; NodoArbol * izq, * der; };

typedef NodoArbol * TArbol;

Page 23: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 23

Se llama recorrido de un árbol binario al proceso que permite acceder una sola vez acada uno de los nodos del árbol. Cuando un árbol se recorre, el conjunto completo de nodosse examina. Los algoritmos de recorrido de un árbol realizan las siguientes tareas comunes:

• Procesar el nodo raíz.

• Recorrer el subárbol izquierdo.

• Recorrer el subárbol derecho.

El orden en que se realizan estas acciones da nombre a los tres algoritmos másusuales: pre-orden, in-orden y post-orden:

void inOrden(TArbol a){if (! arbolVacio(a)) { inOrden(Izda(a)); procesar(a); inOrden(Decha(a));}}

void preOrden(TArbol a){if (! arbolVacio(a)) { procesar(a); preOrden(Izda(a)); preOrden(Decha(a));}}

void postOrden(TArbol a){if (! arbolVacio(a)) { postOrden(Izda(a)); postOrden(Decha(a)); procesar(a);}}

En cuanto a las operaciones aplicables a un árbol binario se muestran en el módulo deimplementación Marbol las siguientes:

- crearVacio: Devuelve un árbol binario vacío.

- crearRaiz: Crea el nodo raíz de un árbol, y almacena en este nodo el valor que se lepasa como parámetro a la función.

- crearIzda: Dado un árbol binario que no tiene desarrollada su rama izquierda, estafunción crea un nodo con el valor que se recibe como argumento, y se asigna a la ramaizquierda del árbol binario original.

- crearDcha: Es similar al procedimiento anterior pero aplicable a la rama derecha.

- sacarRaiz: Esta función devuelve el valor de la raíz de un árbol binario.

- arbolVacio: Determina si un árbol binario está o no vacío.

- destruirArbol. Libera la memoria utilizada por el árbol. Hace un recorrido enpostorden.

Page 24: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 24

#include <stdlib.h>#include <iostream.h>#include "Marbol.h"

// Implementa las operaciones para manejar el tipo TArbolnamespace MArbol{

TArbol crearVacio () { return NULL; }

void crearRaiz (TArbol &arbol, int valor) { TArbol nodo; nodo = new NodoArbol; nodo->elemento = valor; nodo->izq=crearVacio(); nodo->der=crearVacio(); arbol = nodo; }

void crearIzda (TArbol &arbol, int valor) { TArbol nodo; crearRaiz (nodo,valor); arbol->izq = nodo; } void crearDcha (TArbol &arbol, int valor) { TArbol nodo; crearRaiz (nodo,valor); arbol->der = nodo; }

int sacarRaiz (TArbol a) { return a->elemento; }

void destruirArbol (TArbol & arbol) { if (arbol != NULL) { destruirArbol(arbol->izq); destruirArbol(arbol->der); delete arbol; } }}

Page 25: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 25

10.5. Un Ejemplo Completo.A continuación vamos a ver una aplicación relativamente sencilla que hemos

descompuesto en varios módulos distintos. Consiste en un menú que nos permite añadirempleados a una lista para posteriormente poder visualizar dicha lista. Por cada empleado sealmacena su nombre, apellidos y su sueldo. Tanto el nombre como los apellidos deben teneruna longitud que no esté delimitada por ninguna constante. Los módulos en que hemosdividido la aplicación son los siguientes:

El primero de ellos, menu, es el programa principal, muestra el menú por pantalla yllama a las distintas opciones. El módulo MListaEmpleado exporta una lista enlazada en laque se insertan los empleados. Para hacer la implementación de la lista enlazada lo másindependiente posible del tipo base de la lista1, se implementa el tipo TEmpleado en otromódulo distinto (MEmpleado) junto con las operaciones necesarias para escribirlo, leerlo deteclado y liberar la memoria que consume. Por último, el módulo MCadena ofrece lasoperaciones de lectura y escritura de una cadena de caracteres implementada mediante unalista enlazada.

1 Las plantillas de C++ quedan fuera de los objetivos de la asignatura.

menu

MListaEmpleado

MCadena

MEmpleado

Page 26: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 26

menu.cpp

#include <stdlib.h>#include <iostream.h>#include <ctype.h>#include "MEmpleado.h"#include "MListaEmpleado.h"using MEmpleado::TEmpleado;using MEmpleado::leeEmpleado; // importa TEmpleado y leeEmpleado de MEmpleadousing namespace MListaEmpleado; // importa todo el modulo

char menu(){ char opc;

cout << "A: Introducir Empleado" << endl; cout << "B: Mostrar empleados" << endl; cout << "S: Salir" << endl; cout << "Introduzca opcion:";

cin>> opc; cin.ignore(); // limpia el buffer de teclado. return opc;}

int main (){ TEmpleado emp; TListaEmpleado lista; char opcion, seguro; bool salir= false;

lista =crearLista(); // inicializa la lista while (! salir) { opcion = toupper (menu()); switch ( opcion ) { case 'A': cout <<"Introduce un empleado\n"; leeEmpleado (emp); insertaEmpleado (lista, emp); break; case 'B': muestraLista (lista); break;

Page 27: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 27

MListaEmpleado.h

case 'S': cout << "Esta seguro (S/N)" << endl; cin >> seguro; if (toupper (seguro) == 'S' ) { salir = true; } break; default: cout << "Opcion incorrecta " <<endl; break; } } borraLista (lista); // libera la memoria

system ("pause"); return 0;}

#ifndef _MListaEmpleado_h_ // para evitar inclusión duplicada#define _MLislaEmpleado_h_

#include "MEmpleado.h"// Parte de definicion del modulo Lista de Empleadonamespace MListaEmpleado {using MEmpleado::TEmpleado; //importa el tipo TEmpleado

struct TNodoEmpleado{ TEmpleado emp; TNodoEmpleado * sig;};

typedef TNodoEmpleado * TListaEmpleado;

TListaEmpleado crearLista(); // crea la lista vacíavoid insertaEmpleado(TListaEmpleado &lista, TEmpleado emp); // inserta un empleado en la lista (por el principio)void muestraLista(TListaEmpleado lista); // muestra la lista completavoid borraLista (TListaEmpleado &lista); // libera la memoria consumida

}#endif

Page 28: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 28

MListaEmpleado.cpp

#include <stdlib.h> // para incluir NULL#include "MListaEmpleado.h"#include "MCadena.h"

// implementación del módulo de Lista de Empleado

namespace MListaEmpleado {using MEmpleado::destruirEmpleado;

TListaEmpleado crearLista () // crea la lista vacía{ return NULL;}

void insertaEmpleado(TListaEmpleado &l, TEmpleado emp) // inserta un empleado en la lista (por el principio){ TListaEmpleado nuevo; nuevo = new TNodoEmpleado; nuevo->emp = emp; nuevo->sig = l; l = nuevo;}

void muestraLista(TListaEmpleado l) // muestra la lista completa{ TListaEmpleado ptr; ptr = l; while (ptr != NULL) { escribeEmpleado(ptr ->emp); ptr = ptr->sig; }}void borraLista (TListaEmpleado &l) // libera la memoria{ TListaEmpleado ptr; while (l != NULL) { ptr = l; l = l->sig; destruirEmpleado(ptr->emp); delete ptr; }}

} // fin del módulo

Page 29: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 29

MEmpleado.h

#ifndef _MEmpleado_h_ // para evitar inclusión duplicada#define _MEmpleado_h_

#include "MCadena.h"

namespace MEmpleado{ // parte de definicion del módulo Empleado using MCadena::TCadena ; // importa el tipo TCadena de MCadena

struct TEmpleado { TCadena nombre; TCadena apellidos; float sueldo; };

void escribeEmpleado(TEmpleado emp); // escribe un empleado void leeEmpleado(TEmpleado &emp); // lee un empleado void destruirEmpleado(TEmpleado &emp); // libera la memoria de unempleado}#endif

Page 30: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 30

MEmpleado.cpp

MCadena.h

#include <iostream.h>#include "MEmpleado.h" // incluimos la parte de definición// implementación del módulo de Empleadonamespace MEmpleado {

using MCadena::escribeCadena;using MCadena::leeCadena;using MCadena::borraCadena; // importa de MCadena

void escribeEmpleado(TEmpleado emp) // escribe un empleado{ cout << "Nombre: "; escribeCadena(emp.nombre); cout << endl; cout << "Apellidos: "; escribeCadena(emp.apellidos); cout << endl; cout << "Sueldo: " << emp.sueldo << endl;}

void leeEmpleado(TEmpleado & emp) // lee un empleado{ cout << "Nombre: " ; leeCadena (emp.nombre); cout << "Apellidos: " ; leeCadena (emp.apellidos); cout << "Sueldo: " ; cin >> emp.sueldo;}

void destruirEmpleado(TEmpleado &emp) // libera la memoria de un empleado{ borraCadena (emp.nombre); borraCadena (emp.apellidos);}

} // fin del módulo

#ifndef _MCadena_h_ // para evitar inclusión duplicada#define _MCadena_h_

// Parte de definicion del modulo MCadenanamespace MCadena {

struct TNodo { char car; TNodo * sig; }; typedef TNodo * TCadena;

void leeCadena (TCadena &c); // Lee una cadena de teclado void escribeCadena (TCadena c); // muestra la cadena void borraCadena (TCadena &c); // libera la memoria consumida}

#endif

Page 31: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 31

MCadena.cpp

#include <iostream.h>#include <ctype.h>#include "MCadena.h" // incluimos la parte de definición

// implementación del módulo de Cadena

namespace MCadena {

const char ENTER = '\n';

void escribeCadena (TCadena c) // muestra la cadena { TCadena ptr; ptr = c; while (ptr != NULL) { cout << ptr->car; ptr = ptr->sig; } }

Page 32: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 32

void leeCadena (TCadena &c) // Lee una cadena de teclado { char letra; TCadena ptr;

cin.get (letra); if (letra == ENTER) { c = NULL; // cadena vacía } else { c = new TNodo; // inserta la primera letra c->car = letra; c->sig = NULL; ptr = c;

cin.get (letra); // inserta el resto while (letra != ENTER) { ptr->sig = new TNodo; ptr = ptr->sig; ptr->car = letra; cin.get (letra); } ptr ->sig = NULL; } }

void borraCadena(TCadena &c) // libera la memoria consumida { TCadena ptr; while (c != NULL) { ptr = c; c = c->sig; delete ptr; } }

} // fin del módulo MCadena

Page 33: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 33

EJERCICIOS

1. Escribe un módulo de implementación llamado MComplejo.cpp parecido al visto en estetema pero que exporte el tipo de dato número complejo y las operaciones suma, resta,producto, división, lectura y escritura sobre dicho tipo. El tipo y las operaciones estándefinidas en el fichero MComplejo.h, dado a continuación:

Probarlo sobre el siguiente programa ejemplo:

/*----------------------------------------------------------------*//* Programa ejemplo para práctica de módulos. Usa el tipo de *//* de datos Complejo que se encuentra definido en el fichero *//* Mcomplejo.h. *//*----------------------------------------------------------------*/

#include <stdlib.h>#include <iostream.h>#include "complejo.h"

// programa cliente del modulo Mcomplejo.

// Lista de importación:using namespace Mcomplejo;

int main()

// declara el tipo de datos Complejo y algunas operaciones#ifndef _Mcomplejo_h_#define _Mcomplejo_h_namespace Mcomplejo{

struct Complejo { float p_real, p_imag; }; // números complejos Complejo leerCMP (); void EscribirCMP (Complejo c); Complejo asignarCMP (float real, float imag); Complejo sumar (Complejo x, Complejo y); Complejo restar (Complejo minuendo, Complejo sustraendo); Complejo multiplicar (Complejo x, Complejo y); Complejo dividir (Complejo x, Complejo y);}#endif

Page 34: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 34

{ Complejo a, b, c; // declara 3 números complejos a = asignarCMP (4.5, 5.0); b = asignarCMP(2.45, -3.0); c = leerCMP(); escribirCMP(a) ; escribirCMP(b) ; escribirCMP(c) ; b = sumarCMP(a, c) ; a = restarCMP(b, c) ; c = multiplicarCMP(a, b) ; escribirCMP(a) ; a = dividirCMP(c, b) ; escribirCMP(a) ; escribirCMP(b) ; escribirCMP(c) ;

cout << endl;

system("pause"); return 0;}

2. Implementar el programa prbMod3.cpp, similar al del ejercicio 1, pero en lugar denúmeros complejos importar un módulo llamado MPolinon.h que contenga el tipo de datoTPolinomio y las mismas operaciones que se aplican a los complejos. El grado máximo delos polinomios es 10.

3. Escribe un módulo llamado UNIDADES, que defina un número de identificadoresconstantes que sean útiles en formulas para convertir de un conjunto de unidades a otro.Necesitamos saber que:

-. 1 pulgada son 2.54 centímetros.-. 1 milla son 1.6093 Kilómetros.-. 1 galón son 4.5461 litros.-. 1 libra son 0.4536 Kilogramos.-. La formula para pasar de grados Celsius a Fahrenheit es:

celsius = (fahrenheit - 32.0) * 5.0 / 9.0Tu módulo debería exportar identificadores apropiados para los valores 2.54, 1.0693,4.5461, 0.4536, 32.0 y 5.0/9.0. Escribe a continuación un módulo separado llamadoCONVERSIONESUNIDADES, que defina funciones para convertir de un conjunto deunidades a otras. Se habrían de incluir dos funciones (una en cada dirección), para cadauna de las siguientes parejas:

- pulgadas y centímetros.- millas y kilómetros.- galones y litros.- libras y kilogramos.-grados celsius y grados fahrenheit.

Page 35: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 35

El módulo de implementación de CONVERSIONESUNIDADES, debería importar delmódulo UNIDADES y debería usar los identificadores constantes exportados desde esemódulo. Escribe un programa para comprobar este módulo.

4. Escriba un módulo llamado Mcadenas similar al del apartado 10.5 que exporte lasoperaciones leeCadena, escribeCadena, comparaCadenas, concatenaCadenas,longitudCadena, copiaCadena y posicionCadena (toma dos parámetros, c1 yc2 y si c2 está contenida en c1, devuelve la posición de c1, dondecomienza c2; en caso de que c2 no este contenida en c1 devuelve –1).

Diseña también un módulo cliente para probar el módulo Mcadena.

5. Implementar un módulo de librería que trabaje con una pila de números cardinales. Lasoperaciones que tendrá que incluir son las vistas en este tema, así como las operaciones decomparar dos pilas para determinar si son iguales y copiar una pila en otra.

6. Supóngase que se modifica la definición de implementación de la cola de forma que sedeclare un sólo puntero cola que apunte al frente de la cola. A su vez la lista enlazada quesimula la cola es circular tal y como se muestra en la figura inferior. Se pide redefinir elmódulo de implementación Mcola mostrado en el tema en base a esta nueva definición.Añadir una función que calcule la longitud de una cola.

ColaFinal

Frente

Diseña un módulo cliente para probar el módulo cola. En dicho módulo se habrá decrear una cola de elementos de tipo INTEGER. Los elementos que se insertarán en lacola (esta se creará a base de llamadas sucesivas a InsertarCola), serán leídos de unfichero de texto. Además de esta operación en el módulo cliente se habrán de probartodas las restantes operaciones de la cola (sacarCola, colaVacia, crearCola,longitudCola, destruirCola).

Si el fichero de texto fuera el siguiente:

25 35 40 45 50¶

La cola a crear sería la siguiente:

Page 36: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 36

2535404550

Cola

FrenteFinal

7. Añadir los siguientes procedimientos al módulo Marbol:

- Buscar un elemento en el árbol y devolver el nodo de tipo árbol que lo contiene.

- Insertar un nodo en el subárbol derecha (o izquierda) a partir del nodo que contieneun elemento pasado como parámetro. Esta operación sólo es posible si el subárboldonde se va insertar está vacío.

- Calcular el nivel de un nodo.

- Devolver el nodo padre de un nodo.

- Eliminar un nodo y todos sus descendientes de un árbol binario.

8. Diseña una aplicación para la gestión del personal de una empresa. De cada uno de losempleados de la empresa se ha de almacenar la siguiente información:

- Nombre

- DNI

-Año de Contratación

-Nómina

Para gestionarlos de una forma eficiente, y minimizar en lo posible el Tiempo debúsqueda, se decide almacenarlos en una Tabla Hash, que utilice el método deencadenamiento para la resolución de colisiones. La función hash, sería el primer carácterdel nombre de cada empleado (campo clave). De modo que nuestra tabla hash tendría 26posiciones, correspondientes a las 26 letras del alfabeto inglés.

Diseña un menú que permita llevar a cabo las siguientes operaciones, con la estructuraanteriormente definida:

A.- Insertar un nuevo Empleado.

B.- Eliminar un Empleado.

C.- Buscar un Empleado.

D.- Visualizar los datos de todos los Empleados.

Page 37: Departamento de Lenguajes y Ciencias de la Computación. I ...afdez/apuntes/laboratorio/apuntes/modulos.pdf · Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

Departamento de Lenguajes y Ciencias de la Computación. I.T.I. Gestión/Sistemas

___________________________________________________________________________

Laboratorio de Programación Módulos Pág 37

E.- Salir.

- Seleccione una opcion:

A.- Insertar un nuevo Empleado. Pedirá los datos del empleado a insertar, y lo

insertará en la tabla.

Nombre:

DNI:

Anyo:

Nómina:

B.- Eliminar un Empleado. Pedirá el campo clave (nombre) del empleado a eliminar, lobuscará y posteriormente lo eliminará de la tabla.

C.- Buscar un Empleado. Pedirá el campo clave (nombre) del empleado a buscar y lobuscará en la tabla, devolviendo true o false según el resultado de la búsqueda.

D.- Visualizar los datos de todos los Empleados. Recorrerá toda la tabla, imprimiendopor pantalla toda la información relativa a cada uno de los empleados, su nombre, DNI,año de contratación y nómina.

Para implementar la aplicación, diseña primero el módulo MTabla con sus partes dedefinición (define el tipo TEmpleados (la tabla hash), de acuerdo a la definiciónanterior) y cada una de las operaciones a llevar a cabo sobre dicho tipo(Insertar_Tabla, Eliminar_Tabla, Visualizar_Tabla, Buscar_Tabla, Crear_Tabla). PorUltimo diseña un módulo de prueba (cliente), donde se encontrará implementado elmenú y que importará el tipo de datos TEmpleados, junto con las operaciones quenecesite del módulo MTabla.

NOTA: Recuerda que has de hacer un procedimiento para crear (inicializar) laestructura; este habrá de ejecutarse al comienzo, antes de ejecutar cualquiera de lasoperaciones anteriores del módulo de prueba.