curso de programacion 2:´ -...

83
Curso de Programaci´ on 2: Manual de pr ´ acticas Grado en Ingenier´ ıa Inform´ atica Javier Mart´ ınez y Joaqu´ ın Ezpeleta ´ Area de Lenguajes y Sistemas Inform´ aticos Departamento de Inform´ atica e Ingenier´ ıa de Sistemas Curso 2017-18

Upload: duongngoc

Post on 04-Nov-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

Curso de Programacion 2:Manual de practicas

Grado en Ingenierıa Informatica

Javier Martınez y Joaquın EzpeletaArea de Lenguajes y Sistemas Informaticos

Departamento de Informatica e Ingenierıa de Sistemas

Curso 2017-18

Indice general

1. Practica 1: Desarrollo de programas C++ en diversos entornos 4

1.1. Objetivos de la practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.2. Preparacion de la practica y trabajo en el laboratorio de Programacion . . . . . . . . . . . 5

1.3. Primeros pasos en un sistema operativo unix o linux . . . . . . . . . . . . . . . . . . . 5

1.3.1. Como iniciar y finalizar una sesion de trabajo . . . . . . . . . . . . . . . . . . . . 5

1.3.2. Directorios y ficheros en unix (o en linux) . . . . . . . . . . . . . . . . . . . . 7

1.3.3. Ordenes unix o linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.3.4. Trabajo con ficheros y directorios en unix o en linux . . . . . . . . . . . . . . 9

1.3.5. Organizacion de nuestro directorio de trabajo . . . . . . . . . . . . . . . . . . . . 11

1.3.6. Edicion de programas fuente C++ . . . . . . . . . . . . . . . . . . . . . . . . . . 12

1.4. Puesta a punto de un programa escrito en C++ . . . . . . . . . . . . . . . . . . . . . . . . 13

1.4.1. Compilacion y ejecucion de un programa escrito en C++ . . . . . . . . . . . . . . 13

1.4.2. Correccion de errores de un programa C++ . . . . . . . . . . . . . . . . . . . . . 16

1.5. Tecnologıa y herramientas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.5.1. Transmision de datos a traves de la lınea de ordenes . . . . . . . . . . . . . . . . . 16

1.5.2. Medida del tiempo desde un programa . . . . . . . . . . . . . . . . . . . . . . . . 17

1.5.3. Generacion de datos pseudoaleatorios . . . . . . . . . . . . . . . . . . . . . . . . 19

1.5.4. Programacion de funciones genericas . . . . . . . . . . . . . . . . . . . . . . . . 20

1.6. Trabajo a desarrollar en esta practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

1.6.1. Especificacion del primer programa a desarrollar . . . . . . . . . . . . . . . . . . 22

1.6.2. Especificacion del segundo programa a desarrollar . . . . . . . . . . . . . . . . . 22

1.6.3. Especificacion del tercer programa a desarrollar . . . . . . . . . . . . . . . . . . . 23

1.6.4. Especificacion del cuarto programa a desarrollar . . . . . . . . . . . . . . . . . . 23

1.6.5. Resultados del trabajo desarrollado en la primera practicas . . . . . . . . . . . . . 24

1.7. ¿Que hay que saber hacer con soltura tras realizar esta practica? . . . . . . . . . . . . . . 25

1

1.8. Anexo. El servidor hendrix y el sistema operativo unix . . . . . . . . . . . . . . . . . 26

1.8.1. El computador de practicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

1.8.2. Acceso a una cuenta en hendrix-ssh . . . . . . . . . . . . . . . . . . . . . . . 26

1.8.3. Resumen de ordenes basicas en unix o linux . . . . . . . . . . . . . . . . . . 26

2. Practica 2: Definicion de estructuras de datos genericos y desarrollo de programas sin bucles(diseno recursivo sin inmersion) 30

2.1. Objetivos de esta practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

2.2. Tecnologıa y herramientas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

2.2.1. Diseno de estructuras de datos genericos . . . . . . . . . . . . . . . . . . . . . . . 30

2.2.2. Parametros de una funcion cuyo valor puede estar definido por defecto . . . . . . . 32

2.3. Trabajo a desarrollar en esta practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

2.3.1. Primera tarea: diseno del tipo generico Pila . . . . . . . . . . . . . . . . . . . . 32

2.3.2. Segunda tarea: diseno sin bucles de funciones que trabajan con enteros . . . . . . 35

2.3.3. Tercera tarea: diseno recursivo de funciones de mayor nivel para trabajar con pilasde datos genericos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

2.3.4. Resultados del trabajo desarrollado en las dos primeras practicas . . . . . . . . . . 40

3. Practica 3: Desarrollo de programas C++ sin bucles (recursividad sin o con inmersion) 42

3.1. Objetivos de esta practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.1.1. Calendario de esta practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.2. Trabajo a realizar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

3.2.1. Comportamiento de un programa gestor de una cola de personas . . . . . . . . . . 43

3.2.2. Desarrollo del programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

3.3. Calendario de trabajo y tareas a realizar . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

3.4. ¿Como compilar y ejecutar los programas anteriores? . . . . . . . . . . . . . . . . . . . . 52

3.4.1. ¿Como compilar los programas de prueba de la primera fase de esta practica? . . . 52

3.4.2. ¿Como compilar el programa a desarrollar en la segunda fase de esta practica? . . 54

3.4.3. ¿Como evitar especificar en un programa la ruta de los ficheros nombrados en lasordenes include? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

3.4.4. ¿Como simplificar la compilacion de programs con una cierta complejidad? . . . . 55

3.5. La herramienta make . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

3.5.1. Primera version de un fichero make para compilar el programa . . . . . . . . . . 56

3.5.2. Segunda version de un fichero make para compilar el programa . . . . . . . . . . 58

2

3.5.3. Tercera version de un fichero make para compilar el programa . . . . . . . . . . . 58

3.5.4. Cuarta version de un fichero make para compilar el programa . . . . . . . . . . . 60

3.5.5. Version final de un fichero make para compilar el programa . . . . . . . . . . . . 61

3.5.6. Otra aplicaciones y documentacion de la herramienta make . . . . . . . . . . . . 62

3.6. Resultados del trabajo desarrollado en las tres primeras practicas . . . . . . . . . . . . . . 62

4. Practica 4: Analisis experimental del coste de algoritmos 64

4.1. Objetivos de la practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

4.2. Analisis del algoritmo de ordenacion por seleccion . . . . . . . . . . . . . . . . . . . . . 65

4.2.1. La funcion de coste, en tiempo, para cada uno de los casos . . . . . . . . . . . . . 65

4.2.2. Analisis de la eficiencia del algoritmo de ordenacion de vectores por seleccion . . 69

4.3. Analisis del algoritmo de ordenacion por insercion . . . . . . . . . . . . . . . . . . . . . 70

4.4. Uso de scripts o guiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

4.5. Resultados del trabajo desarrollado en las cinco practicas de la asignatura . . . . . . . . . 76

5. Practica 5: Diseno de algoritmos de ordenacion de matrices 78

5.1. Objetivos de la practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

5.1.1. Calendario de esta practica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

5.2. Trabajo a desarrollar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

5.2.1. Algoritmo de ordenacion de una matriz cuadrada por intercambio de sus elementos 79

5.2.2. Algoritmo de ordenacion rapida (quicksort) de los elementos de una matriz cuadrada 80

5.3. Resultados del trabajo desarrollado en las cinco practicas de la asignatura . . . . . . . . . 81

3

Capıtulo 1

Practica 1: Desarrollo de programas C++en diversos entornos

1.1. Objetivos de la practica

El primer objetivo de esta primera practica de la asignatura es aprender a desarrollar programasescritos en C++ en diversos entornos. En esta asignatura se desarrollaran programas con ayuda del entornoCodeLite, instalado en los computadores personales ubicados en los laboratorios de practicas, y tambiensin su ayuda, utlizando directamente las herramientas de edicion y compilacion existentes en un sistemaunix o linux.

En las practicas se trabajara con dos tipos de maquinas:

Con los computadores personales (pc) disponibles en los laboratorios de programacion, operadosmediante el sistema operativo CentOS, una variante del sistema operativo linux.

Con el servidor hendrix-ssh del departamento de Informatica e Ingenierıa de Sistemas. Esteservidor es un cluster de dos computadores, hendrix01 y hendrix02, gobernado por un sistemaoperativo unix.

Para trabajar en el desarrollo de programas en cualquiera de dichas maquinas es necesario aprender aoperar, a nivel elemental, con los sistemas operativos unix y linux. Para ello hay que saber realizar lassiguientes operaciones:

Entrar y salir en la cuenta de trabajo que cada alumno dispone en el cluster hendrix-ssh y en lospc de los laboratorios de programacion.

Navegar por su sistema de directorios (carpetas).

Gestionar el almacenamiento de nuestros ficheros (copiarlos, moverlos, cambiarlos de nombre,eliminarlos, etc.).

Organizar nuestra cuenta de trabajo, creando una determinada estructura de directorios internos parafacilitar el desarrollo de programas C++ en esta asignatura.

Utilizar un editor de textos como, por ejemplo, el editor gedit.

Editar, compilar, corregir errores, en su caso, y ejecutar programas escritos en C++.

4

El segundo objetivo de esta practica es aprender alguno nuevo sobre tecnologıa C++ de aplicaciondirecta a algunos de los trabajos que se van a plantear en las practicas de esta asignatura:

1. Como medir el tiempo empleado en ejecutar un segmento de codigo C++.

2. Como generar datos pseudoaleatorios para realizar pruebas con ellos.

3. Como desarrollar algoritmos genericos.

4. Como gestionar datos suministrados desde la lınea de ordenes en la que se invoca la ejecucion deun programa.

1.2. Preparacion de la practica y trabajo en el laboratorio de Programacion

Antes de acudir a la sesion de laboratorio asociada a esta practica conviene haber leıdo el texto deeste capıtulo, incluyendo su ultimo apartado, un anexo que resume las ordenes basicas para trabajar en unsistema unix o linux.

Esta practica pretende facilitar al alumno el aprendizaje del modo de trabajo en un entorno unix olinux: la edicion de programas fuente escritos en C++, su compilacion, su ejecucion y, en su caso, sudepuracion hasta constatar su correcto funcionamiento.

Al cluster hendrix-ssh se puede acceder desde cualquier puesto de trabajo conectado a la redinformatica de la Universidad de Zaragoza. Tambien es posible conectarse a el desde cualquier cualquiercomputador con acceso a internet. Las instrucciones para hacerlo se pueden consultar en la web de laasignatura Programacion 2 (enlace Como programar en C++).

En la sesion de laboratorio correspondiente a esta practica cada alumno debera seguir el presenteguion ejecutando las operaciones y tareas que en el se van describiendo, comprendiendo su significadoy preguntando al profesor o profesora las dudas que le vayan surgiendo.

El desarrollo del trabajo de programacion propuesto y la obtencion de los resultados pedidos deberancompletarse dentro de las dos semanas del mes de febrero en las que estan programadas las sesiones delaboratorio asociadas a esta practica.

1.3. Primeros pasos en un sistema operativo unix o linux

Los siguientes parrafos presentan una introduccion al manejo del sistema operativo unix. Serecomienda leer el texto a la vez que se ejecutan las ordenes que se describen en el. Lo que aquı se presentaes tambien de aplicacion para un sistema operativo linux.

Para ejecutar una orden unix o linux basta escribir la orden tal y como esta se presenta y pulsar latecla de finalizacion de lınea.

1.3.1. Como iniciar y finalizar una sesion de trabajo

Se puede trabajar directamente en uno de los pc del laboratorio, en modo local ejecutando ordenes linux,o estableciendo conexion con el cluster hendrix-ssh, tal como se detalla a continuacion, ejecutandoordenes unix.

5

Conexion con el cluster hendrix-ssh

Para establecer una conexion con el cluster hendrix-ssh desde uno de los puestos de trabajo dellaboratorio, regidos por un sistema operativo CentOS, una variante del sistema operativo linux, seprocede siguiendo los siguientes cuatro pasos:

1. Accediendo a la cuenta personal en el sistema operativo CentOS.

2. Activando el icono de la aplicacion Terminal situado en la parte superior de la ventana. Se abreuna nueva ventana con el nombre Terminal.

3. Ejecutando en la nueva ventana Terminal la orden ssh de conexion a otro computador, en estecaso al cluster hendrix-ssh:

lab0.04 $ ssh -X hendrix-ssh

4. Se establecera la conexion con uno de los computadores, hendrix01 o hendrix02, del clusterhendrix-ssh que se limitara a pedir la contrasena (password) de la cuenta, que coincidecon la empleada para acceder al sistema operativo CentOS. Para asegurar la confidencialidad dela contrasena, el sistema no produce ningun eco en pantalla (salida estandar) al escribir lacontrasena, que debera finalizar pulsando la tecla de fin de lınea.

password: <<-- ¡ojo, lo tecleado no hace eco en pantalla!

Sesion de trabajo con el cluster hendrix-ssh

Tras establecer conexion con el cluster hendrix-ssh aparecera en pantalla una secuencia de caracteresde aviso (o prompt), por ejemplo hendrix01:-/ o bien hendrix02:-/, que sirven para indicarle alusuario que el sistema operativo unix de hendrix-ssh esta listo para aceptar sus ordenes.

password: <<-- ¡ojo, lo tecleado no hace eco en pantalla!

Last successful login for a334412: Tue Sep 22 11:03:08 MET-1METDST 2008

hendrix02:-/ <<-- hendrix02 esta dispuesto a recibir ordenes Unix

La interfaz de usuario de mas bajo nivel del sistema operativo unix se basa en la escritura deinstrucciones u ordenes en modo textual al computador. El programa encargado de presentar el aviso(prompt), de procesar las ordenes y de ejecutarlas (aparte de muchas otras cosas mas), se conoce comoshell (concha).

A partir de este momento el usuario puede ejecutar ordenes unix desde su cuenta de trabajo hasta quede por terminada la sesion de trabajo.

Al concluir el trabajo, el usuario debe finalizar la sesion antes de abandonar el terminal para evitar queuna persona no autorizada pueda acceder a su cuenta de trabajo. Ello se logra mediante la orden unixexit.

hendrix02:-/ exit <<-- fin de la sesion de trabajo en hendrix-ssh

6

Para volver a trabajar en hendrix-ssh sera necesario iniciar una nueva sesion de trabajo de la forma quese ha indicado anteriormente.

1.3.2. Directorios y ficheros en unix (o en linux)

La informacion se almacena en ficheros y estos se organizan en directorios.

Los ficheros se almacenan en directorios, de forma semejante a como se acomodan los libros en losestantes en una biblioteca. El concepto de directorio es analogo al de carpeta en un sistema operativobasado en iconos. Cuando accedes a tu cuenta, el sistema te situa en tu directorio personal. Ese directorio seconoce normalmente como tu HOME. Escribiendo la orden pwd (print working directory) puedesconocer el nombre completo del directorio en que te encuentras.

hendrix02:-/ pwd <<-- muestra la ruta desde la raiz al directorio actual

Un directorio puede contener otros directorios, ası como ficheros, de forma similar a como una carpetapuede almacenar otras carpetas junto a una coleccion de ficheros. La manera natural de imaginarse estaorganizacion es considerarla como un arbol de directorios y ficheros. El diagrama de la figura aclara esto.

El nombre completo de un directorio consta de la ruta o camino desde el directorio raız \ hasta el propiodirectorio. El nombre completo de un fichero es el resultado de concatenar la ruta desde el directorio raız \hasta el directorio que lo aloja, seguida del nombre del fichero. Para ilustrarlo se presentan a continuacionlos nombres de algunos de los directorios y ficheros mostrados en la figura anterior.

/ <<-- directorio raiz/users2/users2/prg01/users2/prg01/quimicos/users2/prg01/quimicos/X1234567 <<-- directorio HOME de X1234567/users2/prg01/quimicos/X1234567/practicas <<-- subdirectorio del anterior/users2/prg01/quimicos/X1234567/carta.txt <<-- fichero carta.txt/users2/prg01/quimicos/X1234567/prueba1.p <<-- fichero prueba1.p

7

Para inspeccionar el contenido de un directorio (en este caso, el de tu HOME), se utiliza la instruccionls (listar). Si listas el contenido de tu directorio y no aparece nada, eso significa que, en ese momento, tudirectorio aun esta vacıo.

hendrix02:-/ ls <<-- lista el contenido del directorio actual

1.3.3. Ordenes unix o linux

Las ordenes que se van a presentar en los apartados que siguen son validas tanto en un sistema unixcomo tambien en un sistema linux.

Antes de presentar nuevas ordenes conviene advertir que, al escribir una orden unix, las letrasmayusculas y minusculas tiene un significado diferente.

Existen multitud de ordenes o instrucciones en unix. Para ver como funcionan vamos a experimentarcon algunas de ellas.

Hay ordenes que no requieren ningun parametro. Ejecuta, por ejemplo, la orden date que informasobre la fecha y hora actuales.

hendrix02:-/ date <<-- presenta la fecha y hora actualMon Feb 13 11:51:14 CET 2012

Sin embargo, la mayorıa de las ordenes unix requieren de algun parametro para trabajar. Estosparametros se le pasan a la instruccion como argumentos en la misma lınea de la instruccion, separadospor espacios. Por ejemplo, la instruccion ls permite conocer el contenido de una coleccion de directoriosque se enumeran en la propia orden:

hendrix02:-/ ls /export /export/home

La salida estandar de cualquier instruccion unix es, por defecto, la pantalla del terminal. No obstante,la salida de resultados puede dirigirse hacia un fichero de texto de nueva creacion (para almacenarla en el)mediante el operador > seguido del nombre del fichero, de la siguiente forma:

hendrix02:-/ ls /export /proc > resultados

Si ahora listas el contenido de tu directorio (orden ls), veras un fichero de texto con el nombreresultados.

hendrix02:-/ ls

Para visualizar el contenido de un fichero de texto, podemos utilizar la instruccion cat (concatenar):

hendrix02:-/ cat resultados <<-- presenta el texto seleccionado

Veras que el texto almacenado en el fichero es presentado por el terminal, pero como tiene mas lıneasde las que caben en la pantalla, en el listado final quedan ocultas una parte de las lıneas. Para ver el fichero,pagina a pagina, podemos ejecutar la orden more:

8

hendrix02:-/ more resultados <<-- presenta el texto seleccionado

Comprueba que la salida se detiene tras presentar una pagina, esperando que pulses la barraespaciadora para mostrar la siguiente pagina. Si quieres cancelar la visualizacion, pulsa la tecla Q o pulsasimultaneamente las teclas Control y C, es decir, pulsa Control+C.

La combinacion de teclas Control+C se utiliza frecuentemente cuando se desea poner fin(abortar) una orden o un programa en ejecucion.

Hasta ahora hemos visto ordenes, con y sin argumentos, que implican la ejecucion de una operaciondeterminada. El comportamiento de una orden unix puede ser modificado o matizado mediante lo que sedenominan opciones.

Las opciones se le pasan a una instruccion como si fueran argumentos, viniendo siempre precedidas porel caracter -.

Hemos visto la orden ls para listar el contenido de un directorio. Probemos ahora a ejecutar la siguienteorden.

hendrix02:-/ ls -l <<-- presenta el contenido del directorio

El listado mostrado es ligeramente distinto ya que presenta mas informacion que la anterior.

La orden ls -l es tan utilizada que se puede ejecutar de forma abreviada mediante la orden ll.

hendrix02:-/ ll <<-- equivale a: ls -l

Para conocer todas las opciones disponibles y los argumentos necesarios de una orden se puede utilizarla ayuda on-line de unix mediante la orden man (manual) o acudir a un buscador en internet (Google uotro):

hendrix02:-/ man ls <<-- manual de ayuda para explicar la orden "ls"

1.3.4. Trabajo con ficheros y directorios en unix o en linux

Para copiar ficheros se utiliza la orden cp (copy):

hendrix02:-/ cp resultados copiaResultadoshendrix02:-/ ll

La orden rm (remove) borra o elimina ficheros. Debe extremarse el cuidado al ejecutar una orden deborrado, ya que no es posible la vuelta atras en caso de error. Los ficheros borrados estan definitivamenteperdidos.

hendrix02:-/ rm copiaResultados <<-- elimina el fichero

Si necesitas nuevos directorios para organizar tus ficheros, los puedes crear dentro de tu directorio conla orden mkdir (make directory). Crearemos el directorio pruebas.

9

hendrix02:-/ mkdir pruebas <<-- crea un nuevo directoriohendrix02:-/ mkdir pruebas1 <<-- crea otro nuevo directorio

La orden rmdir (remove directory) borra o elimina directorios.

hendrix02:-/ rm pruebas1 <<-- elimina el directorio pruebas1

La orden cd (change of directory) permite navegar por los directorios. Vamos a navegar por eldirectorio pruebas (cd pruebas) y otros mas.

hendrix02:-/ cd pruebas <<-- se situa en pruebashendrix02:-/ cd / <<-- se situa en el directorio raiz /hendrix02:-/ cd /export/home <<-- se situa en /export/homehendrix02:-/ pwd/export/home/

La instruccion cd sin argumentos nos devuelve al directorio base de nuestra cuenta (al directorio HOME).

hendrix02:-/ cd <<-- vuelve al directorio base de nuestra cuenta

La misma instruccion se puede expresar haciendo uso de la direccion simbolica $HOME que hacereferencia al directorio base de nuestra cuenta.

hendrix02:-/ cd $HOME <<-- vuelve al directorio base de nuestra cuenta

La instruccion cd .. permite ir hacia atras, volviendo al directorio padre del actual.

hendrix02:-/ cd .. <<-- vuelve al directorio padre

El directorio que contiene al directorio en que estas (su directorio ”padre”) se representa con ’..’ (dospuntos seguidos). El directorio en que estas se representa con ’.’ (un punto). Compruebalo ejecutando lassiguientes ordenes:

hendrix02:-/ ll . <<-- listado del directorio actualhendrix02:-/ ll .. <<-- listado del directorio padre del actual

Para trasladar un fichero de su directorio a otro directorio se utiliza la instruccion mv (move) expresandoel nombre del fichero a trasladar como primer parametro y el directorio de destino como segundo parametro.Situate en tu directorio HOME y crea un fichero con un texto mediante la orden cat sin argumentos:

hendrix02:-/ cat > nombreTexto

Ahora puedes ir escribiendo varias lıneas de texto y la instruccion las ira copiando a tu ficheronombreTexto. Cuando decidas no introducir mas texto, teclea Control-D. Puedes comprobar con

10

ls la existencia del fichero nombreTexto. Comprueba su contenido ejecutando la orden cat. Esta esuna forma sencilla, pero muy limitada, de generar ficheros de texto. Lo normal es utilizar un editor detextos como, por ejemplo, gedit que se estudiara un poco mas adelante. Para trasladar el fichero textonombreTexto al directorio pruebas, escribe y ejecuta:

hendrix02:-/ mv nombreTexto pruebas

Situate en pruebas, comprueba que el fichero esta allı:

hendrix02:-/ cd pruebashendrix02:-/ ll

La instruccion mv tiene una segunda funcion, diferente de la anterior, ya que permite cambiar elnombre de un fichero, definiendo como primer parametro el nombre del fichero a cambiar y como segundoparametro su nuevo nombre. Cambia el nombre del fichero nombreTexto a texto.txt, compruebaque el cambio se ha efectuado y borralo:

hendrix02:-/ mv nombreTexto texto.txthendrix02:-/ llhendrix02:-/ rm texto.txt

Queremos senalar finalmente que cabe la posibilidad de utilizar el caracter ’*’ en una orden unix amodo de comodın.

hendrix02:-/ rm p*0.txt

La orden anterior eliminara todos los ficheros almacenados en el directorio cuyo sufijo sea txt y cuyonombre comienze por la letra p y acabe con el dıgito 0.

hendrix02:-/ cp *.txt pruebas

La orden anterior hace una copia en el directorio pruebas de todos los ficheros almacenados en eldirectorio actual cuyo sufijo sea txt.

1.3.5. Organizacion de nuestro directorio de trabajo

En primer lugar vamos a crear en nuestro directorio de trabajo un subdirectorio denominadoprogramacion2 para almacenar en el y en sus subdirectorios todos los ficheros relacionados con laasignatura.

hendrix02:-/ cd <<-- nos situamos en nuestro directorio de trabajohendrix02:-/ mkdir programacion2

A su vez, en el subdirectorio programacion2 creamos los siguientes nuevos directorios:

11

hendrix02:-/ cd $HOME/programacion2hendrix02:-/ mkdir practica1hendrix02:-/ mkdir practica2hendrix02:-/ mkdir practica3hendrix02:-/ mkdir practica4hendrix02:-/ mkdir practica5hendrix02:-/ mkdir datos

practica1, practica2, . . . , practica5 para almacenar el codigo fuente de los programasC++ que desarrollemos en las diferentes practicas de la asignaturas.

datos para almacenar los ficheros de datos que utilicen o generen nuestros programas.

Los ficheros con codigo C++ o con datos que se faciliten para la realizacion de estas practicas estaranaccesibles desde la seccion de Material docente comun de la web de Programacion 2.

1.3.6. Edicion de programas fuente C++

Para crear ficheros fuente con codigo escrito en C++ y poder modificarlos posteriormente, utilizaremosel editor de textos gedit. Podemos invocarlo por primera vez para editar el codigo del ficherosaludo.cc.

hendrix02:-/ cd $HOME/programacion2/practica1hendrix02:-/ gedit saludo.cc &

Al invocar el editor gedit no olvidar el ultimo caracter escrito, &, ya que facilita que se abra una nuevaventana de edicion, manteniendo activa la ventana de ordenes unix. Si se omite dicho caracter, la ventanade ordenes unix queda desactivada hasta que no se sale del programa editor gedit.

El codigo del fichero saludo.cc lo podemos copiar desde la carpeta practica1, accesible desdela web de Programacion 2 (seccion de Material docente comun), y pegar en la ventana deleditor gedit.

#include <iostream>

using namespace std;

/∗∗ Pre: −−−∗ Post : Escribe por la salida estandar ”Un saludo, amigos”∗/

int main() {cout << ”Un saludo, amigos” << endl;return 0;

}

A menos que se diga otra cosa, cuando se genera un nuevo fichero, este se crea en el directorio actual.Si se quiere acceder o crear un fichero en un directorio distinto al actual, basta con anteponer al nombredel fichero su ”trayectoria”(path). La trayectoria representa el nombre completo de una ruta, desde laraız (o desde el directorio en que estamos) hasta un fichero particular, a traves del arbol de directorios. Si

12

estamos en nuestro directorio HOME, en el que tenemos un directorio programacion2, y dentro de el otrollamado practica1 en el que hay un fichero saludo.cc, y queremos hacer una listado por pantalla deeste ultimo fichero:

hendrix02:-/ cdhendrix02:-/ cd programacion2hendrix02:-/ cd practica1hendrix02:-/ cat saludo.cc

O bien:

hendrix02:-/ cdhendrix02:-/ cd programacion2/practica1hendrix02:-/ cat saludo.cc

E incluso, sin movernos de nuestro directorio HOME:

hendrix02:-/ cdhendrix02:-/ cat programacion2/practica1/saludo.cc

Es decir, en la orden correspondiente se ha detallado el nombre del fichero, saludo.cc, precedido porsu trayectoria o camino,programacion2/practica1/. Del mismo modo, tambien serıa valido:

hendrix02:-/ cat $HOME/programacion2/practica1/saludo.cc

1.4. Puesta a punto de un programa escrito en C++

Lo que se describe en los siguientes apartados se puede aplicar al trabajo de puesta a punto deprogramas en un computador con sistema operativo unix, por ejemplo, en el cluster hendrix-ssh,o en un computador con sistema operativo linux, por ejemplo, en cualquiera de los computadorespersonales de los laboratorios de practicas.

1.4.1. Compilacion y ejecucion de un programa escrito en C++

Vamos a comenzar editando, compilando y ejecutando el programa C++ almacenado en el ficherosaludo.cc.

Compilacion paso a paso de un programa escrito en C++

Tras situarnos en el directorio programacion2/practica1, compilaremos el fichero saludo.ccejecutando la orden g++ saludo.cc -c. Esta orden compila el codigo fuente del programa y creael fichero saludo.o que almacena el codigo objeto (binario) resultado de la compilacion.

A continuacion generaremos un programa ejecutable, al que vamos a dar el nombre saludo1,ejecutando la orden g++ saludo.o -o saludo1.

13

hendrix02:-/ cd $HOME/programacion2/practica1hendrix02:-/ g++ saludo.cc -chendrix02:-/ g++ saludo.o -o saludo1

Se puede comprobar que, junto al fichero saludo.cc, se encuentran los ficheros saludo.o ysaludo1, creados al ejecutar las dos ordenes anteriores.

Ya estamos en condiciones de ejecutar cuantas veces lo deseemos el programa ejecutable saludo1mediante la orden ./saludo1:

hendrix02:-/ ./saludo1Un saludo, amigoshendrix02:-/ ./saludo1Un saludo, amigoshendrix02:-/ ./saludo1Un saludo, amigoshendrix02:-/

Como abreviar la compilacion de un programa escrito en C++

El proceso anterior se puede simplificar mediante la orden g++ saludo.cc -o saludo2 quecompila el programa fuente saludo.cc, crea un fichero que almacena el correspondiente programaejecutable, en este caso bajo el nombre saludo2, y borra finalmente el fichero binario saludo.oresultante de la compilacion.

hendrix02:-/ g++ saludo.cc -o saludo2hendrix02:-/ ./saludo2Un saludo, amigoshendrix02:-/ ./saludo2Un saludo, amigos

El proceso de creacion de un programa ejecutable puede simplificarse aun mas hacendo uso de laherramienta make, ejecutando la orden make saludo. Esta orden localiza en el directorio actual el ficherofuente saludo.cc, lo compila, crea un programa ejecutable, al que denomina saludo y borra el ficherobinario resultante de la compilacion.

hendrix02:-/ make saludoCC -o saludo saludo.cchendrix02:-/ ./saludoUn saludo, amigoshendrix02:-/ ./saludoUn saludo, amigos

Si la orden make saludo se ejecuta de nuevo, sin haber habido cambios en los ficheros implicadosen el proceso, saludo.cc y saludo, su ejecucion se limita a afirmar que el programa saludoesta actualizado:

hendrix02:-/ cd $HOME/prog2/practica1hendrix02:-/ make saludo

14

’saludo’ is up to date.hendrix02:-/ ./saludoUn saludo, amigoshendrix02:-/ ./saludoUn saludo, amigos

Sobre el uso y posibilidades de la herramienta make se profundizara en la practica tercera de estaasignatura.

Como optimizar el codigo generado por un compilador de C++

Los compiladores pueden intentar realizar determinadas optimizaciones del codigo que generan. Elloredundara en una mayor eficiencia de los programas ejecutables, a costa de un mayor esfuerzo en lacompilacion.

Al ejecutar una orden de compilacion se puede seleccionar el nivel de optimizacion del codigo generadomediante la opcion -On, donde n es un natural que expresa el nivel de optimizacion (a mayor nivel, mayorgrado de optimizacion). Hay cinco niveles de optimizacion:

Nivel 0 de optimizacion (optimizacion por defecto).

hendrix02:-/ g++ saludo.cc -O0 -o saludo0

O bien, omitiendo la opcion-O0:

hendrix02:-/ g++ saludo.cc -o saludo0

Nivel 1 de optimizacion.

hendrix02:-/ g++ saludo.cc -O1 -o saludo1

Nivel 2 de optimizacion.

hendrix02:-/ g++ saludo.cc -O2 -o saludo2

Nivel 3 de optimizacion.

hendrix02:-/ g++ saludo.cc -O3 -o saludo3

Nivel 4 de optimizacion.

hendrix02:-/ g++ saludo.cc -O4 -o saludo4

15

1.4.2. Correccion de errores de un programa C++

Vamos a utilizar de nuevo el editor de textos gedit, ahora con un fin malevolo, el de provocar un parde errores en el codigo almacenado en el fichero saludo.cc.

hendrix02:-/ gedit saludo.cc &

Al invocar el editor gedit no olvidar de nuevo escribir como ultimo caracter & ya que facilita que seabra una nueva ventana de edicion, manteniendo activa la ventana de ordenes unix.

Eliminamos del fichero la lınea la declaracion using namespace std;. Ahora el contenido delfichero saludo.cc sera el siguiente:

#include <iostream>

/∗∗ Pre: −−−∗ Post : Escribe por la salida estandar ”Un saludo, amigos”∗/

int main() {cout << ”Un saludo, amigos” << endl;return 0;

}

Al compilar el programa saludo.cc, el propio compilador informa de dos errores detectados,informando de la lınea en la que se situan y haciendo un diagnostico de cada uno de ellos.

hendrix02:-/ make saludoCC -o saludo saludo.cc"saludo.cc", line 8: Error: cout is not defined."saludo.cc", line 8: Error: endl is not defined.2 Error(s) detected.

*** Error code 2make: Fatal error: Command failed for target ’saludo’

hendrix02:-/

1.5. Tecnologıa y herramientas

En este apartado se presentan algunos recursos tecnologicos del lenguaje C++ cuyo conocimiento nosresultara de utilidad en el desarrollo de algunos de los trabajos que se van a proponer en las practicas deesta asigantura.

1.5.1. Transmision de datos a traves de la lınea de ordenes

Al invocar la ejecucion de un programa es posible transmitirle informacion a traves de la lınea quecontiene la orden para ejecutarlo.

De este modo, en la invocacion al programa listarArgumentos, que se presenta a continuacion,estamos, en, febrero, de y 2018 son datos que se transmiten al programa listarArgumentos

16

en la misma lınea que contiene la orden de ejecutar el programa.

hendrix02:-/ ./listarArgumentos estamos en febrero de 2018

Un posible diseno del codigo del programa listarArgumentos.cc se presenta a continuacion. Elprograma se limita a presentar un listado numerado de los datos que figuran en la lınea de ordenes.

#include <iostream>

using namespace std;

/∗∗ Pre: −−−∗ Post : Presenta por la salida estandar un listado en el que se numeran∗ los argumentos presentes en la linea de ordenes∗/

int main ( int numArg, char∗ args []) {for ( int i = 0; i < numArg; ++i) {

cout << i+1 << ”. ” << args[i] << endl;}return 0;

}

Al ser ejecutada la orden ./listarArgumentos estamos en febrero de 2018, elargumento numArg de la funcion main(numArg,args) toma como valor el numero de cadenas osecuencias de caracteres presentes en la lınea de ordenes, incluyendo en este numero la cadena con lainvocacion al programa, ./listarArgumentos, es decir, en este caso tomara el valor 6.

El segundo argumento, args, es una referencia a un vector de cadenas de caracteres. Cadauno de dichas cadenas almacena, al ser ejecutada la orden ./listarArgumentos estamos enfebrero de 2017 una de las cadenas de la lınea de ordenes. Ası, args[0] almacena la cadena./listarArgumentos, args[1] almacena la cadena estamos, args[2] almacena la cadena en,args[3] almacena la cadena febrero, args[4] almacena la cadena de y, finalmente, args[5]almacena la cadena 2018.

Por lo tanto, los resultados observables por pantalla al ejecutar la orden ./listarArgumentosestamos en febrero de 2018, son los que se muestran a continuacion.

hendrix02:-/ ./listarArgumentos estamos en febrero de 20181. ./listarArgumentos2. estamos3. en4. febrero5. de6. 2018

1.5.2. Medida del tiempo desde un programa

Se va a explicar como medir desde un programa el tiempo real invertido en la ejecucion de una secuenciade instrucciones y el tiempo dedicado por el procesador en la ejecucion de una secuencia de instrucciones.

17

Medida del tiempo invertido en ejecutar una secuencia de instrucciones

Los recursos a utilizar para medir el tiempo real empleado en ejecutar una secuencia de instrucciones decodigo se encuentran definidos en la biblioteca predefinida <ctime> y son los siguientes:

Tipo de dato time t. Un dato de este tipo representa una medida de tiempo con precision de unsegundo. Los datos de tipo time t admiten operaciones aritmeticas.

La invocacion time(NULL) que devuelve el valor del tiempo actual como un dato de tipo time t.

Para mayor informacion y detalle sobre estos recursos conviene consultar el manual de bibliotecaspredefinidas en C++.

La forma de calcular el tiempo real invertido en ejecutar una secuencia de instrucciones A1; ...;Ak; se ilustra en el esquema mostrado a continuacion.

// Declara la variable t1 y toma una primera medida del tiempo realtime t t1 = time(NULL);A1; ...; Ak; // Secuencia de instrucciones cuya duracion se desea medir// Declara la variable t2 y toma una segunda medida del tiempo realtime t t2 = time(NULL);// Calcula la diferencia entre ambas medidas de tiempo y la transforma en un valor// de tipo int que expresa el tiempo real trancurrido , en segundosint segundos = int ( t2 − t1 );

Medida del tiempo de procesador dedicado a ejecutar una secuencia de instrucciones

El tiempo real transcurrido durante la ejecucion de una secuencia de instrucciones no coincidenecesariamente con el tiempo que el procesador (CPU) del computador ha estado dedicado a ejecutarla.Esta diferencia se manifiesta especialmente en programas interactivos, cuando su duracion depende de larapidez con la que el operador facilta los datos solicitados por el programa.

Los recursos a utilizar para medir el tiempo que el procesador dedica a ejecutar una secuencia deinstrucciones se encuentran tambien definidos en la biblioteca predefinida <ctime> y son los siguientes:

Tipo de dato clock t. Un dato de este tipo representa una medida del tiempo. Dicho tiempo seexpresa en unas unidades denominadas tics.

La constante CLOCKS PER SEC cuyo valor es igual al numero de tics que hay en un segundo.Este valor no es fijo, sino que depende de cada implementacion del lenguaje.

La funcion clock() devuelve el valor del tiempo de procesador invertido en de ejecucion delprograma desde su inicio. El valor devuelto es un dato de tipo clock t.

Para mayor informacion y detalle sobre estos recursos conviene consultar el manual de bibliotecaspredefinidas en C++.

La forma de calcular el tiempo de procesador invertido en ejecutar una secuencia de instrucciones A1;...; Ak; se ilustra en el esquema mostrado a continuacion.

18

// Declara la variable t1 y toma una primera medida del tiempo de dedicacion// del procesador al programaclock t t1 = clock ();A1; ...; Ak; // Secuencia de instrucciones cuya duracion se desea medir// Declara la variable t2 y toma una nueva medida del tiempo de dedicacion// del procesador al programaclock t t2 = clock ();// Calcula, en segundos y como dato de tipo float , el tiempo de procesador dedicado// a ejecutar la anterior secuencia de instruccionesfloat segundos = float ( t2− t1) / CLOCKS PER SEC;

1.5.3. Generacion de datos pseudoaleatorios

Los recursos que vamos a utilizar para generar datos numericos pseudoaleatoros se encuentran definidosen la biblioteca predefinida <cstdlib>. Se trata unicamente de dos funciones y de una constante:

La funcion srand(semilla) permite definir la semilla a partir de la cual inicializar lageneracion de numeros pseudoaleatorios. Para un valor de semilla determinado, se genera una mismasecuencia de numeros pseudoaleatorios. Por ello, es conveniente utilizar una semilla diferente comoinicializacion de dicha secuencia. Una forma practica de resolver el problema es definir una semillaque dependa del instante en que se ejecuta la instruccion, por ejemplo, srand(time(NULL)).Tal como se ha mencionado anteriormente, la funcion time(NULL) esta definida en la bibliotecapredefinida <ctime>. Devuelve un valor que representa el tiempo actual (para conocer los detallesconviene consultar el manual de las bibliotecas estandar predefinidas en C++).

La funcion rand() devuelve un entero de tipo int, comprendido entre 0 y RAND MAX, que esgenerado de forma pseudoaleatoria.

La constante RAND MAX cuyo valor es igual el del maximo dato de tipo int que puede serrepresentado y depende de cada implementacion del lenguaje.

El segmento de codigo C++ mostrado a continuacion ilustra como es posible generar una secuencia denumeros enteros pseudoaleatorios.

/∗∗ Pre: n > 0 AND desde <= hasta AND AND (hasta − desde) <= RAND MAX∗ Post : El vector v[0,n−1] almacena n datos del intervalo [desde, hasta] generados∗ de modo pseudoaleatorio∗/

void generar ( int v [], const int n, const int desde, const int hasta ) {time t semilla = time(NULL); // Asigna a semilla un valor entero que representa el tiempo actualsrand( semilla ); // Inicializa con semilla el generador de numeros pseudoaleatoriosfor ( int i = 0; i < n; ++i) {

// Asigna a v[ i ] un numero pseudoaleatorio del intervalo [desde, hasta]v[ i ] = desde + rand () % (hasta − desde + 1);

}}

19

1.5.4. Programacion de funciones genericas

El lenguaje C++ permite programar funciones genericas definiendo plantillas (template). Unaplantilla, en la cual se declaran uno o mas parametros genericos, se define inmediatamente antes de lacabecera de la funcion. Esos parametros genericos son visibles y pueden ser utilizados en la funcion.

A continuacion se muestran dos funciones genericas, permutar(a,b) y ordenar(v,n).

La funcion generica permutar(a,b) se ha programado definiendo sus dos parametros comoreferencias a sendas variables genericas de tipo T.

La genericidad de la funcion ordenar(v,n) esta soportada por el tipo generico Tipo. En el codigode la funcion se invoca la funcion anterior de la forma permutar(v[i],v[iMenor]).

/∗∗ Pre: a = X y b = Y∗ Post : a = Y y b = X∗/

template <typename T>void permutar (T& a, T& b) {

T aux = a;a = b; b = aux;

}

/∗∗ Pre: n > 0∗ Post : v [0.. n−1] es una permutacion de los datos iniciales de v [0.. n−1] y todos∗ ellos estan ordenados de menor a mayor valor∗/

template <typename Tipo>void ordenar (Tipo v [], const int n) {

// Ordenacion del vector v[0,n−1] por el metodo de seleccionfor ( int i = 0; i < n−1; ++i) {

// Los datos de v [0.. i−1] son los menores y estan ordenados de menor a mayor valor// Selecciona el dato menor de v[ i .. n−1]int iMenor = i ;for ( int j = i + 1; j < n; ++j) {

// v[iMenor] es el menor de v[ i .. j−1]if (v[ j ] < v[iMenor]) {

iMenor = j ;}// viMenor] es el menor de v[ i .. j ]

}// v[iMenor] es el menor de v[ i .. n−1]// Permuta v[ i ] y v[iMenor]permutar(v[ i ], v[iMenor]);// Los datos de v [0.. i ] son los menores de v [0.. n−1] y estan ordenados de menor// a mayor valor

}// Los datos de v [0.. n−1] ya estan ordenados

}

La funcion permutar(a,b) puede ser invocada para permutar las valores de dos variables del mismotipo, independientemente de cual sea el tipo. La unica condicion que debe cumplir dicho tipo es que tengaimplementada la operacion de asignacion, que figura programada por tres veces en el codigo de la funcion.

La funcion ordenar(v,n) puede ser invocada para ordenar los valores de cualquier vector o tabla

20

v[0..n-1] que almacene datos de cualquier tipo. La unica condicion que debe cumplir dicho tipo es quetenga implementadas todas operaciones programadas en el codigo de la funcion:

El operador de comparacion < programado en la expresion: v[j] < v[iMenor]

La asignacion de valor a una variable del mismo tipo, programada por tres veces dentro del codigoasociado a la funcion permutar(a,b), invocada desde el codigo de ordenar(v,n) de la formapermutar(v[i],v[iMenor]).

He aquı un ejemplo que ilustra como invocar la funcion ordenar(v,n) para ordenar una tabla dedatos enteros.

// Declara una tabla de datos enterosconst int DIM = 10000;int v[DIM];// Almacena en dicha tabla DIM datos pseudoaletorios comprendidos en el intervalo [0,3500]generar (v, DIM, 0, 3500);// Ordena los datos DIM de dicha tabla de menor a mayor valorordenar(v, DIM);

. . .

21

1.6. Trabajo a desarrollar en esta practica

Para consolidar las ideas y el conocimiento sobre las herramientas presentadas en esta practica, cadaalumno debe desarrollar y poner a punto los cuatro programas que se detallan a continuacion. El codigo delos ficheros de estos programas se ubicara en el directorio programacion2/practica1.

Se recomienda completar este trabajo dentro de las dos semanas en las que hay programadas sesiones detrabajo en laboratorio correspondientes a esta primera practica, es decir, antes de concluir el mes de febrero.

1.6.1. Especificacion del primer programa a desarrollar

Se sugiere que este primer programa ejecutable a desarrollar sea denominado tiempoReaccion. Alser invocado pedira al operador cierto numero de veces que pulse la tecla de fin de lınea e informara cadauna de las veces del tiempo transcurrido, en segundos, entre la aparicion del mensaje con dicha peticion yel momento en que el operador pulsa cada vez la tecla pedida.

El numero de veces que el programa pide al operador que pulse la tecla de fin de lınea se ha de especificarcomo argumento en la lınea de ordenes. He aquı una ilustracion del modo de funcionamiento de dichoprograma en el que en la lınea de ordenes se incluye el argumento 3, que denota que el protocolo peticion-respuesta debe repetirse 3 veces:

hendrix02:-/ ./tiempoReaccion 31) Pulse la tecla de fin de linea, por favor ...Su tiempo de reaccion ha sido de 2 segundos

2) Pulse la tecla de fin de linea, por favor ...Su tiempo de reaccion ha sido de 6 segundos

3) Pulse la tecla de fin de linea, por favor ...Su tiempo de reaccion ha sido de 0 segundos

hendrix02:-/ ...

Si en la lınea de ordenes se omite el argumento numerico que denota el numero de veces, el programase limitara a pedir al operador que pulse la tecla de fin de lınea una sola vez.

hendrix02:-/ ./tiempoReaccion1) Pulse la tecla de fin de linea, por favor ...Su tiempo de reaccion ha sido de 4 segundos

hendrix02:-/ ...

1.6.2. Especificacion del segundo programa a desarrollar

Se sugiere que el segundo programa ejecutable a desarrollar sea denominado generarTabla01.Este programa presentara por la salida estandar (pantalla), en 10 columnas, una secuencia de datosenteros generados de forma pseudoaleatorıa. En la propia lınea de ordenes de invocacion al programa seespecificara el numero de datos a generar (por ejemplo, 250 datos) y los valores enteros mınimo y maximode los datos pseudodoaleatorios generados (por ejemplo, 1 y 100). He aquı una ilustracion del modo defuncionamiento de dicho programa.

22

hendrix02:-/ ./generarTabla01 250 1 10037 85 3 12 88 43 37 21 10 6254 33 13 52 61 11 93 7 26 48

. . .28 83 19 74 62 50 49 92 35 66

hendrix02:-/ ...

1.6.3. Especificacion del tercer programa a desarrollar

Se sugiere que el tercer programa ejecutable a desarrollar sea denominado generarTabla02.Este programa presentara por la salida estandar (pantalla), en 10 columnas, una secuencia de datosreales generados de forma pseudoaleatorıa. En la propia lınea de ordenes de invocacion al programa seespecificara el numero de datos a generar (por ejemplo, 500 datos) y los valores reales mınimo y maximode los datos pseudodoaleatorios generados (por ejemplo, 0.0 y 10.0). He aquı una ilustracion del modo defuncionamiento de dicho programa.

hendrix02:-/ ./generarTabla02 500 0.0 10.03.165 3.298 9.483 . . . 7.577 3.682 6.3876.257 2.449 5.876 . . . 7.370 3.961 8.703

. . .1.014 3.009 8.039 . . . 9.203 2.231 5.319

hendrix02:-/ ...

1.6.4. Especificacion del cuarto programa a desarrollar

Se sugiere que el cuarto programa a desarrollar sea denominado medirCoste. Al ser invocado deberanaportarse cuatro parametros en la lınea de ordenes: el numero de datos a ordenar (por ejemplo, 20000 datos),los valores mınimo y maximo de dichos datos (por ejemplo, 1 y 10000) y un nombre que identifique alcomputador en el que se ejecuta el programa (por ejemplo, hendrix).

Los resultados que presenta el programa medirCoste por la salida estandar (pantalla) se describen acontinuacion. Al lanzar su ejecucion, genera una secuencia de 20000 datos pseudoaleatorios comprendidosen el intervalo [1,10000], los extremos del intervalos corresponden a los valores mınimo y maximo de losdatos aportados en la lınea de ordenes, muestra los 20 primeros y los 20 ultimo datos de dicha secuencia einforma que esta procediendo a su ordenacion (de menor a mayor valor).

hendrix02:-/ ./medirCoste 20000 1 10000 hendrix

Datos a ordenar:181 2382 2675 4096 4352 7153 5827 6079 6656 8802

7847 5045 2292 8447 510 1169 7722 2165 2609 9946. . .

8145 3888 548 1177 4850 99 727 4320 3446 50414865 2129 7316 3578 9252 8179 8151 2608 624 2925

Ordenando 20000 datos enteros en hendrix...

23

Tras haber concluido la ordenacion de la secuencia, muestra los 20 primeros datos y los 20 ultimosdatos, ya ordenados, e informa del tiempo de CPU (procesador) invertido en dicha ordenacion.

hendrix02:-/ ./medirCoste 20000 1 10000 hendrix

Datos a ordenar:181 2382 2675 4096 4352 7153 5827 6079 6656 8802

7847 5045 2292 8447 510 1169 7722 2165 2609 9946. . .

8145 3888 548 1177 4850 99 727 4320 3446 50414865 2129 7316 3578 9252 8179 8151 2608 624 2925

Ordenando 20000 datos enteros en hendrix ...

Datos ordenados:2 3 4 4 5 5 5 6 7 88 9 9 9 9 10 11 12 12 13

. . .9991 9991 9992 9992 9992 9993 9993 9994 9994 99959995 9996 9996 9997 9997 9998 10000 10000 10000 10000

Tiempo de CPU para ordenar 20000 enteros en hendrix: 11.060 segundos

hendrix02:-/ ...

En el diseno del programa medirCoste se hara uso de la funcion generica ordenar(v,n) quepermite ordenar de menor a mayor valor los datos de una tabla de datos de tipo int.

1.6.5. Resultados del trabajo desarrollado en la primera practicas

Como resultado de esta primera practica, cada alumno dispondra en su cuenta hendrix-ssh de undirectorio (carpeta) denominado programacion2 dentro del cual se podran encontrar el directorio y losficheros que se detallan a continuacion:

1. Directorio (carpeta) programacion2/practica1 con los siguientes ficheros:

Fichero tiempoReaccion.cc con el codigo C++ del primer programa desarrollado en estapractica.

Fichero generarTabla01.cc con el codigo C++ del segundo programa desarrollado en estapractica .

Fichero generarTabla02.cc con el codigo C++ del tercer programa desarrollado en estapractica.

Fichero medirCoste.cc con el codigo C++ del cuarto programa desarrollado en esta practica.

24

1.7. ¿Que hay que saber hacer con soltura tras realizar esta practica?

A continuacion se enumeran los conocimientos practicos que cada alumno debe adquirir como resultadodel trabajo desarrollado en esta practica. Este aprendizaje no puede aplazarse para mas adelante ya que loaprendido va a ser aplicado de forma continuada a partir de este momento.

Cada alumno debe saber ejecutar y comprender las siguientes ordenes de un sistema operativo unixo linux:

• Entrar y salir de la cuenta de trabajo.

• Navegar por los directorios del sistema operativo.

• Visualizar y analizar el contenido de sus directorios.

• Crear nuevos directorios y borrar directorios existentes.

• Hacer una copia de un fichero.

• Cambiar de nombre un fichero.

• Trasladar un fichero de un directorio a otro.

• Borrar un fichero.

• Editar un fichero que almacena un texto.

Cada alumno debe ser tambien capaz de realizar las siguientes operaciones que intervienen en eldesarrollo de un programa C++ en una maquina unix o linux:

• Editar ficheros que almacenen codigo C++ utilizando el editor gedit.• Compilar un programa C++, analizar los posibles errores detectados por el compilador y, en su

caso, corregirlos.

• Ejecutar el programa, un vez haya sido compilado de forma satisfactoria.

• Identificar y corregir los errores en el comportamiento del programa puestos de manifiesto alejecutarlo y someterlo a un conjunto de pruebas suficientemente amplio y significativo, hastatener la conviccion de su correcto funcionamiento.

Finalmente cada alumno debe ser capaz de lo siguiente:

• Disenar programas que reciban datos a traves de la lınea de ordenes.

• Generar secuencias de datos enteros o reales pseudoaleatorios.

• Disenar programas capaces de deducir experimentalmente el coste de la ejecucion - en tiemporeal o en tiempo de procesador - de determinadas acciones algorıtmicas.

25

1.8. Anexo. El servidor hendrix y el sistema operativo unix

1.8.1. El computador de practicas

Algunas de las tareas planteadas en practicas de Programacion 2 se van a realizar sobre uncluster denominado hendrix-ssh integrado por dos computadores Sun UltraSPARC-T2 a 1165MHz del departamento de Informatica e Ingenierıa de Sistemas, conocidos con los nombres familiaresde hendrix01 y hendrix02. El cluster trabaja desde el punto de vista del usuario como una maquinaunica regida por un sistema operativo unix.

Para trabajar en dicho computador es necesario disponer de una cuenta de usuario. Todo alumnodispondra de una cuenta individual en el sistema que le habra sido abierta a principio de curso por eladministrador del cluster hendrix-ssh y comunicado el nombre de su cuenta y la contrasena de accesomediante correo electronico dirigido a su cuenta de correo en la Universidad de Zaragoza.

1.8.2. Acceso a una cuenta en hendrix-ssh

El computador de practicas hendrix-ssh es multiusuario, es decir, permite trabajar a la vez a unamplio numero de usuarios, conectandose cada uno desde un terminal distinto.

Los terminales de acceso al computador de practicas se cuentan por centenares y se encuentrandistribuidos en salas de usuarios de toda la Universidad desde las que se puede entrar a las cuentas.

Los alumnos matriculados en la asignatura tienen una cuenta abierta en la maquina hendrix-ssh paraque puedan trabajar y almacenar en ella programas y datos. Para iniciar una sesion de trabajo es necesarioidentificarse mediante un nombre de usuario (login u username) y una clave o contrasena de acceso(password).

Las cuentas son estrictamente personales. Nadie puede entrar en tu cuenta si no conoce tu contrasenao clave de acceso. Por lo tanto, no se debe decir a nadie la contrasena de la cuenta. Es responsabilidadexclusiva de cada alumno conocer el nombre de usuario y la contrasena de su cuenta en hendrix-ssh.

A la maquina hendrix-ssh se puede acceder desde los puestos de trabajo ubicados en los diferenteslaboratorios del centro o desde cualquier computador con acceso a internet. Para realizar la conexionconviene leer las explicaciones publicadas en la web de la asignatura.

1.8.3. Resumen de ordenes basicas en unix o linux

Antes de comenzar, conviene tener presente que, en el lenguaje de ordenes de unix o linux, una letramayuscula tiene un significado diferente al de su letra minuscula equivalente.

Inicio de una sesion de trabajo. Para comenzar una sesion de trabajo se ha de entrar en una cuentaabierta en el sistema unix. Para ello se debe responder dos preguntas sobre el nombre de la cuenta (login)y su contrasena o clave de acceso (password). Tras la escritura de nombre y contrasena se ha de pulsarla tecla ENTER. No sorprenda el comprobar que al escribir la contrasena no produce ninguna accion de ecoen pantalla, es decir, da la impresion de que no se ha escrito nada.

Si no ha habido error al escribir el nombre de cuenta y la contrasena, el sistema presenta porpantalla una serie de anuncios e informaciones y, finalmente, presenta el nombre de uno de loscomputadores (hendrix01:-/ o hendrix02:-/) lo cual sirve de advertencia al usuario de que elcluster hendrix-ssh esta dispuesto a recibir ordenes unix.

26

login as: a334412password:

<Aparecen escritos una serie de mensajes por pantalla>

hendrix01:-/

Orden exit para finalizar la sesion de trabajo y salir del sistema (cierra las ventanas y conexionesremotas establecidas):

hendrix01:-/ exit

Orden ls (list) para listar todos los archivos de un directorio:

hendrix01:-/ ls

Orden ll (large list) para obtener un listado de todos los archivos de un directorio coninformacion detallada:

hendrix01:-/ ll

Orden cp (copy) para copiar ficheros:

hendrix02:-/ cp ficheroOriginal nombreFicheroCopiahendrix02:-/ cp ficheroOriginal directorioDestino

Orden rm (remove) para borrar ficheros:

hendrix02:-/ rm inutil.txthendrix02:-/ rm cap1/pr*.cc

Orden mv (move) para trasladar ficheros o cambiar su nombre:

hendrix01:-/ mv viejoNombreFichero nuevoNombreFicherohendrix01:-/ mv ficheroAMover directorioDestino

Orden mkdir (make directory) para crear un nuevo directorio:

hendrix02:-/ mkdir nombreNuevoDirectorio

Orden rmdir (remove directory) para eliminar directorios (exige que el directorio este vacıo):

hendrix01:-/ rmdir nombreDirectorioAEliminar

27

Orden cd (change of directory) para cambiar de directorio:

hendrix02:-/ cd /export/home/practicas/Practicashendrix02:-/ cd .. <<-- cambia al directorio padre (un nivel superior)hendrix02:-/ cd $HOME/programacion2/practica1hendrix02:-/ cd <<-- cambia al directorio HOME de la cuenta

Orden pwd (print working directory) para visualizar el camino desde el directorio raiz de lamaquina al directorio actual:

hendrix01:-/ pwd

Orden man de llamada al manual de ayuda (explica la utilidad y parametros de las ordenes unix):

hendrix02:-/ man ls <<-- explica el modo de usar la orden lshendrix02:-/ man rm <<-- explica el modo de usar la orden rm

Orden cat para mostrar por pantalla como un listado continuo el contenido de un fichero, visto comotexto:

hendrix01:-/ cat nombreFichero

Orden more para mostrar por pantalla de forma controlable el contenido de un fichero, visto como texto.Tras cada pantallazo de texto admite tres posibles ordenes: mostrar una nueva lınea (tecla ENTER), mostraruna nueva pagina (tecla ESPACIO) y finalizar la orden (tecla Q).

hendrix02:-/ more nombreFichero

Orden gedit para editar un fichero de texto (con el editor de textos gedit):

hendrix02:-/ gedit nombreFicherohendrix02:-/ gedit nombreFichero &hendrix02:-/ gedit &

La diferencia entre las ordenes anteriores es que la dos ultimas mantienen activa la ventana inicial deordenes unix.

Orden g++ con opcion -c para compilar el programa fuente p.cc escrito en C++ :

hendrix01:-/ cd $HOME/programacion2/practica1hendrix01:-/ g++ p.cc -c

Orden g++ con opcion -o para construir el programa ejecutable p a partir del programa objeto p.oresultante de la compilacion anterior:

hendrix02:-/ g++ p.o -o p

28

Orden para invocar la ejecucion del programa p:

hendrix02:-/ ./p

Orden para invocar la ejecucion del programa p con K argumentos en la lınea de ordenes:

hendrix01:-/ ./p arg1 arg2 ... argK

Orden passwd (password) para cambiar la contrasena o clave de acceso a la cuenta:

hendrix02:-/ passwd

Orden wc para contar los caracteres, palabras y lıneas de un fichero de texto:

hendrix02:-/ wc nombreFichero

Orden date para consultar el dıa, fecha, hora (con minutos y segundos) y ano actual:

hendrix01:-/ dateThu Oct 18 10:18:52 MET 2001

Orden whoami para visualizar el nombre de usuario de la cuenta de trabajo:

hendrix02:-/ whoami

Orden clear para borrar la pantalla:

hendrix01:-/ clear

Abortar una orden. Si se desea finalizar una orden unix en ejecucion basta con teclear Control+C.Esta posibilidad suele ser util cuando se esta ejecutando un programa y este no termina y se desea forzar suterminacion.

Para recordar y reproducir la ultima orden unix basta teclear ESCAPE+K.

29

Capıtulo 2

Practica 2: Definicion de estructuras dedatos genericos y desarrollo de programassin bucles (diseno recursivo sin inmersion)

2.1. Objetivos de esta practica

Esta practica persigue un doble objetivo:

Diseno de estructuras de datos genericos. Aprender a disenar estructuras de datos genericos juntocon una coleccion de funciones basicas para trabajar con ellas.

Lo aprendido se aplicara al diseno de pilas de datos genericos.

Diseno de algoritmos sin bucles. Programar varios algoritmos sin bucles, aplicando un disenorecursivo cuando sea necesario, aunque nunca un diseno recursivo por inmersion. Para disenar estosalgoritmos sin bucles debera aplicarse la metodologıa de diseno recursivo estudiada en la asignatura.

Se programaran de este modo varias funciones que trabajan con numeros naturales, ası como variasfunciones para gestionar la informacion de pilas de datos genericos.

2.2. Tecnologıa y herramientas

2.2.1. Diseno de estructuras de datos genericos

Definicion de un tipo de dato para representar una pila de datos genericos

Asumamos que hemos de desarrollar diversos programas que trabajan con pilas de datos de tiposdiversos: pilas de datos de tipo int, pilas de datos de tipo char, pilas de datos de tipo double, pilasde datos de tipo Nif, pilas de datos de tipo Tiempo, pilas de datos de tipo Ciudadano, etc.

Conviene evitar la definicion de un tipo de dato diferente para representar cada una de las pilas de datosanteriores. Para ello basta proceder a la definicion de un tipo de dato denominado Pila que almacene datosde un tipo generico al que se va a denominar T. Por lo tanto, la definicion del tipo Pila sera generica yaque se hara en funcion del tipo de dato generico T, tal como se esquematiza a continuacion.

30

/∗∗ Un dato definido a partir del tipo Pila representa una pila de datos del tipo generico T.∗ Los datos de la pila seran gestionados segun una polıtica LIFO, es decir , el ultimo en∗ llegar a la pila (en ser apilado) sera el primero en salir de ella (en ser desapilado ).∗/

template <typename T>struct Pila {

private :// Los campos definidos en estas seccion se ocultan a cualquier funcion ,// excepto a las definidas como funciones amigas (’ friend ’). . .

public :// Estas son las unicas funciones que tienen visibilidad sobre los datos ocultos// definidos como ’ private ’ de cualquier registro de tipo Pilafriend void vaciar<T> (Pila<T>& P);friend void apilar <T> (Pila<T>& P, const T nuevo);friend void desapilar <T> (Pila<T>& P);friend T cima<T> (const Pila<T>& P);friend bool estaVacia<T> (const Pila<T>& P);friend bool estaLlena<T> (const Pila<T>& P);

};

Al desarrollar programas que trabajen con datos del tipo Pila, habra que determinar el tipo de dato(int, char, double, Nif, Tiempo, Ciudadano, etc.) que se corresponde con el tipo generico T. Paraello la definicion de un tipo de dato que represente una pila de datos se hara precisando, tras el nombredel tipo generico Pila, el del nombre del tipo de los datos a almacenar en la pila, escrito entre angulos.Ejemplos:

Pila <int> P1; // P1 es una pila de datos de tipo int

Pila <char> P2; // P2 es una pila de datos de tipo char

Pila <double> P3; // P3 es una pila de datos de tipo double

Pila <Nif> P4; // P4 es una pila de datos de tipo Nif

Pila <Tiempo> P5; // P5 es una pila de datos de tipo Tiempo

Pila <Ciudadano> P6; // P6 es una pila de datos de tipo Ciudadano

Pila <T> P7; // P7 es una pila de datos de tipo T

Etc., etc.

Coleccion de funciones basicas para trabajar con cualquier pila de datos

Para trabajar con una pila, P, definida a partir del tipo generico Pila, conviene contar con una reducidacoleccion de funciones basicas que permitan definir el contenido inicial de una pila (vaciar(P)), anadiry eliminar datos de ella (apilar(P,nuevo) y desapilar(P)) y consultar su estado (cima(P),estaVacia(P) y estaLlena(P)). Estas funciones seran las unicas con derecho acceder a los camposque definen la representacion interna de una pila. Sus comportamientos se resumen a continuacion:

vaciar(P): tras ser ejecutada, la pila P no almacena ningun dato. Como el valor o contenido inicialde una pila P esta indefinido, esta funcion permite definir un contenido concreto para comenzar atrabajar con la pila P.

31

apilar(P,nuevo): modifica la pila P anadiendole el dato nuevo, que se situa en su cima, comosu dato mas reciente.

desapilar(P): modifica la pila P, retirando de la pila P su dato cima, es decir, su dato masreciente.

cima(P): devuelve un valor igual al de su dato cima, es decir, al de su dato mas reciente; no alterael contenido de la pila P.

estaVacia(P): devuelve un valor cierto si y solo si la pila P no contiene en ese momento ningundato; no altera el contenido de la pila P.

estaLlena(P): devuelve un valor cierto si y solo si la pila P esta llena por almacenar un numerode datos igual a su capacidad maxima; no altera el contenido de la pila P.

2.2.2. Parametros de una funcion cuyo valor puede estar definido por defecto

Los parametros de una funcion pueden tomar valores definidos por defecto en la propia lista deparametros de la funcion. Ası, por ejemplo, en la funcion numCifras(. . .) se asigna por defecto unvalor 10 a su segundo argumento. Los parametros con valores definidos por defecto pueden ser uno o masy han de situarse, obligatoriamente, al final de la lista de parametros de la funcion.

/∗∗ Devuelve el numero de cifras del numero natural <n> cuando se expresa en base <b>,∗ siendo <b> un entero comprendido entre 2 y 10∗/

int numCifras (const int n, const int b = 10);

Cualquier invocacion de la funcion anterior requiere definir obligatoriamente el valor de su primerparametro, mientras que la definicion del valor del segundo es opcional. Si se omite este valor, el segundoparametro toma el valor por defecto, es decir, el valor 10. Tras cada una de las invocaciones que se presentana continuacion, se explica el valor que toman los parametros n y b de la funcion numCifras(n,b).

numCifras(9708725, 2); // n = 9708725 y b = 2numCifras(9708725); // n = 9708725 y b = 10numCifras(9708725, 6); // n = 9708725 y b = 6numCifras(9708725, 10); // n = 9708725 y b = 10

2.3. Trabajo a desarrollar en esta practica

2.3.1. Primera tarea: diseno del tipo generico Pila

Se ha de crear un nuevo directorio, programacion2/genericas, que alojara diversos ficheros enlos que se definan de estructuras de datos genericos y el codigo de funciones genericas para trabajar condichas estructuras.

En esta carpeta se situara el fichero pila.h en el que se va a definir el tipo generico Pila junto conuna coleccion de seis funciones genericas basicas que facilitan la gestion de cualquier pila de datos definidaa partir del tipo Pila.

32

El esquema de este fichero, que se presenta a continuacion, se encuentra disponible en la carpetapractica2, accesible a traves del enlace Material docente comun de la web de Programacion 2.

Cada alumno debe completar la definicion interna del tipo de dato generico Pila y disenar el codigode cada una de sus seis funciones genericas basicas, sustituyendo los puntos suspensivos por el codigo C++que corresponda. El diseno del tipo Pila debe estar orientado a optimizar la eficiencia de las funcionesque permiten anadir y retirar datos de una pila, apilar(P,nuevo) y desapilar(P).

/∗∗ Fichero pila .h que contiene la definicion del tipo generico Pila , que representa una pila∗ de datos genericos , y un conjunto de funciones basicas para trabajar con pilas genericas∗/

#ifndef PILA GENERICA H

#define PILA GENERICA H

/∗∗ Capacidad maxima de almacenamiento de datos en las pilas que puedan definirse∗ a partir del tipo generico Pila∗/

const int DIM = 120; // Redefinir su valor en caso necesario

/∗∗ Predeclaracion del tipo Pila∗/

template<typename T>struct Pila ;

/∗∗ Notacion empleada en la especificacion de funciones :∗ P = [] La pila P esta vacıa , es decir , almacena 0 datos∗ P = [d 1, d 2, ..., d K] la pila P almacena K datos. El mas antiguo es el dato d 1,∗ el segundo mas antiguo el dato d 2, etc ., etc . y el mas reciente es el dato d K∗/

/∗∗ Pre: −−−∗ Post : P = []∗/

template <typename T>void vaciar ( Pila <T>& P) {

. . . escriba aquı el codigo de esta funcion . . .}

/∗∗ Pre: P = [d 1, d 2, ..., d K] AND K >= 0 AND K < DIM∗ Post : P = [d 1, d 2, ..., d K, nuevo]∗/

template <typename T>void apilar ( Pila <T>& P, const T nuevo) {

. . . escriba aquı el codigo de esta funcion . . .}

33

/∗∗ Pre: P = [d 1, d 2, ..., d (K−1),d K] AND K > 0∗ Post : P = [d 1, d 2, ..., d (K−1)]∗/

template <typename T>void desapilar ( Pila<T>& P) {

. . . escriba aquı el codigo de esta funcion . . .}

/∗∗ Pre: P = [d 1, d 2, ..., d (K−1),d K] AND K > 0∗ Post : cima(P) = d K∗/

template <typename T>T cima (const Pila<T>& P) {

. . . escriba aquı el codigo de esta funcion . . .}

/∗∗ Pre: −−−∗ Post : estaVacia (P) = (P = [])∗/

template <typename T>bool estaVacia (const Pila<T>& P) {

. . . escriba aquı el codigo de esta funcion . . .}

/∗∗ Pre: P = [d 1, d 2, ..., d K]∗ Post : estaLlena (P) = (K = DIM])∗/

template <typename T>bool estaLlena (const Pila<T>& P) {

. . . escriba aquı el codigo de esta funcion . . .}

/∗∗ Un dato definido a partir del tipo generico Pila representa una pila de datos de tipo T.∗ Los datos son gestionados segun una polıtica FIFO, es decir , el ultimo en entrar (en ser∗ apilado) sera el primero en salir (en ser desapilado ).∗/

template <typename T>struct Pila {

private :. . . defina aquı la estructura interna del tipo Pila . . .

public :// Estas son las unicas funciones que van a tener visibilidad sobre los datos ocultos// definidos como ’ private ’ de cualquier registro de tipo Pilafriend void vaciar<T> (Pila<T>& P);friend void apilar <T> (Pila<T>& P, const T nuevo);friend void desapilar <T> (Pila<T>& P);friend T cima<T> (const Pila<T>& P);friend bool estaVacia<T> (const Pila<T>& P);friend bool estaLlena<T> (const Pila<T>& P);

};

#endif

34

Conviene aclarar que el fichero pila.h no define ningun modulo de biblioteca. Se trata simplementede un fichero a incluir, mediante la correspondiente clausula #include "pila.h", en el codigo decualquier otro modulo que necesite definir una o mas pilas de datos del tipo que sea.

2.3.2. Segunda tarea: diseno sin bucles de funciones que trabajan con enteros

Se debe hacer un diseno de un modulo de biblioteca denominado calculos que incluya en sufichero de especificacion, calculos.h, las funciones que se especifican de un modo no formal acontinuacion. Los ficheros de interfaz e implementacion del modulo se ubicaran en el directorio (carpeta)programacion2/practica2.

Todas las funciones del modulo tienen un parametro con un valor definido por defecto. Esta circunstanciano debe condicionar sus disenos.

/∗∗ Fichero de interfaz calculos .h del modulo de biblioteca calculos∗/

#ifndef CALCULOS H

#define CALCULOS H

/∗∗ Devuelve el numero de cifras del numero natural <n> cuando se expresa en base <b>,∗ siendo <b> un entero comprendido entre 2 y 10∗/

int numCifras (const int n, const int b = 10);

/∗∗ Devuelve el valor de la cifra del numero natural <n> situada en la posicion <i>,∗ empezando a contar por su cifra menos significativa , cuando <n> se expresa en∗ base <b>, siendo <b> un entero comprendido entre 2 y 10∗/

int cifra (const int n, const int i , const int b = 10);

/∗∗ Devuelve el valor de la mayor de las cifras del numero natural <n> cuando∗ se expresa en base <b>, siendo <b> un entero comprendido entre 2 y 10∗/int cifraMayor (const int n, const int b = 10);

/∗∗ Devuelve el valor de la cifra mas significativa del numero natural <n> cuando∗ se expresa en base <b>, siendo <b> un entero comprendido entre 2 y 10∗/

int cifraMasSignificativa (const int n, const int b = 10);

/∗∗ Devuelve la suma de las cifras del numero natural <n> cuando <n> se∗ expresa en base <b>, siendo <b> un entero comprendido entre 2 y 10∗/

int sumaCifras (const int n, const int b = 10);

#endif

35

El diseno del modulo de biblioteca calculos comprende las siguiente subtareas:

1. Sustituir en el fichero de interfaz calculos.h cada una de las especificaciones no formales por unaespecificacion formal, escribiendo la pre y la postcondicion de cada una de ellas como predicadosmatematicos.

2. Escribir el fichero de implementacion calculos.cc del modulo calculos de forma que no seprograme ningun bucle en el codigo de ninguna de las funciones. En ningun caso se aplicaran tecnicasde inmersion al proceder a aplicar un diseno recursivo ni se desarrollaran funciones auxiliares, ya quenada de ello es necesario.

3. Completar el diseno de un programa, pruebas01.cc, que permita hacer cuantas pruebasde las funciones definidas en el modulo calculos sean necesarias para confiar en su buencomportamiento.

El fichero calculos.h de especificacion del modulo calculos y el fichero pruebas01.cccon un programa de pruebas desarrollado parcialmente (cada alumno debiera completarlo) se encuentrandisponibles en la carpeta practica2, accesible a traves del enlace Material docente comun de la web deProgramacion 2.

¿Como compilar y ejecutar el programa anterior?

Tras situarnos en el directorio programacion2/practica2, compilaremos en primer lugar el fichero deimplementacion del modulo de biblioteca calculos, calculos.cc. Como resultado de la compilacionse genera el fichero objeto calculos.o

hendrix02:-/ cd $HOME/programacion2/practica2hendrix02:-/ g++ calculos.cc -c

A continuacion se compila el modulo principal del programa, el fichero pruebas1.cc. En la orden sedebe incluir el nombre del fichero con el codigo objeto del modulo calculos, es decir, calculos.o.

hendrix02:-/ g++ pruebas01.cc calculos.o -o pruebas01

Como resultado se obtiene el fichero compilado pruebas01 que puede ser ejecutado cuantas veces sedesee.

hendrix02:-/ ./pruebas01... mostrara los resultados de ejecutar el pograma anterior ...

36

2.3.3. Tercera tarea: diseno recursivo de funciones de mayor nivel para trabajar con pilasde datos genericos

Se han de disenar las funciones genericas numDatos(P), mostrar(P,anchura),mostrarInvertida(P,anchura), eliminarFondo(P), eliminar(P,i) einsertarFondo(P,nuevo), que se editaran en un fichero de nombre funcionesPilas.h.

Estas funciones trabajan con pilas de datos definidas a partir del tipo generico Pila y resuelvenproblemas de un nivel de abstraccion superior al de las funciones basicas dedicadas a gestionar internamentelas pilas, desarrolladas en un apartado anterior y contenidas en el fichero pilas.h.

En el diseno de estas seis nuevas funciones se ha de tener en cuenta que el trabajo con una pilaha de ser independiente de la representacion de esta y debe realizarse exclusivamente invocando lasfunciones definidas en el fichero pilas.h, es decir, las funciones vaciar(P), apilar(P,nuevo),desapilar(P), cima(P), estaVacia(P) y estaLlena(P).

Por razones didacticas, el diseno de estas funciones debe estar libre de bucles y no se han de aplicartecnicas de diseno recursivo por inmersion, por no resultar necesarias. Por razones didacticas tambien, nose debe hacer uso de estructuras de datos auxiliares en las que almacenar temporalmente el contenido delas pilas de datos con las que se trabaje, es decir, no se pueden definir otras pilas, vectores, ficheros, etc.auxiliares.

El fichero funcionesPilas.h se ubicara en el carpeta programacion2/practica2. Unesquema de ese fichero se encuentra disponible en la carpeta practica2, accesible a traves del enlaceMaterial docente comun de la web de Programacion 2.

Cada alumno debe completar el diseno de cada una de las funciones genericas sustituyendo los puntossuspensivos por el codigo C++ que corresponda.

/∗∗ Fichero funcionesPilas .h que contiene un conjunto de funciones para∗ trabajar con pilas genericas de tipo Pila <T> que almacenan una∗ coleccion de datos de tipo <T> gestionados segun una polıtica LIFO∗/

#ifndef FUNCIONES GENERICAS H#define FUNCIONES GENERICAS H

#include <iostream>#include <iomanip>

// Tipo generico Pila y operaciones basicas para el trabajo con pilas de datos#include ” ../ genericas / pila .h”

using namespace std;

/∗∗ Notacion empleada en las especificaciones :∗ P = [] La pila P esta vacıa , es decir , almacena 0 datos∗ P = [D 1, D 2, ..., D K] la pila P almacena K datos. El mas antiguo∗ es el dato D 1, el segundo mas antiguo el dato D 2, etc ., etc .,∗ y el mas reciente es el dato D K∗/

37

/∗∗ Pre: P = [D 1, D 2, ..., D K] AND K >= 0∗ Post : P = [D 1, D 2, ..., D K] AND numDatos(P) = K∗/

template <typename T>int numDatos (Pila <T>& P) {

. . .}

/∗∗ Pre: P = [D 1, D 2, ..., D K] AND K >= 0∗ Post : P = [D 2, ..., D K]∗/

template <typename T>void eliminarFondo ( Pila <T>& P) {

. . .}

/∗∗ Pre: P = [D K, ..., D (i+1), D i, D (i−1), ..., D 1] AND∗ K >= 1 AND i >= 1 AND i <= K∗ Post : P = [D K, ..., D (i+1), D (i−1), ..., D 1]∗/

template <typename T>void eliminar ( Pila <T>& P, const int i ) {

. . .}

/∗∗ Pre: P = [D 1, D 2, ..., D K AND K >= 0∗ Post : P = [nuevo, D 1, D 2, ..., D K]∗/

template <typename T>void insertarEnFondo ( Pila <T>& P, const T nuevo) {

. . .}

/∗∗ Pre: P = [D 1, D 2, ..., D K] y anchura >= 1∗ Post : P = [D 1, D 2, ..., D K] y presenta por pantalla un listado de∗ los datos apilados en [P] comenzando por la cima, D K, y acabando∗ por el del fondo de la pila , D 1. Cada dato lo escribe en una lınea ,∗ empleando anchura caracteres y alineado a la derecha. Cada dato es∗ precedido por el caracter ’|’ y es seguido por los caracteres ’ ’ y∗ ’|’, tal como se ilustra a continuacion . Tras el ultimo dato se∗ presenta una linea de la forma ”+−−...−−+”, seguida por una lınea∗ en blanco:∗∗ | D K |∗ | ... |∗ | D 2 |∗ | D 1 |∗ +−−−−−+∗/

template <typename T>void mostrar ( Pila <T>& P, const int anchura = 3) {

. . .}

38

/∗∗ Pre: P = [D 1, D 2, ..., D K] y anchura >= 1∗ Post : P = [D 1, D 2, ..., D K] y presenta por pantalla un listado de los∗ datos apilados en [P] comenzando por el del fondo de la pila , D 1,∗ y acabando por el de la cima de la pila , D K. Cada dato lo escribe∗ en una lınea , empleando anchura caracteres y alineado a la derecha.∗ Cada dato es precedido por el caracter ’|’ y es seguido por los∗ caracteres ’ ’ y ’|’, tal como se ilustra a continuacion . Antes∗ del primer dato se presenta una linea de la forma ”+−−...−−+”:∗∗ +−−−−−+∗ | D 1 |∗ | D 2 |∗ | ... |∗ | D K |∗/

template <typename T>void mostrarInvertida ( Pila <T>& P, const int anchura = 3) {

. . .}

#endif

En el desarrollo del codigo de las funciones anteriores puede ser necesario invocar alguna de lasfunciones genericas basicas vaciar(P), estaVacia(P), estaLlena(P), apilar(P,nuevo),desapilar(P) y cima(P).

En principio, la invocacion de cada una de ellas debiera hacerse tal como se muestra a continuacion,incluyendo tras el nombre de la funcion, la lista de tipos que corresponden a sus tipos genericos, escritaentre angulos:

vaciar<T>(P)

estaVacia<T>(P)

estaLlena<T>(P)

apilar<T>(P,nuevo)

desapilar<T>(P)

cima<T>(P)

No obstante, en todas las invocaciones anteriores el compilador es capaz de deducir el tipo de dato quese corresponde con el tipo generico T, a partir del analisis de los tipos de los argumentos de cada uno de lasinvocaciones. Por esta razon se puede omitir la lista de tipos al invocarse la funcion.

En resumen, la forma mas abreviada de las invocaciones anteriores es:

vaciar(P)

estaVacia(P)

estaLlena(P)

apilar(P,nuevo)

39

desapilar(P)

cima(P)

El fichero anterior se incluira en el codigo de cualquier modulo que necesite hacer uso de alguna de lasfunciones que en el se definen, mediante la correspondiente clausula #include "funcionesPila.h".

Desarrollo de programas de pruebas de las funciones anteriores

Cada alumno debe ejecutar algun programa para para probar el correcto funcionamiento de las diferentesfunciones definidas en los dos apartados anteriores. Estos programas se ubicaran en el directorio (carpeta)programacion2/practica2.

Para ilustrar una forma sencilla de disenar programas de prueba, se ha dispuesto el programa de pruebaspruebas02.cc en la web de la asignatura (en la carpeta practica2 accesible a traves del enlace Materialdocente comun).

¿Como compilar y ejecutar un programa de pruebas?

El programa de pruebas que se acaba de mencionar consta unicamente de un modulo principal cuyocodigo se encuentra en el fichero pruebas02.cc. Dentro de este codigo se han programado dos clausulas#include para la insercion en el del codigo de los ficheros pila.h y funcionesPilas.h.

Tras situarnos en el directorio programacion2/practica2, compilaremos el modulo principal delprograma, el fichero pruebas02.cc.

hendrix02:-/ cd $HOME/programacion2/practica2hendrix02:-/ g++ pruebas02.cc -o pruebas02

Como resultado se obtiene el fichero pruebas02 que puede ser ejecutado cuantas veces se desee.

hendrix02:-/ ./pruebas02... mostrara los resultados de ejecutar el pograma anterior ...

2.3.4. Resultados del trabajo desarrollado en las dos primeras practicas

Como resultado de las dos primeras practicas, cada alumno dispondra en su cuenta en el servidorhendrix-ssh de un directorio (carpeta) denominado programacion2 dentro del cual se podran encontrarlos directorios (carpetas) y ficheros que se detallan a continuacion. Estos ficheros debieran estar listos antesdel 20 de marzo, fecha del comienzo de las sesiones correspondientes a la siguiente practica.

1. Directorio (carpeta) programacion2/practica1 con los siguientes ficheros:

Fichero tiempoReaccion.cc con el codigo C++ del primer programa de la practica 1a.

Fichero generarTabla01.cc con el codigo C++ del segundo programa de la practica 1a.

Fichero generarTabla02.cc con el codigo C++ del tercer programa de la practica 1a.

Fichero medirCoste.cc con el codigo C++ del cuarto programa de la practica 1a.

40

2. Directorio (carpeta) programacion2/practica2 con los siguientes ficheros:

Ficheros de interfaz y de implementacion, calculos.h y calculos.cc, con el codigo C++ delmodulo calculos de la practica 2a.

Fichero funcionesPilas.h de la practica 2a con el codigo C++ de una coleccion de funcionesgenericas, programadas sin bucles, sin aplicar tecnicas de inmersion y sin funciones auxiliares,que ejecutan operaciones con pilas de datos, definidas a partir del tipo generico Pila, de un nivelsuperior al de las funciones genericas basicas del fichero pila.h.

Ficheros con los programas de prueba (pruebas01.cc, pruebas02.cc, etc.) que se hayan puestoa punto para realizar pruebas de los desarrollos anteriores.

3. Directorio (carpeta) programacion2/genericas con los siguientes ficheros:

Fichero pila.h con el codigo C++ desarrollado en la practica 2a en el que se representa el tipogenerico Pila junto con una coleccion de seis funciones genericas basicas para trabajar con pilasde datos definidas a partir del tipo Pila.

41

Capıtulo 3

Practica 3: Desarrollo de programas C++sin bucles (recursividad sin o coninmersion)

3.1. Objetivos de esta practica

Esta practica tiene como principal objetivo constatar que es posible desarrollar programas de cualquiertamano cuyo codigo no presente ningun bucle.

Para ello se propone el desarrollo y la puesta a punto de un programa sin bucles escrito en C++, haciendoun diseno recursivo de determinadas funciones, cuando sea necesario. En tales casos debera aplicarse lametodologıa de diseno recursivo estudiada en la asignatura, y se tendra en cuenta que en algunos de losdisenos de funciones sera necesario aplicar tecnicas de inmersion o generalizacion.

Por otra parte se pretende continuar con el diseno de estructuras de datos genericas. En este casomediante el diseno de colas de datos genericos para su posterior uso en el desarrollo del programamencionado en el parrafo anterior.

Un objetivo adicional de esta practica es aprender a utilizar la herramienta make que facilita la puesta apunta y el mantenimiento de proyectos de programacion.

En el ultimo apartado de este capıtulo se hace una presentacion muy resumida de la herramienta make.Informacion adicional se puede lograr facilmente buscandola en internet.

3.1.1. Calendario de esta practica

Cada alumno debe realizar el trabajo asociado a esta practica a lo largo de unas seis semanas. Dossesiones de practicas, la tercera (ultimos dıas de marzo y primeros de abril tras la Semana Santa) y la cuarta(en el mes de abril), estan dedicadas a esta practica.

Se plantea esta tercera practica para que comience a ser desarrollada en marzo de 2018, inmediatamentedespues de la segunda sesion de practicas. La tercera sesion de practicas debe servir para concluir el trabajopropuesto como primera fase de la practica mientras que la cuarta sesion (programada en el mes de abril)debe servir para concluir la totalidad el trabajo propuesto en la practica.

42

3.2. Trabajo a realizar

Al final de la practica cada alumno debe haber desarrollado y puesto a punto un programa, escrito enC++, cuyo comportamiento se describe a continuacion.

En un apartado posterior se daran las pautas sobre la arquitectura del programa y el desarrollo de sucodigo.

3.2.1. Comportamiento de un programa gestor de una cola de personas

El programa a disenar debe gestionar una cola de personas, inicialmente sin ninguna persona,permitiendo anadir y eliminar personas de la cola e informar sobre el estado de la cola (numero de personasen la cola e informacion de dichas personas).

El programa se comporta como un interprete interactivo de ordenes escritas por el operador. Informainicialmente del repertorio de las ordenes que es capaz de ejecutar. A continuacion pide al operador queescriba una orden y procede a ejecutarla. Itera este comportamiento hasta que el operador escribe la ordenfin.

Un ejemplo ilustrativo del tipo de dialogo que el programa ha de mantener con el operador se presentaa continuacion.

ORDENES DISPONIBLES===================fininsertarretirarcuantaslistarayuda

Orden: cuantasHay 0 personas en la cola

Orden: listarLa cola esta vacia

Orden: insertarNombre y apellido: Luis LesmesFecha de nacimiento (aaaammdd): 19981209Numero de NIF: : 75907755Luis Lesmes se ha incorporado a la cola

Orden: cuantasHay 1 persona en la cola

Orden: listar1. 75907755-G 09/12/1998 Luis Lesmes

Orden: insertarNombre y apellido: Andrea BuenoFecha de nacimiento (aaaammdd): 19990120Numero de NIF: : 76509223Andrea Bueno se ha incorporado a la cola

43

Orden: cuantasHay 2 personas en la cola

Orden: listar1. 75907755-G 09/12/1998 Luis Lesmes2. 76509223-E 20/01/1999 Andrea Bueno

Orden: retirarLuis Lesmes ha abandonado la cola

Orden: cuantasHay 1 persona en la cola

Orden: listar1. 76509223-E 20/01/1999 Andrea Bueno

Orden: hayudaLa orden HAYUDA es desconocida

Orden: ayuda

ORDENES DISPONIBLES===================fininsertarretirarcuantaslistarayuda

Orden: ...

Orden: finFin de la ejecucion del programa

Cada orden se limita a un codigo que identifica la orden (fin, insertar, retirar, cuantas,listar y ayuda). Este codigo puede escribirse con letras mayusculas, minusculas o con cualquiercombinacion de ellas. Por ejemplo, las siguientes ordenes son equivalentes:

Orden: listar

Orden: LISTAR

Orden: Listar

Orden: LiStAr

El efecto de cada una de las seis ordenes que debe ser capaz de ejecutar el programa se explica acontinuacion.

Orden fin.El programa se limita a concluir su ejecucion informando de ello al operador mediante el mensajeque se muestra a continuacion.

44

Orden: finFin de la ejecucion del programa

Orden insertar.Si la cola no esta llena, entonces anade una nueva persona a la cola cuyos datos son definidospreviamente, de forma interactiva, por el operador. Tras completar la ejecucion de la orden, presentaun mensaje en el que informa de ello.

Orden: insertarNombre y apellido: Luis LesmesFecha de nacimiento (aaaammdd): 19981209Numero de NIF: : 75907755Luis Lesmes se ha incorporado a la cola

Orden: ...

Si la cola esta llena no lleva a cabo ninguna de las acciones anteriores y se limita a informar de lasituacion.

Orden: insertarLa cola esta llena

Orden: ...

Orden retirar.Si la cola no esta vacıa, entonces elimina de la cola a la persona mas antigua en ella. Tras completarla ejecucion de la orden, presenta un mensaje en el que informa de ello.

Orden: retirarLuis Lesmes ha abandonado la cola

Orden: ...

Si la cola esta vacıa no lleva a cabo ninguna de las acciones anteriores y se limita a informar de lasituacion.

Orden: insertarLa cola esta vacia

Orden: ...

Orden cuantas.Presenta un mensaje en el que informa del numero de personas almacenadas en la cola.

Orden: cuantasHay 307 personas en la cola

Orden: ...

Orden listar.Presenta un listado con los datos personales (NIF, fecha de nacimiento y nombre) de las personasalmacenadas en la cola. Cada persona se presenta en una lınea. El listado se presenta numerado,comenzando con la persona mas antigua en la cola y concluyendo con la mas recientemente llegadaa ella.

45

Orden: listar1. 75907755-G 09/12/1998 Luis Lesmes2. 76509223-E 20/01/1999 Andrea Bueno

. . .306. 69100987-V 31/05/1997 Eloy Granados307. 23644747-B 28/06/1995 Matilde Navarro

Orden: ...

Si la cola esta vacıa, el programa se limita a informar de la situacion.

Orden: listarLa cola esta vacia

Orden: ...

Orden ayuda.El programa presenta de nuevo por pantalla el listado de ordenes que es capaz de ejecutar.

Orden: ayuda

ORDENES DISPONIBLES===================fininsertarretirarcuantaslistarayuda

Orden: ...

3.2.2. Desarrollo del programa

El desarrollo de este programa se puede realizar con la ayuda de cualquier entorno de desarrollode programas escritos en C++ (Codelite u otro). No obstante lo anterior, la version final del programaha de estar instalada en la cuenta que cada alumno dspone en el servidor hendrix y debe presentar,obligatoriamente, la arquitectura que se detalla a continuacion. El programa ası dispuesto debe estar listopara ser ejecutado, sin ayuda de ningun entorno de desarrollo, tanto en las maquinas del cluster hendrix-sshcomo en cualquiera de los pc de los laboratorios de practicas.

Adicionalmente, se recuerda que el codigo C++ de todos y cada uno de los componentes del programadebera estar programado sin bucles.

La arquitectura del programa comprende los siguientes componentes:

Modulo de biblioteca fecha, ubicado en el directorio programacion2/tipos. Su fichero de interfazes el siguiente (se puede descargar desde la web de la asignatura), a falta unicamente de disenar laestructura interna de los datos de tipo Fecha. El fichero de implementacion del modulo debe serdesarrollado por cada alumno.

46

/∗∗ Fichero de interfaz fecha .h del modulo fecha∗/

#ifndef FECHA H#define FECHA H

/∗∗ Un dato de tipo Fecha permite representar cualquier fecha∗ del calendario∗/

struct Fecha {private :

. . . // Definir aquı la estructura interna del tipo Fechapublic :

// Funciones con acceso a la estructura interna anteriorfriend Fecha definirFecha ( int d, int m, int a );friend Fecha definirFecha ( int fecha );friend int dia (Fecha f );friend int mes (Fecha f );friend int anyo (Fecha f );

};

/∗∗ Pre: d >= 1 y d <= 31, m >= 1 y m <= 12, a > 0∗ Post : Devuelve la fecha definida por d/m/a∗/

Fecha definirFecha ( int d, int m, int a );

/∗∗ Pre: El valor de fecha tiene ocho cifras cuando se escribe en∗ base 10: aaaammdd, donde aaaa define el ano, mm el numero∗ del mes y dd el dıa del mes∗ Post : Devuelve la fecha definida por dia /mes/ano∗/

Fecha definirFecha ( int fecha );

/∗∗ Pre: f es una fecha valida del calendario∗ Post : devuelve el numero correspondiente al dıa de la fecha [ f ]∗/

int dia (Fecha f );

/∗∗ Pre: f es una fecha valida del calendario∗ Post : devuelve el numero correspondiente al mes de la fecha [ f ]∗/

int mes (Fecha f );

/∗∗ Pre: f es una fecha valida del calendario∗ Post : devuelve el numero correspondiente al ano de la fecha [ f ]∗/

int anyo (Fecha f ) ;

Modulo de biblioteca nif ubicado en el directorio programacion2/tipos. Su fichero de interfazes el siguiente (se puede descargar desde la web de la asignatura), a falta unicamente de disenarla estructura interna de los datos de tipo Nif. El fichero de implementacion del modulo debe ser

47

desarrollado por cada alumno.

/∗∗ Fichero de interfaz nif .h del modulo nif∗/

#ifndef NIF H#define NIF H

/∗∗ Un dato de tipo Nif que representa la informacion del NIF∗ (Numero de Identificacion Fiscal ) de un ciudadano∗/

struct Nif {private :

. . . // Definir aquı la estructura interna del tipo Nifpublic :

// Funciones con acceso a la estructura interna anteriorfriend Nif crearNif (const int numero);friend int numero (const Nif unNif);friend char letra (const Nif unNif);

};

/∗∗ Pre: numero > 0∗ Post : Devuelve un dato que representa un NIF con numero igual a [numero]∗/

Nif crearNif (const int numero);

/∗∗ Pre: −−−∗ Post : Devuelve el numero del NIF unNif∗/

int numero (const Nif unNif);

/∗∗ Pre: −−−∗ Post : Devuelve la letra del NIF unNif∗/

char letra (const Nif unNif);

#endif

Modulo de biblioteca persona ubicado en el directorio programacion2/tipos. Su fichero de interfazes el siguiente (se puede descargar desde la web de la asignatura), a falta unicamente de disenar laestructura interna de los datos de tipo Persona. El fichero de implementacion del modulo debe serdesarrollado por cada alumno.

/∗∗ Fichero de interfaz persona.h del modulo persona∗/

#ifndef PERSONA H#define PERSONA H

#include ”nif .h”#include ”fecha .h”

48

// Maxima longitud del nombre de una personaconst int MAX LONG = 32;

/∗∗ Un dato de tipo Persona representa algunas informaciones relevante de una persona:∗ su nombre, su numero de identificacion fiscal y su fecha de nacimiento∗/

struct Persona {private :

. . . // Definir aquı la estructura interna del tipo Personapublic :

friend Persona definirPersona (const char nombre[], const Nif nif ,const Fecha nacimiento );

friend void nombre (Persona p, char suNombre[]);friend Nif nif (Persona p);friend Fecha nacimiento (Persona p);

};

/∗∗ Pre: −−−∗ Post : Devuelve una persona cuyo nombre es [nombre], su NIF es [ nif ] y∗ ha nacido en la fecha [nacimiento]∗/

Persona definirPersona (const char nombre[], const Nif nif , const Fecha nacimiento );

/∗∗ Pre: −−−∗ Post : La cadena de caracteres [suNombre] es el nombre de la persona [p]∗/

void nombre (Persona p, char suNombre[]);

/∗∗ Pre: −−−∗ Post : Devuelve el NIF de la persona [p]∗/

Nif nif (Persona p);

/∗∗ Pre: −−−∗ Post : Devuelve la fecha de nacimiento de la persona [p]∗/

Fecha nacimiento (Persona p);

Fichero cola.h ubicado en el directorio programacion2/genericas que presenta el diseno del tipogenerico Cola junto con una coleccion de funciones basicas para el trabajo con colas.

El diseno del del tipo generico Cola se debe realizar de forma similar a como se diseno en la practicaanterior tipo generico Pila.

Un esquema que ilustra el contenido del fichero cola.h se presenta a continuacion (se puede descargardesde la web de la asignatura).

/∗∗ Fichero cola .h que contiene la definicion del tipo generico Cola, que representa∗ una cola de datos genericos , y un conjunto de funciones basicas para trabajar con∗ colas definidas a partir del tipo generico Cola∗/

49

#ifndef COLA H#define COLA H

#include <fstream>

using namespace std;

/∗∗ Capacidad maxima de almacenamiento de datos en las colas que∗ puedan definirse a partir del tipo generico Cola∗/

const int DIM = 250; // Redefinir su valor en caso necesario

/∗∗ Predeclaracion del tipo Cola∗/

template <typename T>struct Cola;

/∗∗ Pre: −−−∗ Post : C = []∗/

template <typename T>void vaciar (Cola <T>& C) {

. . . // Escribir aquı el codigo de la funcion}

/∗∗ Pre: C = [d 1, d 2, ..., d K] AND K >= 0 AND K < DIM∗ Post : C = [d 1, d 2, ..., d K, nuevo]∗/

template <typename T>void insertar (Cola<T>& C, const T nuevo) {

. . . // Escribir aquı el codigo de la funcion}

/∗∗ Pre: C = [d 1, d 2, ..., d (K−1), d K] AND K > 0∗ Post : C = [d 2, ..., d (K−1), d K]∗/

template <typename T>void retirar (Cola<T>& C) {

. . . // Escribir aquı el codigo de la funcion}

/∗∗ Pre: C = [d 1, d 2, ..., d (K−1), d K] AND K > 0∗ Post : primero(C) = d 1∗/

template <typename T>T primero (const Cola<T> C) {

. . . // Escribir aquı el codigo de la funcion}

/∗∗ Pre: C = [d 1, d 2, ..., d (K−1), d K] AND K >= 0∗ Post : numElementos(C) = K

50

∗/template <typename T>int numElementos (const Cola<T> C) {

. . . // Escribir aquı el codigo de la funcion}

/∗∗ Pre: C = [d 1, d 2, ..., d (K−1), d K] AND K >= 0∗ Post : estaLlena (C) = (K == DIM)∗/

template <typename T>bool estaLlena (const Cola<T> C) {

. . . // Escribir aquı el codigo de la funcion}

/∗∗ Un dato definido a partir del tipo generico Cola representa una cola de datos∗ de tipo T, donde T es un tipo generico . Los datos de la cola son gestionados∗ segun una polıtica FIFO, es decir , el primero en entrar (en ser incorporado∗ a la cola) sera el primero en salir (en abandonar la cola ).∗/

template <typename T>struct Cola {

private :. . . // Definir aquı la estructura interna del tipo Cola

public :// Funciones con acceso a la estructura interna anteriorfriend void vaciar<T> (Cola <T>& C);friend void insertar <T> (Cola<T>& C, const T nuevo);friend void retirar <T> (Cola<T>& C);friend T primero<T> (const Cola<T>& C);friend int numElementos<T> (const Cola<T>& C);friend bool estaLlena<T> (const Cola<T>& C);

};

#endif

Fichero gestor.cc ubicado en el directorio programacion2/practica3 que presenta modulo principaldel programa a desarrolar en esta practica para la gestion de colas de personas y cuyo comportamientose ha descrito anteriormente.

Para representar el conjunto de datos asociados a personas, el programa trabajara con datos de tipoPersona y, para representar una cola de personas, el programa trabajara con una cola definida a partirdel tipo generico Cola.

3.3. Calendario de trabajo y tareas a realizar

Esta practica se plantea para ser desarrollada en dos fases a lo largo de seis semanas.

Primera fase de la tercera practica.

El trabajo correspondiente a la primera fase comprende la programacion y puesta a punto de lossiguientes componentes del programa:

• Desarrollo de los modulos de biblioteca fecha, nif y persona, que facilitan la

51

representacion y el trabajo con fechas del calendario, NIFs (numeros de identificacion fiscal) ypersonas.

• Desarrollo de algun sencillo programa auxiliar que permita probar el buen comportamientos delos tres modulos anteriores. A tıtulo ilustrativo se facilita un programa de prueba elemental enla web de la asignatura (almacenado en el fichero prueba1.cc).

• Desarrollo del fichero colas.h que facilita la representacion y el trabajo con colas de datos,a partir de la definicion del tipo generico Cola.

• Prueba del buen comportamientos del tipo generico Cola y de las funciones genericas definidasen el fichero colas.h. Para ello se puede hacer uso del programa de prueba que se facilita enla web de la asignatura (almacenado en el fichero prueba2.cc). Cada alumno es libre deadaptar y modificar este programa de prueba o de desarrollar programas de prueba alternativos.

Conviene insistir en la importancia de probar exhaustivamente el buen comportamiento de loscomponentes programados en esta primera fase antes de abordar el desarrollo de la segunda.

Los trabajos de programacion y las pruebas asociadas a esta primera fase debieran comenzarinmediatamente despues de concluida la segunda practica de la asignatura y debieran estar concluidosen la tercera sesion de practicas en laboratorio (programada para la segunda quincena de marzo).

Segunda fase de la tercera practica.

El trabajo correspondiente a la segunda fase comprende la programacion y puesta a punto del moduloprincipal del programa (fichero gestor.cc) a desarrollar en esta practica para la gestion de colas depersonas y cuyo comportamiento se ha descrito anteriormente.

Se recuerda que el codigo C++ del modulo principal no puede presentar ningun bucle. Su disenohara uso de tipo generico Cola, desarrollado en la primera fase de la practica, para representarcolas de personas y el tipo Persona para representar la informacion de cada una de las personasalmacenadas en una cola de personas.

Se insiste en la necesidad de probar exhaustivamente el programa hasta tener la conviccion de subuen funcionamiento.

Los trabajos de programacion y las pruebas asociadas a esta primera fase debieran comenzarinmediatamente despues de la tercera sesion de practicas en laboratorio y debieran estar concluidosen la cuarta sesion de practicas en laboratorio (programada para el mes de abril).

Para facilitar la compilacion de este programa, que consta de varios compoentes, se propone haceruso de la herramienta make que se decribe mas adelante y que sera explicada dentro de la cuartasesion de practicas en laboratorio.

3.4. ¿Como compilar y ejecutar los programas anteriores?

3.4.1. ¿Como compilar los programas de prueba de la primera fase de esta practica?

En los dos aparatados que sigue se explica como compilar programas que permitan realizar pruebas delcomportamiento de los elementos definidos en modulos persona, fecha y nif y en el fichero cola.h.

¿Como compilar el programa prueba1.cc?

Se va a construir un programa ejecutable en hendrix-ssh cuyo modulo principal esta definidoen el fichero prueba1.cc almacenado en el directorio programacion2/tipos/. Este ficheroesta disponible en la web de la asignatura.

52

El programa se apoya en el modulo de biblioteca persona que, a su vez, se apoya en los modulos debiblioteca fecha y nif. Antes de compilar el fichero prueba1.cc es necesario haber compilado losficheros de implementacion de los tres modulos de biblioteca, persona.cc, fecha.cc y nif.cc.

La secuencia de ordenes que permiten compilar los cuatro ficheros hasta obtener el fichero p1, con elcodigo del programa ejecutable, se detalla a continuacion.

Para compilar este programa lo mas comodo es estar previamente ubicados en el directorioprogramacion2/tipos ejecutando, en su caso, una orden cd. A continuacion basta con compilar loscuatro ficheros antes citados hasta obtener el fichero p1, con el codigo del programa ejecutable y estaremoslistos para ejecutar el programa p1.

hendrix02:˜/ cd $HOME/programacion2/tiposhendrix02:˜/programacion2/tipos/ g++ persona.cc -c -o ../practica3/persona.ohendrix02:˜/programacion2/tipos/ g++ fecha.cc -c -o ../practica3/fecha.ohendrix02:˜/programacion2/tipos/ g++ nif.cc -c -o ../practica3/nif.ohendrix02:˜/programacion2/tipos/ cd $HOME/programacion2/practica3hendrix02:˜/programacion2/practica3/ g++ prueba1.cc fecha.o nif.o persona.o

-o p1hendrix02:˜/programacion2/practica3/ ./p1

Nombre y apellido: Elena SalvadorFecha de nacimiento (aaaammdd): 19980803Numero de NIF: 76876504

Elena Salvador, con NIF 76876504-Q, nacio el 03/08/1998

hendrix02:˜/programacion2/tipos/ ...

Al comienzo del fichero prueba1.cc hay tres programadas tres ordenes de inclusion de ficheros deinterfaz de modulos:

#include ” ../ tipos / fecha .h”#include ” ../ tipos / nif .h”#include ” ../ tipos /persona .h”

Es posible que, al desarrollar el programa, no se conozca la ubicacion definitiva de estos tres moduloso, simplemente, no interese precisarla.

#include ”fecha .h”#include ”nif .h”#include ”persona .h”

En tal caso, la informacion sobre donde se ubican los ficheros de interfaz de estos modulo hay queaportarla al compilar mediante la opcion -I ruta:

hendrix02:˜/programacion2/practica3/ g++ prueba1.cc fecha.o nif.o persona.o-I ../tipos -o p1

hendrix02:˜/programacion2/practica3/ ./p1Nombre y apellido: Elena SalvadorFecha de nacimiento (aaaammdd): 19980803Numero de NIF: 76876504

Elena Salvador, con NIF 76876504-Q, nacio el 03/08/1998

53

hendrix02:˜/programacion2/tipos/ ...

¿Como compilar el programa prueba2.cc?

Se va a construir un programa ejecutable en hendrix-ssh cuyo modulo principal esta definido enel fichero prueba2.cc almacenado en el directorio programacion2/practica3/prueba2.cc.Este fichero esta disponible en la web de la asignatura.

Para compilar este programa lo mas comodo es estar previamente ubicados en el directorioprogramacion2/practica3 ejecutando, en su caso, una orden cd. A continuacion basta concompilar el fichero prueba1.cc generando el fichero que se ha optado por denominar p2 y estaremoslistos para ejecutar el programa ejecutable p2.

hendrix02:˜/ cd $HOME/programacion2/practica3hendrix02:˜/programacion2/practica3/ g++ prueba2.cc -o p2hendrix02:˜/programacion2/practica3/ ./p2La cola almacena 20 enteros

1. 12. 83. 27... presenta los restantes resultados de ejecutar primeraPrueba ...

hendrix02:˜/programacion2/practica3/ ...

3.4.2. ¿Como compilar el programa a desarrollar en la segunda fase de esta practica?

Se va a construir un programa ejecutable en hendrix-ssh cuyo modulo principal esta definido en elfichero gestor.cc almacenado en el directorio programacion2/practica3/.

El programa se apoya en el modulo de biblioteca persona que, a su vez, se apoya en los modulosde biblioteca fecha y nif. Antes de compilar el fichero gestor.cc es necesario haber compilado losficheros de implementacion de los tres modulos de biblioteca, persona.cc, fecha.cc y nif.cc. Porcomodidad los ficheros objeto resultantes de las tres compilaciones, persona.o, fecha.o y nif.o seubicanen el directorio programacion2/practica3/.

hendrix02:˜/ cd $HOME/programacion2/tiposhendrix02:˜/programacion2/tipos/ g++ persona.cc -c -o ../practica3/persona.ohendrix02:˜/programacion2/tipos/ g++ fecha.cc -c -o ../practica3/fecha.ohendrix02:˜/programacion2/tipos/ g++ nif.cc -c -o ../practica3/nif.ohendrix02:˜/programacion2/tipos/ cd $HOME/programacion2/practica3hendrix02:˜/.../practica3/ g++ gestor.cc persona.o fecha.o nif.o -o gestorhendrix02:˜/programacion2/practica3/ ./gestor

hendrix02:˜/programacion2/practica3/ ...

54

3.4.3. ¿Como evitar especificar en un programa la ruta de los ficheros nombrados en lasordenes include?

En el codigo del fichero gestor.cc deben figurar dos ordenes para declarar que allı se hande incluir los ficheros persona.h y cola.h. En principio, en tales ordenes se debe especificarno solo el nombre del fichero, sino su ubicacion fısica (por ejemplo, con relacion al directorio$HOME/programacion2/practica3:

#include ” ../ tipos /persona .h” // fichero de interfaz del modulo personas#include ” ../ genericas / cola .h” // fichero de definicion del tipo generico Cola

Si el programa se desarrollara desde el entorno CodeLite es muy probable que el camino (path) quedebiera preceder a los ficheros persona.h y cola.h serıan difererentes.

Por ello es deseable evitar la especificacion de la ubicacion de estos ficheros en las ordenes include:

#include ”persona .h” // fichero de interfaz del modulo personas#include ”cola .h” // fichero de definicion del tipo generico Cola

A cambio, la ubicacion de estos ficheros hay que declararla en la orden de compilacion mediante unaclausula -I, tal como se muestra a continuacion. La opcion -I permite especificar directorios adicionalesen los que localizar los ficheros citados en clausulas #include. La clasusula -I tambien se puede incluirantes de compilar un programa desde el entorno CodeLite.

hendrix02:˜/.../practica3/ g++ gestor.cc persona.o fecha.o nif.o-I ../tipos -I ../genericas -o gestorhendrix02:˜/programacion2/practica3/ ./gestor

ORDENES DISPONIBLES===================fininsertar

... presenta los restantes resultados de ejecutar gestor ...

hendrix02:˜/programacion2/practica3/ ...

3.4.4. ¿Como simplificar la compilacion de programs con una cierta complejidad?

La herramienta make que se describe en el siguiente apartado permite simplificar el proceso decompilacion de programas. Con ello se ahorra tiempo, tanto mas, cuanto mas compleja sea la estructuradel programa.

3.5. La herramienta make

La herramienta make es un programa muy utilizado en sistemas como unix y linux, que facilita eldesarrollo de programas ya que permite controlar el proceso de compilacion de los modulos y ficheros quelo integran.

55

La herramienta make ejecuta una secuencia de acciones que se describen en un fichero de texto. Elcontenido de este fichero puede verse como un guion que describe que debe hacerse para lograr el objetivode compilar el programa y obtener como resultado un fichero con el codigo ejecutable.

En un fichero make las acciones que la herramienta make debe ejecutar se definen mediante reglas quetienen la siguiente forma:

objetivo: dependencias<TAB> orden1<TAB> orden2

...<TAB> ordenK

En la primera lınea se define un objetivo, al que siguen dos puntos (:) y una lista de dependencias,eventualmente vacıa. Cada dependencia hace referencia a un objetivo que debe estar actualizado o, en sucaso, ser alcanzado previamente a comenzar a ejecutar las ordenes descritas en la regla.

Tras alcanzar todos los objetivos descritos en la lista de dependencias de la regla, make ejecuta lasordenes descritas en las lıneas sucesivas, salvo aquellas cuya ejecucion no sea necesaria. La escritura decada orden debe venir precedida por un caracter tabulador (<TAB>, en el esquema anterior).

En resumen, la ejecucion de una regla tiene dos fases:

1. En primer lugar, logro de los objetivos incluidos en la lista de dependencias que no esten actualizados.

2. A continuacion, procede a actualizar el objetivo propio de la regla ejecutando las K ordenes descritasen las lıneas sucesivas, excepto en el caso de que ello no sea necesario por estar el objetivo yaactualizado.

Para ilustrar el uso del programa make se van a presentar diversas versiones de un fichero make deutilidad para el desarrollo del programa planteado en esta practica.

Veremos mas adelante que a este fichero de texto se le suele denominar makefile (fichero de laherramienta make). No obstante este fichero de texto puede recibir un nombre distinto. En los sucesivosejemplos que se presenten en este apartado, el fichero make va a recibir los nombres guion v1,guion v2, guion v3, etc.

3.5.1. Primera version de un fichero make para compilar el programa

Esta primera version del fichero make, que hemos denominado guion v1, facilita la compilacion delprograma generando un fichero, gestor, con su codigo ejecutable:

#-------------------------------------------------------------------------# File: guion_v1 (practica3, version 1)# Author: profesores de programacion 2# Date: 16/01/2017# Coms.: Ejemplo de fichero ’make’ para crear el ejecutable del# programa a desarrollar en la practica 3#-------------------------------------------------------------------------

56

# Primera regla: detalla como crear el ejecutable ’gestor’

gestor: fecha.o nif.o persona.o gestor.cc<TAB> g++ -o gestor gestor.cc fecha.o nif.o persona.o

# Segunda regla: detalla como crear el fichero objeto ’fecha.o’

fecha.o: ../tipos/fecha.h ../tipos/fecha.cc<TAB> g++ -c ../tipos/fecha.cc

# Tercera regla: detalla como crear el fichero objeto ’nif.o’

nif.o: ../tipos/nif.h ../tipos/nif.cc<TAB> g++ -c ../tipos/nif.cc

# Cuarta regla: detalla como crear el fichero objeto ’persona.o’

persona.o: ../tipos/persona.h ../tipos/persona.cc<TAB> g++ -c ../tipos/persona.cc

La primera regla plantea como objetivo la creacion o actualizacion del programa ejecutable gestor.En la lista de dependencias se declaran los fichero objeto fecha.o, nif.o y persona.o y el ficherofuente gestor.cc. Si cualquiera de los tres ficheros objeto no existen o no estan actualizadso, entoncesmake ejecutara con caracter previo la regla que tiene como objetivo dicho fichero: fecha.o, nif.o opersona.o.

La orden make solo procedera a compilar de nuevo el fichero fuente gestor.cc en tres casos: 1) sino se dispone del fichero ejecutable gestor (objetivo de la regla), 2) si es necesario actualizar alguno delos tres fichero objeto y 3) si el fichero fuente gestor.cc ha sido modificado desde la ultima ejecucionde la misma orden make.

En un fichero makefile se pueden escribir comentarios. Un comentario comienza por el caracter # yse prolonga hasta el final de la lınea.

Para crear el programa ejecutable gestor se puede ejecutar la orden make, seleccionando la reglacuyo objetivo se pretender lograr (la regla gestor)y anadiendo la opcion -f, para determinar el nombre delfichero make, tal como se presenta a continuacion.

hendrix02:-/programacion2/practica3/ make gestor -f guion_v1g++ -c ../tipos/fecha.ccg++ -c ../tipos/nif.ccg++ -c ../tipos/persona.ccg++ -o gestor gestor.cc fecha.o nif.o persona.ohendrix02:-/programacion2/practica3/ ...

Si la regla cuyo objetivo se pretender lograr es la primera (la regla gestor) entonces se puede omitirel nombre de la regla:

hendrix02:-/programacion2/practica3/ make -f guion_v1g++ -c ../tipos/fecha.ccg++ -c ../tipos/nif.ccg++ -c ../tipos/persona.cc

57

g++ -o gestor gestor.cc fecha.o nif.o persona.ohendrix02:-/programacion2/practica3/ ...

3.5.2. Segunda version de un fichero make para compilar el programa

La segunda version del fichero make, que hemos denominado guion v2, es similar a la anterior.Presenta como unica novedad que en ella se define y se hace uso de una variable.

En un fichero make se pueden variables para facilitar posterioremente su modificacion. En este nuevofichero make se ha definido la variable CC a la que se le ha asignado el nombre del compilador de C++que va a ser utilizado, el compilador g++. Cada vez que se desee escribir en una orden el nombre de dichocompilador, bastara hacer referencia al valor de la variable CC de la forma $(CC). En el caso de quedesearamos cambiar el compilador a utilizar, bastarıa modificar el valor de la variable CC, mientras que elresto del fichero guion v2 se mantendrıa inalterado.

#-------------------------------------------------------------------------# File: guion_v2 (practica3, version 2)# Author: profesores de programacion 2# Date: 16/01/2017# Coms.: Ejemplo de fichero ’make’ para crear el ejecutable del# programa a desarrollar en la practica 3#-------------------------------------------------------------------------

# Definicion de la variable CC. Se le asigna el nombre del compilador g++# Cuando en una orden se escribe $(CC) equivale a escribir g++

CC = g++

# Primera regla: detalla como crear el ejecutable ’gestor’

gestor: fecha.o nif.o persona.o gestor.cc<TAB> $(CC) -o gestor gestor.cc fecha.o nif.o persona.o

# Segunda regla: detalla como crear el fichero objeto ’fecha.o’

fecha.o: ../tipos/fecha.h ../tipos/fecha.cc<TAB> $(CC) -c ../tipos/fecha.cc

# Tercera regla: detalla como crear el programa objeto ’nif.o’fichero

nif.o: ../tipos/nif.h ../tipos/nif.cc<TAB> $(CC) -c ../tipos/nif.cc

# Cuarta regla: detalla como crear el fichero objeto ’persona.o’

persona.o: ../tipos/persona.h ../tipos/persona.cc<TAB> $(CC) -c ../tipos/persona.cc

3.5.3. Tercera version de un fichero make para compilar el programa

La tercera version del fichero make, que hemos denominado guion v3, es similar a lasanteriores. Presenta como novedad que en ella se definen dos nuevas variables, BUSCAR DIR TIPOS

58

y BUSCAR DIR GENERICAS a las que se asignan como valores dos opciones -I directorio paraampliar los directorios en los que el compilador debe intentar localizar los ficheros citados en clausulas#include.

En la orden de compilacion definida en la primera regla se puede observar que se han anadido las dosopciones -I citadas. Tambien se puede observar como se puede escribir una orden en varias lıneas. Paradenotar que la siguiente lınea forma parte de la orden basta con finalizar la lınea con el caracter \.

De esta forma se podran simplicar las ordenes include del fichero gestor.cc, eliminando la ruta opath que determina la ubicacion de los ficheros:

#include ”persona .h” // fichero de interfaz del modulo personas#include ”cola .h” // fichero de definicion del tipo generico Cola

#-------------------------------------------------------------------------# File: guion_v3 (practica3, version 3)# Author: profesores de programacion 2# Date: 16/01/2017# Coms.: Ejemplo de fichero ’make’ para crear el ejecutable del# programa a desarrollar en la practica 3#-------------------------------------------------------------------------

# Definicion de la variable CC. Se le asigna el nombre del compilador g++# Cuando en una orden se escribe $(CC) equivale a escribir g++

CC = g++

# Definicion de las variables BUSCAR_DIR_TIPOS y BUSCAR_DIR_GENERICAS a las# que se asigna la opcion -I path del compilador para determinar caminos o# ’paths’ que conducen a directorios donde debe buscar ficheros nombrados# en clausulas #include

BUSCAR_DIR_TIPOS = -I ../tiposBUSCAR_DIR_GENERICAS = -I ../genericas

# Primera regla: detalla como crear el ejecutable ’gestor’

gestor: fecha.o nif.o persona.o gestor.cc<TAB> $(CC) -o gestor gestor.cc fecha.o nif.o persona.o $(BUSCAR_DIR_TIPOS)\$(BUSCAR_DIR_GENERICAS)

# Segunda regla: detalla como crear el fichero objeto ’fecha.o’

fecha.o: ../tipos/fecha.h ../tipos/fecha.cc<TAB> $(CC) -c ../tipos/fecha.cc

# Tercera regla: detalla como crear el fichero objeto ’nif.o’

nif.o: ../tipos/nif.h ../tipos/nif.cc<TAB> $(CC) -c ../tipos/nif.cc

# Cuarta regla: detalla como crear el fichero objeto ’persona.o’

persona.o: ../tipos/persona.h ../tipos/persona.cc<TAB> $(CC) -c ../tipos/persona.cc

59

3.5.4. Cuarta version de un fichero make para compilar el programa

La cuarta version del fichero make, que hemos denominado guion v4, es similar a las anteriores.Incorpora una quinta regla de nombre borrarObjetos que permite borrar los ficheros objeto, los ficheros’*.o’ presentes en el directorio.

#include ”persona .h” // fichero de interfaz del modulo personas#include ”cola .h” // fichero de definicion del tipo generico Cola

#-------------------------------------------------------------------------# File: guion_v4 (practica3, version 4)# Author: profesores de programacion 2# Date: 16/01/2017# Coms.: Ejemplo de fichero ’make’ para crear el ejecutable del# programa a desarrollar en la practica 3#-------------------------------------------------------------------------

# Definicion de la variable CC. Se le asigna el nombre del compilador g++# Cuando en una orden se escribe $(CC) equivale a escribir g++

CC = g++

# Definicion de las variables BUSCAR_DIR_TIPOS y BUSCAR_DIR_GENERICAS a las# que se asigna la opcion -I path del compilador para determinar caminos o# ’paths’ que conducen a directorios donde debe buscar ficheros nombrados# en clausulas #include

BUSCAR_DIR_TIPOS = -I ../tiposBUSCAR_DIR_GENERICAS = -I ../genericas

# Primera regla: detalla como crear el ejecutable ’gestor’

gestor: fecha.o nif.o persona.o gestor.cc<TAB> $(CC) -o gestor gestor.cc fecha.o nif.o persona.o $(BUSCAR_DIR_TIPOS) \$(BUSCAR_DIR_GENERICAS)

# Segunda regla: detalla como crear el fichero objeto ’fecha.o’

fecha.o: ../tipos/fecha.h ../tipos/fecha.cc<TAB> $(CC) -c ../tipos/fecha.cc

# Tercera regla: detalla como crear el fichero objeto ’nif.o’

nif.o: ../tipos/nif.h ../tipos/nif.cc<TAB> $(CC) -c ../tipos/nif.cc

# Cuarta regla: detalla como crear el fichero objeto ’persona.o’

persona.o: ../tipos/persona.h ../tipos/persona.cc<TAB> $(CC) -c ../tipos/persona.cc

# Quinta regla: elimina los ficheros objetos ’*.o’ presentes# en el directorio

borrarObjetos:<TAB> rm *.o

60

La ejecucion de la quinta regla se logra escribiendo en la orden make el nombre de la regla, tal como semuestra a continuacion.

hendrix02:-/programacion2/practica3/ make borrarObjetos -f guion_v4rm *.ohendrix02:-/programacion2/practica3/ ...

3.5.5. Version final de un fichero make para compilar el programa

La version final del fichero make es identica a la anterior. Solo cambia el nombre del fichero que ahorase denomina makefile.

#-------------------------------------------------------------------------# File: makefile (practica3, version final)# Author: profesores de programacion 2# Date: 16/01/2017# Coms.: Ejemplo de fichero ’make’ para crear el ejecutable del# programa a desarrollar en la practica 3#-------------------------------------------------------------------------

# Definicion de la variable CC. Se le asigna el nombre del compilador g++# Cuando en una orden se escribe $(CC) equivale a escribir g++

CC = g++

# Definicion de las variables BUSCAR_DIR_TIPOS y BUSCAR_DIR_GENERICAS a las# que se asigna la opcion -I path del compilador para determinar caminos o# ’paths’ que conducen a directorios donde debe buscar ficheros nombrados# en clausulas #include

BUSCAR_DIR_TIPOS = -I ../tiposBUSCAR_DIR_GENERICAS = -I ../genericas

# Primera regla: detalla como crear el ejecutable ’gestor’

gestor: fecha.o nif.o persona.o gestor.cc<TAB> $(CC) -o gestor gestor.cc fecha.o nif.o persona.o $(BUSCAR_DIR_TIPOS) \

$(BUSCAR_DIR_GENERICAS)

# Segunda regla: detalla como crear el fichero objeto ’fecha.o’

fecha.o: ../tipos/fecha.h ../tipos/fecha.cc<TAB> $(CC) -c ../tipos/fecha.cc

# Tercera regla: detalla como crear el fichero objeto ’nif.o’

nif.o: ../tipos/nif.h ../tipos/nif.cc<TAB> $(CC) -c ../tipos/nif.cc

# Cuarta regla: detalla como crear el fichero objeto ’persona.o’

persona.o: ../tipos/persona.h ../tipos/persona.cc<TAB> $(CC) -c ../tipos/persona.cc

61

# Quinta regla: elimina los ficheros objetos ’*.o’ presentes# en el directorio

borrarObjetos:<TAB> rm *.o

El nombre, por defecto, de un fichero make es makefile. Esto simplifica la orden make ya que ahorano serıa necesario precisar en la orden el nombre del fichero make mediante la opcion -f.

La orden make para generar el fichero ejecutable gestor se simplifica ahora notablemente:

hendrix02:-programacion2/practica3// make gestorg++ -c ../tipos/fecha.ccg++ -c ../tipos/nif.ccg++ -c ../tipos/persona.ccg++ -o gestor gestor.cc fecha.o nif.o persona.o -I ../tipos -I ../genericashendrix02:-/programacion2/practica3/ ...

Y la orden make para ejecutar la quinta regla, la que permite borrar los ficheros ’*.o’ sera la siguiente:

hendrix02:-/programacion2/practica3/ make borrarObjetosrm *.ohendrix02:-/programacion2/practica3/ ...

Al ser gestor el nombre de la primera regla, el nombre de la regla, gestor, puede omitirse en laorden make y esta se reduce a la mınima expresion:

hendrix02:-/programacion2/practica3/ makeg++ -c ../tipos/fecha.ccg++ -c ../tipos/nif.ccg++ -c ../tipos/persona.ccg++ -o gestor gestor.cc fecha.o nif.o persona.o -I ../tipos -I ../genericashendrix02:-/programacion2/practica3/ ...

3.5.6. Otra aplicaciones y documentacion de la herramienta make

La herramienta make tiene otras aplicaciones y algunas caracteristicas adicionales que incrementansu potencia. Para ampliar conocimientos sobre esta valiosa utilidad se recomienda buscar informacion eninternet.

3.6. Resultados del trabajo desarrollado en las tres primeras practicas

Como resultado de las tres primeras practicas, cada alumno dispondra en su cuenta hendrix-ssh deun directorio (carpeta) denominado programacion2 dentro del cual se podran encontrar los directorios(carpetas) y ficheros que se detallan a continuacion. Estos ficheros debieran estar listos antes del 20 demarzo, fecha del comienzo de las sesiones correspondientes a la siguiente practica.

62

1. Directorio (carpeta) programacion2/practica1 con los siguientes ficheros:

Fichero tiempoReaccion.cc con el codigo C++ del primer programa de la practica 1a.

Fichero generarTabla01.cc con el codigo C++ del segundo programa de la practica 1a.

Fichero generarTabla02.cc con el codigo C++ del tercer programa de la practica 1a.

Fichero medirCoste.cc con el codigo C++ del cuarto programa de la practica 1a.

2. Directorio (carpeta) programacion2/practica2 con los siguientes ficheros:

Ficheros de interfaz y de implementacion, calculos.h y calculos.cc, con el codigo C++ delmodulo calculos de la practica 2a.

Fichero funcionesPilas.h de la practica 2a con el codigo C++ de una coleccion de funcionesgenericas, programadas sin bucles, sin aplicar tecnicas de inmersion y sin funciones auxiliares,que ejecutan operaciones con pilas de datos, definidas a partir del tipo generico Pila, de un nivelsuperior al de las funciones genericas basicas del fichero pila.h.

Ficheros con los programas de prueba (pruebas01.cc, pruebas02.cc, etc.) que se hayan puestoa punto para realizar pruebas de los desarrollos anteriores.

3. Directorio (carpeta) programacion2/practica3 con los siguientes ficheros:

Fichero gestor.cc con el codigo C++ del modulo principal del programa propuesto en la practica3a.

Fichero makefile para facilitar la compilacion del programa propuesto en la practica 3a.

4. Directorio (carpeta) programacion2/genericas con los siguientes ficheros:

Fichero pila.h con el codigo C++ desarrollado en la practica 2a en el que se representa el tipogenerico Pila junto con una coleccion de seis funciones genericas basicas para trabajar con pilasde datos definidas a partir del tipo Pila.

Fichero cola.h con el codigo C++ desarrollado en la practica 3a en el que se representa el tipogenerico Cola junto con una coleccion de seis funciones genericas basicas para trabajar concolas de datos definidas a partir del tipo Pila.

5. Directorio (carpeta) programacion2/tipos con los siguientes ficheros:

Ficheros fecha.h y fecha.cc de interfaz y de implementacion, respectivamente, delmodulo de biblioteca fecha.

Ficheros nif.h y nif.cc de interfaz y de implementacion, respectivamente, del modulo debiblioteca nif.

Ficheros persona.h y persona.cc de interfaz y de implementacion, respectivamente, delmodulo de biblioteca persona.

63

Capıtulo 4

Practica 4: Analisis experimental del costede algoritmos

4.1. Objetivos de la practica

El coste, en tiempo, necesario para ordenar una coleccion de datos del mismo tipo, dispuestos en unvector, depende de multiples factores entre los que cabe citar los siguientes:

El algoritmo de ordenacion utilizado

El numero de datos a ordenar

El tipo de los datos a ordenar

La disposicion inicial de los datos en el vector

El computador en el que se ejecuta el algoritmo

El sistema operativo que gobierna el computador

El compilador utilizado para generar el programa ejecutable

El nivel de optimizacion del codigo compilado

El objetivo principal de la practica es analizar el coste, en tiempo de ejecucion, de losalgoritmos de ordenacion de vectores por seleccion y de ordenacion de vectorespor insercion, en funcion del numero de datos a ordenar, en las circunstancias que se detallan acontinuacion:

Los datos a ordenar seran enteros de tipo int.

Se analizaran sus costes para dos disposiciones iniciales de los datos en el vector: datos inicialmentedispuestos de forma aleatoria y datos inicialmente dispuestos ya ordenados.

Los computadores en los que se ejecutaran los algoritmos y mediran los costes seran en los pc dellaboratorio L0.04 con sistema operativo CentOS (linux) y en el cluster hendrix-ssh consistema operativo unix.

El compilador de C++ utilizado para generar los diferentes programas ejecutables sera el compiladorg++ .

64

Al compilar, se generara codigo ejecutable para los procesadores de los pcs del laboratorio L0.04y del servidor hendrix-ssh con dos niveles diferentes de optimizacion: nivel 0 y nivel 2.

Como segundo objetivo de la practica, se apendera a utilizar scripts o guiones de ordenes dirigidasal sistema operativo.

4.2. Analisis del algoritmo de ordenacion por seleccion

En primer lugar se va a analizar el coste, en tiempo, del algoritmo de ordenacion de vectores por elmetodo de seleccion. Se van a ordenar vectores que almacenan datos enteros de tipo int haciendo uso delalgoritmo generico que se muestra a continuacion. El codigo de este algoritmo se ha dispuesto en el ficheroalgOrdenacion.h, en la carpeta practica4 accesible desde la web de la asignatura. Este fichero sedebera almacenar en el directorio (carpeta) programacion2/genericas de hendrix-ssh.

/∗∗ Definicion de los predicados [esPermutacion] y [ordenado]:∗ esPermutacion(v1,v2,desde, hasta) = (PT alfa EN [desde,hasta ].∗ (Num beta EN [desde,hasta ]. v1[beta] = v1[alfa ])∗ = (Num beta EN [desde,hasta ]. v2[beta] = v1[alfa ]))∗ ordenado(v,desde, hasta) =∗ (PT alfa EN [desde,hasta−1].v[alfa ] <= v[alfa+1])∗/

/∗∗ Pre: v = v0 AND n > 0∗ Post : esPermutacion(v ,v0 ,0, n−1) AND ordenado(v,0,n−1)∗/

template <typename T>void seleccion (T v [], const int n) {

// Ordenacion del vector v[0,n−1] aplicando el metodo de seleccionfor ( int i = 0; i != n−1; ++i){

// n > 0 AND esPermutacion(v,vo,0,n−1) AND ordenado(v,0,i−1) AND// (PT alfa EN [0, i−1].(PT beta EN [i ,h−1].v[alfa] <= v[beta]))int iMenor = i , j = i ;while ( j != n−1) {

j = j + 1;if (v[ j ] < v[iMenor]) {

iMenor = j ;}

}// Permuta v[ i ] y v[iMenor]T dato = v[ i ];v[ i ] = v[iMenor];v[iMenor] = dato ;

}}

4.2.1. La funcion de coste, en tiempo, para cada uno de los casos

El coste, en tiempo, del algoritmo de ordenacion de vectores por el metodo de seleccion depende delos factores enumerados en el apartado anterior: el numero de datos a ordenar, el tipo de estos datos, sudisposicion en el vector, la velocidad del computador en el que va a ser ejecutado, el compilador utilizado y

65

el nivel de optimizacion del codigo ejecutable. Una vez fijados todos los factores, a excepcion del numerode datos a ordenar, que denominaremos n, la funcion de coste, t(n), es asintoticamente proporcional alcuadrado del numero de datos a ordenar, tal como se estudia en la asignatura, es decir:

t(n) = k × n2.

El valor del coeficiente k depende de los factores citados, lo cual dara lugar a una funcion de costediferente en cada caso.

En el siguiente apartado se va a trabajar en la determinacion de la funcion de coste de este algoritmo encuatro casos diferentes, determinados por la disposicion inicial de los datos en el vector y por el nivel deoptimizacion del codigo del algoritmo al ser compilado por g++ para ser ejecutado en uno de los pcs delLab.0.04 y en el cluster hendrix-ssh.

La primera tarea que se propone es la determinacion de las funciones de coste t(n) del algoritmo deordenacion por seleccion, dependientes del numero n de datos a ordenar, en los cuatro casos que vienendeterminados por los siguientes factores:

La disposicion inicial de los datos en el vector. Se estudiaran dos situaciones diferentes: 1) losdatos iniciales del vector estan dispuestos aleatoriamente y 2) los datos del vector ya estan ordenadosal invocar la ejecucion del algoritmo.

El nivel de optimizacion del codigo compilado del algoritmo. Se estudiaran dos situaciones, lasque corresponden a los niveles 0 y 2 de optimizacion del compilador de C++ que va a ser utilizado,el compilador g++.

La variacion de los dos factores anteriores define un total de cuatro casos diferentes, cada uno de loscuales dara lugar a una funcion de coste cuadratica de la forma t(n) = k×n2. La diferencia entre funcionesde coste radica en el valor que toma el coeficiente k en cada caso.

Determinacion de las diferentes funciones de coste

Como paso previo a la determinacion de las cuatro funciones de coste, se deben tomar medidasexperimentales del coste del algoritmo en las diferentes circunstancias descritas en el apartado anterior.

Se van a tomar medidas para dos valores diferentes del numero de datos almacenados en los vectores aordenar, para 25.000 y 50.000 datos.

Se propone denominar medirCoste01.cc a la variante desarrollada en esta practica del programamedirCoste desarrollado en la primera practica que permita:

Medir el coste, en tiempo, del algoritmo de ordenacion por seleccion aplicado a vectores cuyosdatos estan dispuestos inicialmente de forma aleatoria. Para ello hay que compilar el programamedirCoste01.cc dos veces, cada una de ellas con el nivel de optimizacion que corresponda(niveles 0 y 2).

Medir el coste, en tiempo, del mismo algoritmo aplicado a vectores cuyos datos ya estan ordenadosinicialmente, tras haber ejecutado el programa compilado con niveles de optimizacion 0 y 2.

Los datos experimentales de coste en tiempo, expresados en segundos, en uno de los pc dellab.0.04 se anotaran en la parte superior de Tabla 1.

A partir de los datos de coste correspondientes a los cuatro casos en los que se ordena un mayor numerode datos, 50.000 datos, se puede deducir una caracterizacion del coeficiente k de la funcion de coste, en

66

cada uno de dichos casos. Debe anotarse en la parte inferior de la Tabla 1 cada uno de los cuatro valorescalculados del coeficiente k, expresados en nanosegundos (ns). Conviene recordar que 1 ns = 10−9 s.

ALGORITMO DE ORDENACION DE VECTORES POR SELECCIONTIPO DE LOS DATOS ALMACENADOS EN EL VECTOR: INTMAQUINA EN LA QUE SE EJECUTA: PC DEL LAB. 0.04SISTEMA OPERATIVO: CENTOS (LINUX)COMPILADOR UTILIZADO: G++

NIVEL Coste de ejecucion [en segundos (s)]DE Datos dispuestos aleatoriamente Datos inicialmente ya ordenados

OPTIMIZACION n = 25.000 datos n = 50.000 datos n = 25.000 datos n = 50.000 datos0 s s s s2 s s s s

Determinacion de las funciones de coste en cada casoNIVEL Datos dispuestos aleatoriamente Datos inicialmente ya ordenados

DE Funcion de coste: t1(n) = k1.n2 Funcion de coste: t2(n) = k2.n

2

OPTIMIZACION Valor del coeficiente k1 [en ns] Valor del coeficiente k2 [en ns]0 ns ns2 ns ns

Tabla 1. Determinacion de las funciones de coste, en tiempo, en uno de los pcs del lab. 0.04del algoritmo de ordenacion de vectores por seleccion aplicado a datos enteros de tipo int dispuestosinicialmente de forma aleatoria y ya ordenados.

Los datos experimentales de coste en tiempo, expresados en segundos, en el cluster hendrix-sshse anotaran en la parte superior de Tabla 2.

A partir de los datos de coste correspondientes a los cuatro casos en los que se ordena un mayor numerode datos, 50.000 datos, se puede deducir una caracterizacion del coeficiente k de la funcion de coste, encada uno de dichos casos. Debe anotarse en la parte inferior de la Tabla 2 cada uno de los cuatro valorescalculados del coeficiente k, expresado en nanosegundos (ns).

ALGORITMO DE ORDENACION DE VECTORES POR SELECCIONTIPO DE LOS DATOS ALMACENADOS EN EL VECTOR: INTMAQUINA EN LA QUE SE EJECUTA: CLUSTER HENDRIX-SSHSISTEMA OPERATIVO: UNIXCOMPILADOR UTILIZADO: G++

NIVEL Coste de ejecucion [en segundos (s)]DE Datos dispuestos aleatoriamente Datos inicialmente ya ordenados

OPTIMIZACION n = 25.000 datos n = 50.000 datos n = 25.000 datos n = 50.000 datos0 s s s s2 s s s s

Determinacion de las funciones de coste en cada casoNIVEL Datos dispuestos aleatoriamente Datos inicialmente ya ordenados

DE Funcion de coste: t1(n) = k1.n2 Funcion de coste: t2(n) = k2.n

2

OPTIMIZACION Valor del coeficiente k1 [en ns] Valor del coeficiente k2 [en ns]0 ns ns2 ns ns

Tabla 2. Determinacion de las funciones de coste, en tiempo, en el servidor hendrix-ssh, del

67

algoritmo de ordenacion de vectores por seleccion aplicado a datos enteros de tipo int dispuestosinicialmente de forma aleatoria y ya ordenados.

Comprobacion de la precision de las diferentes funciones de coste

A continuacion se va a comprobar la bondad de las cuatro funciones de coste calculadas en el apartadoanterior comparando, para un numero de datos a ordenar igual a 25.000, los valores estimados del coste apartir de dichas funciones de coste y los valores de coste medidos experimentalmente, en cada uno de loscasos.

Para ello se deben completar las Tablas 3 y 4 presentadas a continuacion. En su parte superiorse analiza la precision de las dos funciones de coste (una por cada nivel de optimizacion del codigo) enlos casos en que los 25.000 datos del vector estan inicialmente dispuestos de forma aleatoria. En su parteinferior se analiza la precision de las dos funciones de coste (una por cada nivel de optimizacion del codigo)en los casos en que los 25.000 datos del vector ya estan inicialmente ordenados.

El modo de calculo de los errores en cada estimacion del coste se describe en la parte inferior de lasTablas 3 y 4.

ALGORITMO DE ORDENACION DE VECTORES POR SELECCIONTIPO DE LOS DATOS ALMACENADOS EN EL VECTOR: INTNUMERO DE DATOS A ORDENAR: 25.000MAQUINA EN LA QUE SE EJECUTA: PC DEL LAB. 0.04SISTEMA OPERATIVO: UNIXCOMPILADOR UTILIZADO: G++DISPOSICION INICIAL DE LOS 25.000 DATOS EN EL VECTOR: DISPUESTOS ALEATORIAMENTE

NIVEL COSTE COSTE ERROR EN LA ERROR EN LA

DE EXPERIMENTAL ESTIMADO ESTIMACION ESTIMACION

OPTIMIZACION [segs.] [segs.] [segs.] {%}0 s s s %2 s s s %

DISPOSICION INICIAL DE LOS 25.000 DATOS EN EL VECTOR: INICIALMENTE YA ESTAN ORDENADOS

NIVEL COSTE COSTE ERROR EN LA ERROR EN LA

DE EXPERIMENTAL ESTIMADO ESTIMACION ESTIMACION

OPTIMIZACION [segs.] [segs.] [segs.] [%]0 s s s %2 s s s %

error en la estimacion [segs.]: coste estimado - coste experimentalerror en la estimacion [ %]: 100.0 x (coste estimado - coste experimental) / coste experimental

Tabla 3. Comparacion entre el coste estimado, en tiempo, a partir de las funciones de coste deducidasen la Tabla 1 y el coste medido experimentalmente en uno de los pc del lab 0.04 para ordenar unvector con 25.000 datos de tipo int dispuestos aleatoriamente y dispuestos ya ordenados.

68

ALGORITMO DE ORDENACION DE VECTORES POR SELECCIONTIPO DE LOS DATOS ALMACENADOS EN EL VECTOR: INTNUMERO DE DATOS A ORDENAR: 25.000MAQUINA EN LA QUE SE EJECUTA: CLUSTER HENDRIXSISTEMA OPERATIVO: UNIXCOMPILADOR UTILIZADO: G++DISPOSICION INICIAL DE LOS 25.000 DATOS EN EL VECTOR: DISPUESTOS ALEATORIAMENTE

NIVEL COSTE COSTE ERROR EN LA ERROR EN LA

DE EXPERIMENTAL ESTIMADO ESTIMACION ESTIMACION

OPTIMIZACION [segs.] [segs.] [segs.] {%}0 s s s %2 s s s %

DISPOSICION INICIAL DE LOS 25.000 DATOS EN EL VECTOR: INICIALMENTE YA ESTAN ORDENADOS

NIVEL COSTE COSTE ERROR EN LA ERROR EN LA

DE EXPERIMENTAL ESTIMADO ESTIMACION ESTIMACION

OPTIMIZACION [segs.] [segs.] [segs.] [%]0 s s s %2 s s s %

error en la estimacion [segs.]: coste estimado - coste experimentalerror en la estimacion [ %]: 100.0 x (coste estimado - coste experimental) / coste experimental

Tabla 4. Comparacion entre el coste estimado, en tiempo, a partir de las funciones de coste deducidasen la Tabla 2 y el coste medido experimentalmente en el cluster hendrix-ssh para ordenar un vectorcon 25.000 datos de tipo int dispuestos aleatoriamente y dispuestos ya ordenados.

4.2.2. Analisis de la eficiencia del algoritmo de ordenacion de vectores por seleccion

Como resultado de esta tarea se debe redactar un documento que incluya las cuato tablas anteriores, conlos datos que corresponda, ası como la respuesta a las preguntas que se plantean a continuacion, junto conlas razones que justifican cada una de las respuestas.

1. A la vista de los datos que muestra la Tabla 2, ¿cual es el nivel de optimizacion recomendablepara obtener codigo eficiente al compilar en el cluster hendrix-ssh el algoritmo de ordenacion devectores por seleccion? Justificar la respuesta.

2. A la vista de los datos que muestra la Tabla 4, ¿pueden considerarse validas las diferentesaproximaciones asintoticas t(n) = k × n2 a la funcion del coste del algorimo de ordenacion devectores por seleccion? Justificar la respuesta.

3. ¿Existen diferencias notables en cuanto a la eficiencia del algoritmo de ordenacion de vectores porseleccion segun sea la disposicion inicial de los datos en el vector? A la vista del codigo del algoritmo,¿cuales son las razones que sustentan la afirmacion anterior? Justificar las respuestas.

4. Estimar cuantos datos dispuestos aleatoriamente se podrıan ordenar ejecutando este algoritmo en elcluster hendrix-ssh en un tiempo maximo de una hora. Detallar los calculos realizados.

5. Cuantas veces son mas rapidos ejecutando este algoritmo de ordenacion los pc del Lab.0.04respecto del cluster hendrix-ssh.

69

4.3. Analisis del algoritmo de ordenacion por insercion

Una version generica del algoritmo de ordenacion de vectores por insercion se presenta a continuacion.

/∗∗ Definicion de los predicados [esPermutacion] y [ordenado]:∗ esPermutacion(v1,v2,desde, hasta) = (PT alfa EN [desde,hasta ].∗ (Num beta EN [desde,hasta ]. v1[beta] = v1[alfa ])∗ = (Num beta EN [desde,hasta ]. v2[beta] = v1[alfa ]))∗ ordenado(v,desde, hasta) =∗ (PT alfa EN [desde,hasta−1].v[alfa ] <= v[alfa+1])∗/

/∗∗ Pre: v = v0 AND n > 0∗ Post : esPermutacion(v ,v0 ,0, n−1) AND ordenado(v,0,n−1)∗/

template <typename T>void insercion (T v [], const int n) {

// Ordenacion del vector v[0,n−1] aplicando el metodo de insercionfor ( int i = 1; i <= n−1; ++i) {

/∗ n > 0 AND esPermutacion(v,v0,0,n−1) AND ordenado(v,0,i−1)T dato = v[i ];int j = i , iLimite = 0;while ( j != iLimite ) {

if (v[ j−1] <= dato) {iLimite = j ;

}else {

v[ j ] = v[j−1];j = j −1;

}}v[ j ] = dato;// n > 0 AND esPermutacion(v,v0,0,n−1) AND ordenado(v,0,i)

}}

El codigo de este algoritmo se ha dispuesto tambien en el fichero algOrdenacion.h situado enla carpeta practica4 accesible desde la web de la asignatura y copiado previamente en el directorio(carpeta) programacion2/genericas del cluster hendrix-ssh.

Para analizar el coste del algoritmo de ordenacion de vectores por insercion se va realizar un trabajoanalogo al desarrollado con el algortimo de ordenacion de vectores por seleccion.

1. Se deben completar las Tablas 5 y 6 que se muestran a continuacion. Para la toma dedatos experimentales se recomienda desarrollar un nuevo programa, una variante del programamedirCoste puesto a punto en la practica 1a. El fichero con el codigo fuente del nuevo programase denominara medirCoste02.cc y se alamacenara en el cluster hendrix-ssh, en el directorio(carpeta) programacion2/practica4.

Conviene tener presente que las funciones de coste de este algoritmo, cuando se aplica a la ordenacionde n datos dispuestos en un vector ya ordenados desde el principio, tiene la forma t(n) = k × n.

En tales casos, el coste del algortimo de ordenacion por insercion es mucho menor. Por ello se va amedir para vectores con un mayor numero de datos, concretamente con 1.000.000 y 2.000.000

70

datos inicialmente ya ordenados. Las medidas de estos costes se expresaran en la Tabla 5 y en laTabla 6 en milisegundos [ms] y el valor del coeficiente k de cada una de estas funciones de coste seexpresara en picosegundos [ps]. Conviene recordar que 1ms = 10−3 s y que 1 ps = 10−12 s.

Los valores de los coeficientes k en cada caso, se deduciran a partir de los datos experimentales decoste para el mayor de los numeros de datos, es decir, para n = 2.000.000 datos.

2. Completar a continuacion las Tablas 7 y 8 en las que se comparan los costes del algorimo deordenacion de vectores por insercion deducidos a partir de las funciones de coste y los medidosde forma experimental para n = 25.000 datos (para los casos en que los datos estan dispuestosinicialmente de forma aleatoria) y para n = 1.000.000 datos (para los casos en que los datosestan dispuestos inicialmente ya ordenados).

3. Responder las preguntas que se plantean a continuacion, aportando las razones que justifican cadauna de las respuestas.

a) A la vista de los datos que muestra la Tabla 6, ¿cual es el nivel de optimizacion recomendablepara compilar codigo eficiente del algorimo de ordenacion de vectores por insercion? Justificarla respuesta.

b) A la vista de los datos que muestra la Tabla 8, ¿pueden considerarse validas las diferentesaproximaciones asintoticas t1(n) = k1 × n2 o, en su caso, t2(n) = k2 × n, a la funcion delcoste del algoritmo de ordenacion de vectores por insercion? Justificar la respuesta.

c) ¿Existen diferencias notables en cuanto a la eficiencia del algoritmo de ordenacion de vectorespor insercion segun sea la disposicion inicial de los datos en el vector? A la vista del codigo delalgoritmo, ¿cuales son las razones que sustentan la afirmacion anterior? Justificar las respuestas.

d) Estimar cuantos datos dispuestos aleatoriamente se podrıan ordenar ejecuando este algoritmo enel cluster hendrix-ssh en un tiempo maximo de una hora. Detallar los calculos realizados.

e) ¿Existe una diferencia sensible entre la eficiencia del algoritmo de ordenacion por seleccion yel de ordenacion por insercion? ¿En que circunstancias se presenta una mayor diferencia a favorde cualquiera de ellos? Justificar las respuestas.

f ) Cuantas veces son mas rapidos ejecutando este algoritmo de ordenacion los pc del Lab.0.04respecto del cluster hendrix-ssh.

ALGORITMO DE ORDENACION DE VECTORES POR INSERCIONTIPO DE LOS DATOS ALMACENADOS EN EL VECTOR: INTMAQUINA EN LA QUE SE EJECUTA: PC DEL LAB. 0.04SISTEMA OPERATIVO: UNIXCOMPILADOR UTILIZADO: G++

NIVEL Coste de ejecucion [en segundos, s] Coste de ejecucion [en milisegundos, ms]DE Datos dispuestos aleatoriamente Datos inicialmente ya ordenados

OPTIMIZACION n = 25.000 datos n = 50.000 datos n = 1.000.000 datos n = 2.000.000 datos0 s s ms ms2 s s ms ms

Determinacion de las funciones de coste en cada casoNIVEL Datos dispuestos aleatoriamente Datos inicialmente ya ordenados

DE Funcion de coste: t1(n) = k1.n2 Funcion de coste: t2(n) = k2.n

OPTIMIZACION Valor del coeficiente k1 [en ns] Valor del coeficiente k2 [en ps]0 ns ps2 ns ps

71

Tabla 5. Determinacion de las funciones de coste, en tiempo en uno de los pc del Lab.0.04,del algoritmo de ordenacion de vectores por insercion aplicado a datos enteros de tipo int dispuestosinicialmente de forma aleatoria o ya ordenados.

ALGORITMO DE ORDENACION DE VECTORES POR INSERCIONTIPO DE LOS DATOS ALMACENADOS EN EL VECTOR: INTMAQUINA EN LA QUE SE EJECUTA: CLUSTER HENDRIX-SSHSISTEMA OPERATIVO: UNIXCOMPILADOR UTILIZADO: G++

NIVEL Coste de ejecucion [en segundos, s] Coste de ejecucion [en milisegundos, ms]DE Datos dispuestos aleatoriamente Datos inicialmente ya ordenados

OPTIMIZACION n = 25.000 datos n = 50.000 datos n = 1.000.000 datos n = 2.000.000 datos0 s s ms ms2 s s ms ms

Determinacion de las funciones de coste en cada casoNIVEL Datos dispuestos aleatoriamente Datos inicialmente ya ordenados

DE Funcion de coste: t1(n) = k1.n2 Funcion de coste: t2(n) = k2.n

OPTIMIZACION Valor del coeficiente k1 [en ns] Valor del coeficiente k2 [en ps]0 ns ps2 ns ps

Tabla 6. Determinacion de las funciones de coste, en tiempo en el cluster hendrix-ssh, del algoritmode ordenacion de vectores por insercion aplicado a datos enteros de tipo int dispuestos inicialmente deforma aleatoria o ya ordenados.

ALGORITMO DE ORDENACION DE VECTORES POR INSERCIONTIPO DE LOS DATOS ALMACENADOS EN EL VECTOR: INTNUMERO DE DATOS A ORDENAR: 25.000 DISPUESTOS ALEATORIAMENTE Y 1.000.000 YA ORDENADOS

MAQUINA EN LA QUE SE EJECUTA: PC DEL LAB. 0.04SISTEMA OPERATIVO: UNIXCOMPILADOR UTILIZADO: G++DISPOSICION INICIAL DE LOS 25.000 DATOS EN EL VECTOR: DISPUESTOS ALEATORIAMENTE

NIVEL COSTE COSTE ERROR EN LA ERROR EN LA

DE EXPERIMENTAL ESTIMADO ESTIMACION ESTIMACION

OPTIMIZACION [segs.] [segs.] [segs.] {%}0 s s s %2 s s s %

DISPOSICION INICIAL DE LOS 1.000.000 DATOS EN EL VECTOR: INCIALMENTE YA ESTAN ORDENADOS

NIVEL COSTE COSTE ERROR EN LA ERROR EN LA

DE EXPERIMENTAL ESTIMADO ESTIMACION ESTIMACION

OPTIMIZACION [ms] [ms] [ms] [%]0 ms ms ms %2 ms ms ms %

error en la estimacion [segs.]: coste estimado - coste experimentalerror en la estimacion [ %]: 100.0 x (coste estimado - coste experimental) / coste experimental

Tabla 7. Comparacion entre el coste estimado a partir de las funciones de coste deducidas en la Tabla6 y el coste medido experimentalmente en uno de los pcs del lab. 0.04 para ordenar un vector con

72

25.000 datos de tipo int dispuestos aleatoriamente y para ordenar un vector con 1.000.000 datos de tipoint dispuestos ya ordenados.

ALGORITMO DE ORDENACION DE VECTORES POR INSERCIONTIPO DE LOS DATOS ALMACENADOS EN EL VECTOR: INTNUMERO DE DATOS A ORDENAR: 25.000 DISPUESTOS ALEATORIAMENTE Y 500.000 YA ORDENADOS

MAQUINA EN LA QUE SE EJECUTA: CLUSTER HENDRIXSISTEMA OPERATIVO: UNIXCOMPILADOR UTILIZADO: G++DISPOSICION INICIAL DE LOS 25.000 DATOS EN EL VECTOR: DISPUESTOS ALEATORIAMENTE

NIVEL COSTE COSTE ERROR EN LA ERROR EN LA

DE EXPERIMENTAL ESTIMADO ESTIMACION ESTIMACION

OPTIMIZACION [segs.] [segs.] [segs.] {%}0 s s s %2 s s s %

DISPOSICION INICIAL DE LOS 1.000.000 DATOS EN EL VECTOR: INCIALMENTE YA ESTAN ORDENADOS

NIVEL COSTE COSTE ERROR EN LA ERROR EN LA

DE EXPERIMENTAL ESTIMADO ESTIMACION ESTIMACION

OPTIMIZACION [ms] [ms] [ms] [%]0 ms ms ms %2 ms ms ms %

error en la estimacion [segs.]: coste estimado - coste experimentalerror en la estimacion [ %]: 100.0 x (coste estimado - coste experimental) / coste experimental

Tabla 8. Comparacion entre el coste estimado a partir de las funciones de coste deducidas en la Tabla5 y el coste medido experimentalmente en el cluster hendrix-ssh para ordenar un vector con 25.000datos de tipo int dispuestos aleatoriamente y para ordenar un vector con 1.000.000 datos de tipo intdispuestos ya ordenados.

73

4.4. Uso de scripts o guiones

Un script o guion es un archivo de texto plano que almacena una coleccion de ordenes dirigidas alsistema operativo. Los scripts o guiones son casi siempre interpretados.

El programa bash es un interprete de ordenes dirigidas a un sistema operativo unix o linux.

En esta practica vamos a utilizar scripts con ordenes dirigidas al interprete bash para facilitar lacompilacion y la ejecucion de los programas puestos a punto en la practica para medir experimentalmenteel coste de ejecutar algoritmos de ordenacion de vectores . La utilidad de ello es muy clara, teniendo encuenta la cantidad de veces que hay que compilar y ejecutar los mencionados programas.

A continuacion se muestra un primer script que permite compilar dos veces el programamedirCoste01.cc, cada una de ellas con un nivel de optimizacion diferente, y ejecutar dos veces cadauno de los programas ejecutables resultantes de cada compilacion. Los detalles sobre el funcionamiento yuso de este script se explicaran durante la sesion de practicas.

#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−# File : costes01 .sh# Author: profesores de Programacion 2# Date: enero 2017# Coms: ” script ” en bashshell (bash) para la ejecucion de algunos de# los experimentos requeridos en la practica 4# Modo de invocacion:# bash costes01 .sh# O bien, se puede invocar simplemente del modo:# ./ costes01 .sh# Pero para ello es necesario haber autorizado previamente su ejecucion# desde otras cuentas de usuarios :# chmod a+x costes01.sh#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

echoecho Compilando con nivel de optimizacion O0echo −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−g++ −o ordena0 medirCoste01.cc −O0./ ordena0 25000 100000 999999 hendrix./ ordena0 50000 100000 999999 hendrix

echoecho Compilando con nivel de optimizacion O2echo −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−g++ −o ordena2 medirCoste01.cc −O2./ ordena2 25000 100000 999999 hendrix./ ordena2 50000 100000 999999 hendrixecho

74

Un segundo script permite redireccionar todos los resultados generados por la ejecucion de losprogramas hacia un fichero de texto de nombre resultados01.txt y elimina finalmente los ficherosejecutables generados previamente.

#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−# File : costes02 .sh# Author: profesores de Programacion 2# Date: abril 2017# Coms: ” script ” en bashshell (bash) para la ejecucion de algunos de# los experimentos requeridos en la practica 4# Modo de invocacion:# bash costes02 .sh# O bien, se puede invocar simplemente del modo:# ./ costes02 .sh# Pero para ello es necesario haber autorizado previamente su ejecucion# desde otras cuentas de usuarios :# chmod a+x costes02.sh#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

# si ” resultados01 . txt ” existe , borrarloif [ −e ” ./ resultados01 . txt ” ] # borrarlo si existethen

/bin /rm ./ resultados01 . txtfi

# ahora creamos ” resultados01 . txt ” vacıotouch resultados01 . txt

echoecho Compilando con nivel de optimizacion O0echo −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−g++ medirCoste01.cc −o ordena0 −O0echo Ordenacion tras compilar con nivel de optimizacion O0 >> resultados01. txtecho Midiendo el coste de ordenar 25000 datos ..../ ordena0 25000 100000 999999 hendrix >> resultados01. txtecho Midiendo el coste de ordenar 50000 datos ..../ ordena0 50000 100000 999999 hendrix >> resultados01. txt

echoecho Compilando con nivel de optimizacion O2echo −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−g++ medirCoste01.cc −o ordena2 −O2echo Ordenacion tras compilar con nivel de optimizacion O2 >> resultados01. txtecho Midiendo el coste de ordenar 25000 datos ..../ ordena2 25000 100000 999999 hendrix >> resultados01. txtecho Midiendo el coste de ordenar 50000 datos ..../ ordena2 50000 100000 999999 hendrix >> resultados01. txt

# elimina los ficheros ejecutables generadosrm ordena0 ordena2

echoecho Ha eliminado los ficheros ejecutables generadosecho Resultados almacenados en el fichero resultados01 . txtecho

75

4.5. Resultados del trabajo desarrollado en las cinco practicas de laasignatura

Como resultado de las cinco practicas de la asignatura, cada alumno dispondra en su cuentahendrix-ssh de un directorio (carpeta) denominado programacion2 dentro del cual se podranencontrar los directorios (carpetas) y ficheros que se detallan a continuacion.

1. Directorio (carpeta) programacion2/practica1 con los siguientes ficheros:

Fichero tiempoReaccion.cc con el codigo C++ del primer programa de la practica 1a.

Fichero generarTabla01.cc con el codigo C++ del segundo programa de la practica 1a.

Fichero generarTabla02.cc con el codigo C++ del tercer programa de la practica 1a.

Fichero medirCoste.cc con el codigo C++ del cuarto programa de la practica 1a.

2. Directorio (carpeta) programacion2/practica2 con los siguientes ficheros:

Ficheros de interfaz y de implementacion, calculos.h y calculos.cc, con el codigoC++ del modulo calculos de la practica 2a.

Fichero funcionesPilas.h de la practica 2a con el codigo C++ de una coleccion defunciones genericas, programadas sin bucles, sin aplicar tecnicas de inmersion y sin funcionesauxiliares, que ejecutan operaciones con pilas de datos, definidas a partir del tipo genericoPila, de un nivel superior al de las funciones genericas basicas del fichero pila.h.

Ficheros con los programas de prueba (pruebas01.cc, pruebas02.cc, etc.) que se hayan puestoa punto para realizar pruebas de los desarrollos anteriores.

3. Directorio (carpeta) programacion2/practica3 con los siguientes ficheros:

Fichero gestor.cc con el codigo C++ del modulo principal del programa propuesto en lapractica 3a.

Fichero makefile para facilitar la compilacion del programa propuesto en la practica 3a.

4. Directorio (carpeta) programacion2/practica4 con los siguientes ficheros:

Fichero medirCoste01.cc con el codigo C++ de un programa que servira para medirexperimentalmente el coste de ejecutar el algoritmo de ordenacion de vectores aplicando elmetodo de ordenacion interna por seleccion.

Fichero medirCoste02.cc con el codigo C++ de un programa que servira para medirexperimentalmente el coste de ejecutar el algoritmo de ordenacion de vectores aplicando elmetodo de ordenacion interna por insercion.

5. Directorio (carpeta) programacion2/genericas con los siguientes ficheros:

Fichero pila.h con el codigo C++ desarrollado en la practica 2a en el que se representa eltipo generico Pila junto con una coleccion de seis funciones genericas basicas para trabajarcon pilas de datos definidas a partir del tipo Pila.

Fichero cola.h con el codigo C++ desarrollado en la practica 3a en el que se representa eltipo generico Cola junto con una coleccion de seis funciones genericas basicas para trabajarcon colas de datos definidas a partir del tipo Pila.

Fichero algOrdenacion.h con el codigo de varios algoritmos para la ordenacion devectores o tablas de elementos de un tipo generico.

76

6. Directorio (carpeta) programacion2/tipos con los siguientes ficheros:

Ficheros fecha.h y fecha.cc de interfaz y de implementacion, respectivamente, delmodulo de biblioteca fecha.

Ficheros nif.h y nif.cc de interfaz y de implementacion, respectivamente, del modulo debiblioteca nif.

Ficheros persona.h y persona.cc de interfaz y de implementacion, respectivamente, delmodulo de biblioteca persona.

77

Capıtulo 5

Practica 5: Diseno de algoritmos deordenacion de matrices

5.1. Objetivos de la practica

El principal objetivo de esta practica es profundizar en el conocimiento de dos algoritmos de ordenacionde estructuras de datos indexadas que se presentan en la ultima leccion del curso. Se trata del algoritmo deordenacion por insercion y del algoritmo de ordenacion rapida, tambien conocido comoquicksort.

En esta practica se van a aplicar ambos algoritmos a la ordenacion de los datos de una matriz cuadrada.Para reforzar el aprendizaje sobre diseno recursivo, el codigo de las dos funciones de ordenacion de matricesa disenar va a estar libre de bucles.

5.1.1. Calendario de esta practica

El trabajo de esta quinta practica debe comenzar inmediatamente despues de concluida la practica cuarta.

La sexta sesion de practicas (programada en la segunda quincena de mayo) debe servir para resolverdudas y concluir el trabajo propuesto en ella.

5.2. Trabajo a desarrollar

En esta practica se han de disenar dos algoritmos genericos que tienen como objetivo la ordenacion, demenor a mayor valor, de los elementos almacenados en una matriz de dimension DIM ×DIM .

Se va a optar por especificar los diferentes algoritmos mediante especificaciones no formales y no, porello, menos riguras. En el comentario que precede a la especificacion de cada una de las funciones a disenarse precisa el significado de algunas de las frases que se utilizan al especificar el comportamiento de lasdiferentes funciones que integran el diseno:

Se explica que en una matriz cuadrada, M, de dimension DIM × DIM vamos a considerar que suprimer elemento es el M[0][0], que su segundo elemento es el M[0][1] y, ası sucesivamente, y quesu ultimo elemento es el M[DIM-1][DIM-1]. De esta forma, consideraremos que cualquier elementode la fila i-esima precede (es anterior) a cualquier elemento de la fila (i+1)-esima y, dentro de una

78

misma fila, el elemento j-esimo de la fila precede (es anterior) al elemento (j+1)-esimo de la mismafila.

Se explica que un matriz cuadrada, M, esta ordenada de menor a mayor valor si el valor de un elementoque precede a otro es siempre igual o menor que el valor de este.

Y se explica tambien que, dadas dos matrices cuadradas, A y M, de dimension finita DIM ×DIM ,diremos que ambas matrices almacenan una permutacion de los datos de la otra y viceversa si, paracualquier elemento de la matriz A, el numero de veces que esta repetido este elemento en A es igualal numero de veces que esta repetido en M y viceversa.

En la carpeta practica5 accesible desde la web de la asignatura se han dispuesto los ficherospruebasInsercion.cc y pruebasQuickSort.cc para facilitar la realizacion de pruebas de lasdos funciones que se han de disenar. Cada uno de esos ficheros contiene la especificacion de la funcion deordenacion de matrices que debe ser disenada y probada. Estas funciones se presentan a continuacion.

5.2.1. Algoritmo de ordenacion de una matriz cuadrada por intercambio de sus elementos

La especificacion de la primera de la funciones a disenar, la funcion insercion(M), se especificaa continuacion. Se recuerda que en su codigo no puede haber bucles, ni puede haberlos en el codigode sus funciones auxiliares. El diseno algorıtmico de esta funcion debe consistir en una traslacionfiel del algoritmo de ordenacion de vectores por el metodo de insercion. Noesta permitida la definicion de estructuras de datos auxiliares, tales como vectores, matrices o ficheros,en las que copiar los datos a ordenar.

/∗∗ Dimension de las matrices ( definir de forma que DIM > 0)∗/

const int DIM = ... ;

/∗∗ Sea M una matriz cuadrada de dimension DIMxDIM. Con relacion a la ubicacion de∗ sus DIMˆ2 elementos, diremos que su primer elemento es el M[0][0], su segundo∗ elemento es el M[0][1] y, ası sucesivamente , su ultimo elemento es el M[DIM−1][DIM−1].∗ De esta forma, cualquier elemento de la fila i−esima precede (es anterior ) a cualquier∗ elemento de la fila ( i+1)−esima y, dentro de una misma fila , el elemento j−esimo de∗ la fila precede (es anterior ) al elemento ( j+1)−esimo de la misma fila .∗∗ Sea M una matriz cuadrada de dimension DIMxDIM. Diremos que la matriz M esta∗ ordenada de menor a mayor valor si el valor de un elemento que precede a otro∗ es siempre igual o menor que el valor de este .∗∗ Sean A y M dos matrices cuadradas de dimension finita DIMxDIM. Diremos que ambas∗ matrices almacenan una permutacion de los datos de la otra y viceversa si , para∗ cualquier elemento de la matriz A, el numero de veces que esta repetido este∗ elemento en A es igual al numero de veces que esta repetido en M.∗/

/∗∗ Pre: M = A, siendo matrices cuadradas de dimension DIMxDIM∗ Post : Los elementos de M son una permutacion de los elementos de A y∗ los elementos comprendidos entre el M[0][0] y el M[DIM−1][DIM−1]∗ estan ordenados de menor a mayor valor∗/

template <typename T>

79

void insercion (T M[][DIM]) {// Ordena los elementos de la matriz M aplicando el algoritmo de ordenacion// por insercion. . .

}

5.2.2. Algoritmo de ordenacion rapida (quicksort) de los elementos de una matrizcuadrada

La especificacion de la primera de la funciones a disenar, la funcion quicksort(M), se especificaa continuacion. Se recuerda que en su codigo no puede haber bucles, ni puede haberlos en el codigo desus funciones auxiliares. El diseno algorıtmico de esta funcion debe consistir en una traslacion fiel delalgoritmo de ordenacion rapida de vectores, tambien conocido como quicksort. Noesta permitida la definicion de estructuras de datos auxiliares, tales como vectores, matrices o ficheros, enlas que copiar los datos a ordenar.

/∗∗ Dimension de las matrices ( definir de forma que DIM > 0)∗/

const int DIM = ... ;

/∗∗ Sea M una matriz cuadrada de dimension DIMxDIM. Con relacion a la ubicacion de∗ sus DIMˆ2 elementos, diremos que su primer elemento es el M[0][0], su segundo∗ elemento es el M[0][1] y, ası sucesivamente , su ultimo elemento es el M[DIM−1][DIM−1].∗ De esta forma, cualquier elemento de la fila i−esima precede (es anterior ) a cualquier∗ elemento de la fima ( i+1)−esima y, dentro de una misma fila , el elemento j−esimo de∗ la fila precede (es anterior ) al elemento ( j+1)−esimo de la misma fila .∗∗ Sea M una matriz cuadrada de dimension DIMxDIM. Diremos que la matriz M esta∗ ordenada de menor a mayor valor si el valor de un elemento que precede a otro∗ es siempre igual o menor que el valor de este .∗∗ Sean A y M dos matrices cuadradas de dimension finita DIMxDIM. Diremos que ambas∗ matrices almacenan una permutacion de los datos de la otra y viceversa si , para∗ cualquier elemento de la matriz A, el numero de veces que esta repetido este∗ elemento en A es igual al numero de veces que esta repetido en M.∗/

/∗∗ Pre: M = A, siendo matrices cuadradas de dimension DIMxDIM∗ Post : Los elementos de M son una permutacion de los elementos de A y∗ los elementos comprendidos entre el M[0][0] y el M[DIM−1][DIM−1]∗ estan ordenados de menor a mayor valor∗/

template <typename T>void quicksort (T M[][DIM]) {

// Ordena los elementos de la matriz M aplicando un algoritmo de ordenacion// rapida o quicksort. . .

}

80

5.3. Resultados del trabajo desarrollado en las cinco practicas de laasignatura

Como resultado de las cinco practicas de la asignatura, cada alumno dispondra en su cuentahendrix-ssh de un directorio (carpeta) denominado programacion2 dentro del cual se podranencontrar los directorios (carpetas) y ficheros que se detallan a continuacion.

1. Directorio (carpeta) programacion2/practica1 con los siguientes ficheros:

Fichero tiempoReaccion.cc con el codigo C++ del primer programa de la practica 1a.

Fichero generarTabla01.cc con el codigo C++ del segundo programa de la practica 1a.

Fichero generarTabla02.cc con el codigo C++ del tercer programa de la practica 1a.

Fichero medirCoste.cc con el codigo C++ del cuarto programa de la practica 1a.

2. Directorio (carpeta) programacion2/practica2 con los siguientes ficheros:

Ficheros de interfaz y de implementacion, calculos.h y calculos.cc, con el codigoC++ del modulo calculos de la practica 2a.

Fichero funcionesPilas.h de la practica 2a con el codigo C++ de una coleccion defunciones genericas, programadas sin bucles, sin aplicar tecnicas de inmersion y sin funcionesauxiliares, que ejecutan operaciones con pilas de datos, definidas a partir del tipo genericoPila, de un nivel superior al de las funciones genericas basicas del fichero pila.h.

Ficheros con los programas de prueba (pruebas01.cc, pruebas02.cc, etc.) que se hayan puestoa punto para realizar pruebas de los desarrollos anteriores.

3. Directorio (carpeta) programacion2/practica3 con los siguientes ficheros:

Fichero gestor.cc con el codigo C++ del modulo principal del programa propuesto en lapractica 3a.

Fichero makefile para facilitar la compilacion del programa propuesto en la practica 3a.

4. Directorio (carpeta) programacion2/practica4 con los siguientes ficheros:

Fichero medirCoste01.cc con el codigo C++ de un programa que servira para medirexperimentalmente el coste de ejecutar el algoritmo de ordenacion de vectores aplicando elmetodo de ordenacion interna por seleccion.

Fichero medirCoste02.cc con el codigo C++ de un programa que servira para medirexperimentalmente el coste de ejecutar el algoritmo de ordenacion de vectores aplicando elmetodo de ordenacion interna por insercion.

5. Directorio (carpeta) programacion2/practica5 con los siguientes ficheros:

Fichero pruebaInsercion.cc con el codigo C++ del primero de los programas propuestosen la practica 5a.

Fichero pruebaQuickSort.cc con el codigo C++ del segundo de los programas propuestosen la practica 5a.

6. Directorio (carpeta) programacion2/genericas con los siguientes ficheros:

81

Fichero pila.h con el codigo C++ desarrollado en la practica 2a en el que se representa eltipo generico Pila junto con una coleccion de seis funciones genericas basicas para trabajarcon pilas de datos definidas a partir del tipo Pila.

Fichero cola.h con el codigo C++ desarrollado en la practica 3a en el que se representa eltipo generico Cola junto con una coleccion de seis funciones genericas basicas para trabajarcon colas de datos definidas a partir del tipo Pila.

Fichero algOrdenacion.h con el codigo de varios algoritmos para la ordenacion devectores o tablas de elementos de un tipo generico.

7. Directorio (carpeta) programacion2/tipos con los siguientes ficheros:

Ficheros fecha.h y fecha.cc de interfaz y de implementacion, respectivamente, delmodulo de biblioteca fecha.

Ficheros nif.h y nif.cc de interfaz y de implementacion, respectivamente, del modulo debiblioteca nif.

Ficheros persona.h y persona.cc de interfaz y de implementacion, respectivamente, delmodulo de biblioteca persona.

82