26
05 En esta unidad aprenderás a: Comprender la justificación de la programación estructurada Conocer en qué consiste la programación estructurada Utilizar la la programación estructurada en el diseño de aplicaciones Mantener mejor las aplicaciones Programación estructurada

Prog Estructurada

Embed Size (px)

Citation preview

  • 05

    En esta unidad aprenders a:

    Comprender la justificacinde la programacinestructurada

    Conocer en qu consistela programacin estructurada

    Utilizar la la programacinestructurada en el diseode aplicaciones

    Mantener mejor las aplicaciones

    Programacin estructurada

  • La visin clsica de la programacin estructurada se refiere al control de ejecucin. Elcontrol de su ejecucin es una de las cuestiones ms importantes que hay que tener encuenta al construir un programa en un lenguaje de alto nivel. La regla general es quelas instrucciones se ejecuten sucesivamente una tras otra, pero diversas partes del pro-grama se ejecutan o no dependiendo de que se cumpla alguna condicin. Adems, hayinstrucciones (los bucles) que deben ejecutarse varias veces, ya sea en nmero fijo ohasta que se cumpla una condicin determinada.

    Sin embargo, algunos lenguajes de programacin ms antiguos (como Fortran) se apo-yaban en una sola instruccin para modificar la secuencia de ejecucin de las instruc-ciones mediante una transferencia incondicional de su control (con la instruccin goto,del ingls "go to", que significa "ir a"). Pero estas transferencias arbitrarias del con-trol de ejecucin hacen los programas muy poco legibles y difciles de comprender. Afinales de los aos sesenta, surgi una nueva forma de programar que reduce a lamnima expresin el uso de la instruccin goto y la sustituye por otras ms compren-sibles.

    Esta forma de programar se basa en un famoso teorema, desarrollado por Edsger Dijks-tra, que demuestra que todo programa puede escribirse utilizando nicamente las tresestructuras bsicas de control siguientes:

    Secuencia: el bloque secuencial de instrucciones, instrucciones ejecutadas sucesi-vamente, una detrs de otra.

    Seleccin: la instruccin condicional con doble alternativa, de la forma "if condi-cin then instruccin-1 else instruccin-2".

    Iteracin: el bucle condicional "while condicin do instruccin", que ejecuta la ins-truccin repetidamente mientras la condicin se cumpla.

    Los programas que utilizan slo estas tres instrucciones de control bsicas o sus varian-tes (como los bucles for, repeat o la instruccin condicional switch-case), pero no la ins-truccin goto, se llaman estructurados.

    sta es la nocin clsica de lo que se entiende por programacin estructurada (llamadatambin programacin sin goto) que hasta la aparicin de la programacin orientadaa objetos se convirti en la forma de programar ms extendida. Esta ltima se enfocahacia la reduccin de la cantidad de estructuras de control para reemplazarlas por otroselementos que hacen uso del concepto de polimorfismo. Aun as los programadores toda-va utilizan las estructuras de control (if, while, for, etc.) para implementar sus algorit-mos porque en muchos casos es la forma ms natural de hacerlo.

    Una caracterstica importante en un programa estructurado es que puede ser ledo ensecuencia, desde el comienzo hasta el final sin perder la continuidad de la tarea que

    5. Programacin estructurada5.1 La visin clsica de la programacin estructurada

    119

    5.1 La visin clsicade la programacin estructurada:la programacin sin goto

  • cumple el programa, lo contrario de lo que ocurre con otros estilos de programacin.Este hecho es importante debido a que es mucho ms fcil comprender completa-mente el trabajo que realiza una funcin determinada si todas las instrucciones queinfluyen en su accin estn fsicamente contiguas y encerradas por un bloque. Lafacilidad de lectura, de comienzo a fin, es una consecuencia de utilizar solamentetres estructuras de control, y de eliminar la instruccin de transferencia de controlgoto.

    La realizacin de un programa sin seguir una tcnica de programacin produce frecuen-temente un conjunto enorme de sentencias cuya ejecucin es compleja de seguir, y deentender, pudiendo hacer casi imposible la depuracin de errores y la introduccin demejoras. Se puede incluso llegar al caso de tener que abandonar el cdigo preexistenteporque resulte ms fcil empezar de nuevo.

    Cuando en la actualidad se habla de programacin estructurada, nos solemos referir a ladivisin de un programa en partes ms manejables (usualmente denominadas segmen-tos o mdulos). Una regla prctica para lograr este propsito es establecer que cadasegmento del programa no exceda, en longitud, de una pgina de codificacin, o sea,alrededor de 50 lneas.

    As, la visin moderna de un programa estructurado es un compuesto de segmentos, loscuales puedan estar constituidos por unas pocas instrucciones o por una pgina o msde cdigo. Cada segmento tiene solamente una entrada y una salida, asumiendo que noposeen bucles infinitos y no tienen instrucciones que jamas se ejecuten. Encontramosla relacin entre ambas visiones en el hecho de que los segmentos se combinan utili-zando las tres estructuras bsicas de control mencionadas anteriormente y, por tanto,el resultado es tambin un programa estructurado.

    Cada una de estas partes englobar funciones y datos ntimamente relacionados semn-tica o funcionalmente. En una correcta particin del programa deber resultar fcil eintuitivo comprender lo que debe hacer cada mdulo.

    En una segmentacin bien realizada, la comunicacin entre segmentos se lleva a cabo deuna manera cuidadosamente controlada. As, una correcta particin del problema produ-cir una nula o casi nula dependencia entre los mdulos, pudindose entonces trabajarcon cada uno de estos mdulos de forma independiente. Este hecho garantizar que loscambios que se efecten a una parte del programa, durante la programacin original o sumantenimiento, no afecten al resto del programa que no ha sufrido cambios.

    Esta tcnica de programacin conlleva las siguientes ventajas:

    a) El coste de resolver varios subproblemas de forma aislada es con frecuencia menorque el de abordar el problema global.

    5. Programacin estructurada5.2 La visin moderna de la programacin estructurada

    120

    5.2 La visin modernade la programacin estructurada:

    la segmentacin

  • b) Facilita el trabajo simultneo en paralelo de distintos grupos de programadores.

    c) Posibilita en mayor grado la reutilizacin del cdigo (especialmente de alguno delos mdulos) en futuras aplicaciones.

    Aunque no puede fijarse de antemano el nmero y tamao de estos mdulos, debe inten-tarse un compromiso entre ambos factores. Si nos encontramos ante un mdulo con untamao excesivo, podremos dividir ste a su vez en partes (nuevos mdulos) ms mane-jables, producindose la sucesiva divisin siempre desde problemas generales a proble-mas cada vez menos ambiciosos y, por tanto, de fcil desarrollo y seguimiento. As, estadivisin toma la forma de un rbol cuya raz es el programa principal que implementa lasolucin al problema que afrontamos utilizando uno o varios mdulos que realizan par-tes de dicha solucin por s solos o invocando a su vez otros mdulos que solucionansubproblemas ms especficos. A esta aproximacin se la denomina diseo descendenteo top-down, como queda esquematizado en la siguiente figura:

    Fig. 5.1. Diseo descendente.

    El carcter autocontenido de los mdulos o libreras hace que pueda ocultarse el fun-cionamiento interno de las funciones contenidas en un mdulo, ya que para utilizarlasbasta con saber con qu nombre y argumentos se invocan y qu tipo de valores devuel-ven. Al reunirlas en un mdulo, se realza la relacin entre las mismas separndolas delresto del programa.

    Esta ocultacin de los detalles se denomina encapsulacin y se alcanza dividiendo elcdigo del programa en dos ficheros diferenciados: un fichero (con extensin ".h") queincluye la declaracin de los tipos de datos y de las funciones gracias a lo cual se sabecmo acceder y utilizar cada una de las mismas y otro (con extensin ".c") que contieneel cdigo de cada una de las funciones declaradas en el .h.

    Al compilar este ltimo queda transformado en cdigo objeto (al cual ya no se puedeacceder para su lectura o modificacin) y puede distribuirse conjuntamente con elfichero de declaracin (el que acaba en .h), para su uso por parte de terceros sin riesgoalguno de alteracin de la funcionalidad original (sta qued encapsulada u oculta).

    Esto es as porque para hacer uso de las funciones incluidas en el mdulo nicamentenecesitaremos conocer la informacin que nos proporciona el fichero de declaracin: elnombre, tipos de datos de los argumentos y valores de retorno de las funciones. No esnecesario conocer los detalles de implementacin (sentencias que se ejecutan dentrode una funcin).

    5. Programacin estructurada5.2 La visin moderna de la programacin estructurada

    121

  • 5. Programacin estructurada5.2 La visin moderna de la programacin estructurada

    122

    Supongamos que queremos desarrollar una aplicacin para que dos usuarios jueguen al ajedrez. En primer lugar, necesi-tamos una serie de funciones asociadas al tablero: una que coloque todas las piezas de ambos jugadores en las posicio-nes iniciales, otra que determine si se ha producido el final de la partida, otra que confirme la presencia de una piezadel jugador en juego en una determinada casilla, otra que confirme que el movimiento no se sale del tablero, o que esetipo de pieza puede realizarlo, y una ltima que lleve a efecto el movimiento de una pieza del jugador en juego (elimi-nando del tablero a otra pieza del jugador contrario si procede). Para estas ltimas puede ser preciso utilizar a su vezotro mdulo que represente las funciones de movimiento asociadas a cada tipo de pieza.

    La descomposicin en mdulos del programa quedara:

    Fig. 5.2. Descomposicin del programa en mdulos.

    As, el contenido del fichero de libreratablero.h sera:

    enum columnas { a, b, c, d, e, f, g, h };struct tablero {

    int posx;enum columnas posy;struct pieza mipieza;struct tablero *siguiente;

    }

    int Final(struct tablero *mitablero);void Inicio(struct tablero *mitablero);int Pertenece(struct tablero *mitablero, int posx, enum columnas posy);void Dibuja(struct tablero *mitablero);int FueraTablero(struct tablero *mitablero, int x1, enum columnas y1, int x2, enumcolumnas y2);int Valido_T(struct tablero *mitablero, int x1, enum columnas y1, int x2, enum columnas y2);

    void Mover(struct tablero *mitablero, int x1, enum columnas y1, int x2, enum columnas y2);

    Ajedrez

    Tablero

    Pieza

    1

    Ejemplo prctico

  • Evidentemente, desde el cdigo que haga uso de alguna de las citadas funciones de la libre-ra, hemos de invocar los ficheros de declaracin correspondientes. Para ello, utilizaremosla directiva de C include, tal y como hacamos para utilizar las funciones de entrada/salidacon stdio.h o las de cadenas de caracteres con strong.h, slo que cambiaremos los smbo-los < y > por dobles comillas ", por no tratarse de una librera estndar, sino creada por elpropio programador y cuya ubicacin, por tanto, no es la del directorio que alberga dichaslibreras, en la cual el compilador busca por defecto, sino la especificada entre doblescomillas. En caso de no especificarse ninguna ruta dentro de las dobles comillas, sera bus-cada en el directorio actual. Por tanto, podemos indicar que esta tcnica persigue obte-ner una descomposicin en forma de rbol que permita el fraccionamiento del programaen mdulos que resulten fciles de entender, desarrollar, probar y mantener, y que agru-pen las funciones y datos que estn estrechamente relacionadas entre s.

    5. Programacin estructurada5.2 La visin moderna de la programacin estructurada

    123

    As, el fichero de declaracin pieza.h incluira el siguiente cdigo:

    enum color { blanco, negro };enum tipo { peon, torre, caballo, alfil, reina, rey }struct pieza {

    enum color micolor;enum tipo mitipo;

    }int Valido_P(struct pieza *mipieza, int x1, int y1, int x2, int y2);

    De esta forma, con el conocimiento pblico de ambos ficheros de declaracin (tablero.h, pieza.h) podremos hacer uso de lasfunciones de los mdulos tablero y pieza declaradas en estos ficheros, a pesar de nuestra ignorancia completa de cmo fue-ron implementadas. Lo ignoramos, ya que no tenemos acceso a los ficheros de implementacin o cdigo fuente (tablero.c,pieza.c); nicamente disponemos del cdigo objeto (ablero.o, pieza.o) para su ejecucin posterior.

    El siguiente programa implementa apertura de ajedrez Amar:

    #include "tablero.h"main(){

    struct tablero mipartida;Inicio(&mipartida);Mover(&mipartida, b, 1, a, 3);Dibuja(&mipartida);

    }

    Al igual que las funciones Mover y Valido de la librera o mdulo tablero invocan a una funcin del mdulo pieza, el cdigode la primera debe incluir el fichero de declaracin de la segunda:

    #include "pieza.h"

    2

    Ejemplo prctico

  • Debido a que una forma habitual de realizar la particin en mdulos consiste en agru-par las funciones que permiten operar con un determinado conjunto (o estructura) dedatos, existe una analoga evidente con la programacin orientada a objetos. De hecho,sta puede verse como la continuacin lgica de aqulla. As pues, realizaremos unacomparacin entre ambas tcnicas de programacin, resaltando las semejanzas existen-tes entre ellas.

    La mente humana utiliza patrones o modelos que faciliten la comprensin del complejomundo real. As, estos patrones mentales de comportamiento abstraen aquellas carac-tersticas de un elemento o situacin necesarias para su comprensin ignorando losdetalles que resulten irrelevantes. Este proceso es conocido como abstraccin y resultaesencial en el razonamiento humano, ya que gracias a l podemos manejar sistemas degran complejidad.

    La abstraccin ha sido un aspecto clave de la programacin desde sus comienzos. Alprincipio, los programadores enviaban instrucciones binarias a los ordenadores. Poste-riormente, se emple el lenguaje ensamblador, que no es ms que el resultado de unproceso de abstraccin del cdigo mquina y que nos permite representar secuenciasde bits por smbolos ms inteligibles e intuitivos denominados nemotcnicos.

    El siguiente nivel de abstraccin se alcanz cuando se crearon las instrucciones defini-das por el usuario, las macroinstrucciones que abstraan a las propias instrucciones. Enun proceso de mayor abstraccin surgieron los lenguajes de alto nivel (como Fortran, C,Pascal, Cobol, etc.), que evitan al programador tener que pelearse con el tan denostadocdigo mquina.

    La programacin estructurada y la orientacin a objetos constituyen los pasos fina-les de este camino, ya que permiten a los programadores escribir cdigo sin necesidadde conocer los detalles de la implementacin de funciones de una librera y objetos res-pectivamente. Su implementacin permanece oculta a los programadores, liberndolesde los condicionantes que esto impona.

    De ese modo, un programador no necesita saber cmo se representan internamentelos datos de un tablero de ajedrez. Tan slo necesitar saber cmo mover, iniciar unapartida o validar un determinado movimiento.

    Lo realmente complicado de ambos paradigmas de programacin es encontrar losmodelos o patrones conceptuales correctos para el problema y no la implementacinde los mismos. Realmente, el diseo adquiere la mxima importancia que no tena enla programacin tradicional.

    La propuesta de la moderna programacin estructurada y de la orientacin a objetosconsiste principalmente en intentar superar la complejidad inherente a los proble-mas del mundo real gracias a la abstraccin de nuestro conocimiento sobre tales pro-blemas y su encapsulacin dentro de mdulos o libreras y objetos respectivamente. Se utiliza el trmino encapsular porque los objetos y las libreras pueden verse como "cp-

    5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    124

    5.3 Programacin estructuraday orientacin a objetos

  • sulas" a modo de barrera conceptual que separa un conjunto de valores y operaciones, queposeen un substrato conceptual idntico, del resto del sistema. As, en el ejemplo nmero2 hemos encapsulado los datos del tablero (piezas y posiciones) y las operaciones (iniciar,mover, validar y dibujar) dentro de la misma barrera conceptual que ha surgido de la abs-traccin de la idea de tablero. As, tanto objetos como libreras tienen dos partes bien dife-renciadas: la declaracin y la implementacin. La declaracin o interfaz es de dominiopblico, conocido por las dems partes del programa. En la implementacin se explicitany codifican los elementos necesarios para responder a lo especificado en la declaracin.Esta separacin permite que cada objeto definido en nuestro sistema pueda ocultar suimplementacin y hacer pblica su interfaz de comunicacin.

    La ocultacin de la informacin permite aislar una parte del programa del resto, y queel cdigo de una parte sea revisado o extendido sin afectar a la integridad de las demspartes.

    En este sentido, es interesante resaltar que la opcin de encapsular datos y operacionesen libreras y objetos facilita enormemente que se puedan utilizar en una aplicacin ajena.Se puede, por tanto, empezar a hablar de una relacin consumidor/proveedor de cdigo.La programacin convencional daba ms importancia a la relacin entre el programadory su cdigo, que a la relacin entre el cdigo y las aplicaciones en que se usa.

    El proceso de construccin del software resultante de aplicar las dos propiedades yacomentadas anteriormente sera:

    1. Gracias a la abstraccin se agruparn funcionalidad e informacin en partes diferen-ciadas. El sistema estar constituido entonces por partes que se invocan entre s.

    2. A continuacin, se definir una interfaz pblica que permite la utilizacin de cadaparte del sistema, manteniendo oculta la implementacin en el interior de ella.

    Resumiendo las analogas existentes entre ambas tcnicas de programacin, se puededecir que la abstraccin facilita la comprensin de la divisin de un programa en partesy la encapsulacin permite aislar la implementacin de cada una de las partes, aumen-tando la estabilidad y reutilizacin del cdigo.

    En las unidades siguientes, seguiremos esta idea de asociar la programacin estructu-rada a la orientacin a objetos relacionando cada mdulo/librera con las operaciones arealizar sobre una estructura de datos.

    En el ejemplo prctico 3 vamos a ver una aplicacin de la programacin estructurada ala gestin de los productos que pone a la venta un determinado comercio. Estos produc-tos podrn ser tanto libros como pelculas en DVD.

    5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    125

    En la aplicacin contaremos con un mdulo para realizar operaciones con artculos, como dar de alta y de baja un pro-ducto, visualizarlos en pantalla, vender un determinado nmero de ejemplares o reponer stock de ese producto. La estruc-tura de los datos correspondientes a un producto de dicho comercio sera:

    3

    Ejemplo prctico

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    126

    struct articulo{

    char cod_art[10];float precio;unsigned int existencias;

    };

    Tambin contaremos con estructuras que agrupen la informacin relativa a los libros por un lado y a las pelculas por otro,de forma que pueda consultarse el cdigo de producto por el autor de un libro, el director de una pelcula o por sus nombres,as como dar de alta y de baja los libros y pelculas. Por ejemplo, las estructuras libro y DVD podran ser:

    enum genero { historica, intriga, rosa, viaje, autoayuda, aventuras, ensayo };struct libro{

    char cod_art[10];char titulo[20];char autores[30];char editorial[10];enum genero migenero;

    };struct DVD{

    char cod_art[10];char titulo[20];char director[10];char actores[30];int ao;

    };

    As, la nica relacin entre la estructura articulo y la descripcin del mismo en la estructura libro o DVD es el mismo valor delcampo cod_art. De esta forma, es el programa principal el que se encarga de relacionarlos. La estructura en forma de rbolde las libreras de nuestra aplicacin quedara de la siguiente forma:

    Fig. 5.3. Estructura de rbol de la aplicacin.

    Tienda

    Libro Artculo DVD

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    127

    Se podra haber optado por incluir un campo en la estructura de tipo articulo que se correspondiera con los datos del libro oDVD. As descargamos al programa principal de la responsabilidad de relacionar ambas estructuras mediante el cdigo delartculo y podramos mostrar la informacin sobre el precio y stock junto con los detalles del libro o DVD, o dar de alta/bajasimultneamente a la estructura articulo y al libro/DVD. La estructura articulo resultante sera:

    enum tipo { libro, DVD };union descripcion {

    struct libro milibro;struct DVD miDVD;

    };struct articulo{

    enum tipo mitipo;union descripcion midescripcion;float precio;unsigned int existencias;

    };

    Y entonces la jerarqua de las libreras de nuestra aplicacin sera completamente diferente:

    Fig. 5.4. Jerarqua de las libreras de la aplicacin.

    A partir de ahora supondremos que, en este ejemplo, optamos por la primera de las dos asociaciones posibles: artculos ylibros/dvd. Empezaremos por definir el archivo de declaracin articulo.h con la estructura articulo y la cabecera de las funcio-nes que implementa:

    struct articulo{

    char cod_art[10];float precio;unsigned int existencias;

    };

    Tienda

    Artculo

    DVDLibro

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    128

    float Vender( struct articulo *ar, int cantidad );struct articulo Alta(long int codigo, float euros, unsigned int cantidad );void Visualizar(struct articulo *ar );void Reponer(struct articulo *ar, int cantidad );

    La correspondiente implementacin de estas funciones en el fichero articulo.c quedara:

    #include #include #include "articulo.h"

    struct articulo Alta(char *codigo, float euros, unsigned int cantidad ){

    struct articulo ar;ar.cod_art[0] = codigo;ar.precio = euros;ar.existencias = cantidad;return ar;

    }void Visualizar(struct articulo *ar ){

    printf("Cdigo del artculo: %s\n", ar->cod_art);printf("Precio del artculo: %f\n", ar->precio);printf("Existencias del artculo: %d\n", ar->existencias);

    }float Vender( struct articulo *ar, int cantidad ){

    ar->existencias= ar->existencias-cantidad;return (cantidad*ar->precio);

    }void Reponer(struct articulo *ar, int cantidad ){

    ar->existencias= ar->existencias+cantidad;}

    A partir de esta librera bsica de funciones podemos implementar nuevos procedimientos que den mayores funcionalidades.Por ejemplo, supongamos que una vez introducido un artculo no puede ser introducido otro que tenga el mismo cdigo. Pararealizar una funcin que verifique si es vlido o no el nuevo artculo, podemos utilizar la funcin de comparacin:

    int Valida( struct articulo *ar1, struct articulo *ar2 ){

    if(!strcmp( ar1->cod_art, ar2->cod_art )) return 0;

    else return 1;}

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    129

    /* Programa con funcin Valida */main(){

    int i;struct articulo ar[5], br[5];

    ...

    /* Carga de los arrays con datos */...

    for (i=0; icod_art))

    printf ("Los articulos de la posicin %d son iguales\n", i+1);

    elseprintf ("Los articulos de la posicin %d son

    distintos\n", i+1);}

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    130

    ...

    /* Carga de los arrays con nuevos datos */...

    for (i=0; icod_art, br[i] ->cod_art)) printf ("Los artculos de la posicin %d son iguales\n",

    i+1);elseprintf ("Los artculos de la posicin %d son distintos\n", +1);

    }

    }

    Supongamos que se utiliza la funcin Valida en muchos lugares del programa y que es necesario hacer un cambio que implicala modificacin de la condicin de la misma. Este cambio en un nico punto de la librera modifica automticamente el fun-cionamiento de todo el programa. En la versin con funcin Valida slo hay que modificar el cdigo de la misma para que elprograma quede actualizado, no siendo necesario modificar el programa principal que la invoca. Si esta funcin no existiera,el programador debera ir buscando en el programa cada uno de los lugares donde se ha utilizado la condicin de comparaciny aadirle la condicin de desigualdad de existencias, lo cual lleva mucho ms tiempo y har probablemente que se produzcaalgn error, al pasar inadvertida la modificacin en alguna sentencia. Ese tipo de errores son muy difciles de depurar.

    int Valida( struct articulo *ar1, struct articulo *ar2 ){

    if(!strcmp( ar1->cod_art, ar2->cod_art ) && (ar1->existencias == ar2-> existencias)) return 0;

    else return 1;

    }

    /* Programa con funcin Valida */main(){

    int i;struct articulo ar[5], br[5];...

    /* Carga de los arrays con datos */...

    for (i=0; i

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    131

    ...

    /* Carga de los arrays con nuevos datos */...

    for (i=0; icod_art) && (ar1->

    existencias == ar2-> existencias)) printf ("Los artculos de la posicin %d son iguales\n", i+1);

    elseprintf ("Los artculos de la posicin %d son distintos\n", i+1);

    }...

    /* Carga de los arrays con nuevos datos */...

    for (i=0; icod_art, br[i] ->cod_art) && (ar1->

    existencias == ar2-> existencias)) printf ("Los artculos de la posicin %d son

    iguales\n", i+1);else

    printf ("Los artculos de la posicin %d son distintos\n", i+1);

    }}

    La ocultacin de la informacin no slo es til cuando se modifica alguna funcin, sino que tambin permite la modificacinde la estructura completa, sin necesidad de modificar el programa principal.

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    132

    Imagina que queremos cambiar la estructura porque los artculos no son unitarios (un libro por entregas o una serie en DVDcon varios captulos). Entonces, las ventas no sern unitarias por lo que el campo existencias y las ventas no sern nmerosenteros, sino valores reales. Con la librera de funciones bsicas que hemos realizado no es necesario cambiar ni una lnea decdigo del programa principal. nicamente debemos redefinir parte de la librera para que la estructura defina dicho campode forma apropiada y las funciones alta y vender reciban un float como argumento cantidad, y la funcin Visualizar utilice%f en lugar de %d en la instruccin printf.

    El ejemplo que vamos a desarrollar en este apartado consiste en crear unabiblioteca que permita representar en un plano de dos dimensiones el segui-miento de las trayectorias de los aviones en un determinado espacio areo. Paraello, debemos representar fundamentalmente tres estructuras:

    a) Las zonas del espacio areo que estn restringidas (por saturacin, razones deseguridad o uso militar).

    b) Las trayectorias que siguen los aviones.

    c) El rea concreta del mapamundi sobre la que nuestra aplicacin muestra elseguimiento.

    Aunque la aplicacin pretende simular la trayectoria de unos aviones en un espacio del mundo, esta simulacin es unasimplificacin, ya que el mundo real tiene tres dimensiones (incluyendo los aviones y las zonas restringidas a la nave-gacin area comercial). Para nuestro ejemplo slo nos interesa una visin en dos dimensiones, en la que la altitud delos aviones y de las zonas restringidas no queda reflejada y la ignoramos a pesar de su importancia real.

    Asimismo, el planeta tiene unas dimensiones suficientemente grandes como para que no sea til mostrar las trayectorias delos aviones a una escala global, por lo que debemos limitar nuestro seguimiento a una parte de todo el planeta. Para saberqu parte del mundo queremos mostrar, utilizaremos una estructura dedicada a este fin.

    Hemos comentado con anterioridad que otra de las estructuras que nos interesa representar es la zona restringida, deforma que refleje su extensin (en forma de un polgono en 2D) y las razones de dicha restriccin (seguridad, militar,saturacin).

    Adicionalmente, hemos de representar a las aeronaves y su movimiento. Con este objeto, la estructura que las representaalmacena la velocidad a la que se desplazan. La trayectoria que siguen se supone prefijada en un fichero antes de comenzarla ejecucin de la simulacin (pero con trayectoria independiente para cada uno de los aviones).

    En resumen, la aplicacin que queremos construir deber permitir representar una zona del planeta con dos tipos de ele-mentos: las zonas restringidas y los aviones en movimiento. Los aviones no podrn moverse por las zonas restringidas. Paraestablecer la configuracin inicial de este mundo, utilizaremos lectura de ficheros escritos en modo texto (para una mayorcomprensin y sencillez). As, el programa principal de nuestra aplicacin utilizar las funciones de las libreras que defina-mos con objeto de proporcionar al usuario las siguientes operaciones:

    a) Modificar las condiciones de ejecucin: el fichero que define el mundo, la velocidad a la que transcurre el tiempo paralos movimientos y el tiempo total que durar la simulacin.

    4

    Ejemplo prctico

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    133

    b) Ejecutar la simulacin del seguimiento.

    c) Reiniciar la simulacin del seguimiento.

    Adicionalmente tambin se podra enriquecer nuestra aplicacin con un editor mediante el cual se pudiera modificar el ficheroque almacena la definicin del mundo.

    Para conseguirlo agruparemos las distintas funciones en tres mdulos o libreras: una dedicada a la lectura de ficheros, otra amostrar en pantalla el estado de la zona que estamos siguiendo y una tercera para realizar los movimientos de los aviones.

    Fig. 5.5. Agrupacin de los tres mdulos.

    Uno de los tipos de datos en los que se fundamenta nuestra aplicacin es el que representa un punto en coordenadas pola-res. La posicin de un avin se representa mediante un punto de este tipo y la de una zona restringida con una secuencia depuntos dinmicamente enlazados que define un polgono.

    struct punto{

    double r, angulo;struct punto *siguiente;

    };

    Otra de las estructuras bsicas de la aplicacin es la que permite definir la trayectoria de un avin. Para ello, suponemos queun avin tiene dos motores (uno por cada ala) y que su dinmica se define por las velocidades que imprimen.

    Como se explic anteriormente, los aviones seguirn trayectorias definidas a priori en un fichero. Estas trayectorias vienendefinidas por tramos en los que se mantiene una determinada aceleracin producida por el motor de cada ala del avin. As,utilizaremos una estructura enlazada para encadenar una trayectoria con la siguiente, de la forma indicada a continuacin:

    struct trayectoria{

    double tramo, adcha, aizda;struct trayectoria *siguiente;

    }

    Con estas dos estructuras ya es posible definir las partes en comn de todas las figuras: los aviones, las zonas restringidas yel campo de visin de la pantalla con la que mostramos el seguimiento.

    Figuras

    Dibujo Movimiento Creacin

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    134

    Para ello, supondremos que los puntos que delimitan el polgono correspondiente a una zona restringida o al campo de visinse definen en coordenadas polares con respecto al centro de la zona restringida o del campo de visin. En cambio, a los avio-nes se les supone sin grosor y, por tanto, estarn representados nicamente mediante su punto central.

    Por ltimo, mencionar que utilizaremos una estructura doblemente enlazada (con la figura siguiente y la anterior) para irrecorriendo todas las figuras que se presenten en una ejecucin de nuestro programa. As, la parte comn a los tres tipos defiguras es la siguiente:

    enum tipo { campo_vision, zona, avion };struct figura{

    enum tipo mitipo;double x,y;...

    struct figura *anterior;struct figura *siguiente;

    }

    La parte ausente en el cdigo anterior es la correspondiente al movimiento del avin, que vendr definido por su velocidad(v) y su velocidad angular (w), su distancia entre las ruedas (r) y la direccin que lleva el avin (tetha). Debido a que estoscampos slo son aplicables a los aviones y, en cambio, la secuencia de puntos definida por el atributo mispuntos es aplica-ble a los otros dos tipos de figuras (zonas restringidas y campo de visin), por tanto se pueden representar como una uninsemejante a la siguiente:

    struct velocidad{

    double v,w,r,tetha;struct trayectoria *mistrayecs;

    }union grosor_o_velocidad{

    struct velocidad mivelocidad;struct punto *mispuntos;

    }

    Y as la estructura completa de figura quedara:

    enum tipo { campo_vision, zona, avion };struct figura{

    enum tipo mitipo;double x,y;union grosor_o_velocidad no_comun;struct figura *anterior;struct figura *siguiente;

    }

    Grficamente vamos a ver un ejemplo de zona restringida y de avin en movimiento.

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    135

    Fig. 5.6. Zonas restringida y de avin en movimiento.

    Antes de pasar a detallar el funcionamiento interno de las funciones, haremos una breve sntesis de las funciones que vamosa agrupar en cada uno de los tres mdulos:

    a) Creacin y destruccin de figuras:

    En esta librera se especifican todas las funciones que crean las estructuras para los datos, leen dichos datos de un ficheroy vacan y destruyen las estructuras creadas.

    LeerFiguras: esta funcin crea la lista de figuras y llama a la funcin LeerFigura, que lee una figura tantas veces comosea necesario para definir todo el entorno.

    LeerFigura: esta funcin simplemente va llamando a todas las funciones que leen los campos que definen unaFigura.

    LeerTipo: lee el tipo de la figura; los validos son: campo de visin, avin y zona restringida.

    LeerNodos: crea la estructura de los puntos de una figura. Al menos debe existir un punto por figura (es el caso delos aviones).

    LeerInicial: lee los valores de la posicin inicial de la figura. stos son las coordenadas x, y. En el caso de los avio-nes tambin se leern los valores de v, w, r y tetha.

    LeerTrayecs: crea la lista de trayectorias y las lee desde el fichero.

    LeerControl: lee un carcter del fichero y comprueba si es el carcter de control esperado; si lo es, se salta el restode la lnea llamando a la funcin LineaSiguiente; en otro caso devuelve error.

    LineaSiguiente: lee caracteres del fichero hasta encontrar un fin de lnea (respetando el fin de fichero), es decir,ignora el resto de la lnea.

    LeeNumero: lee caracteres del fichero hasta encontrar uno que sea distinto del espacio en blanco y devuelve el numerocorrespondiente (float o int).

    BorrarFiguras: libera toda la memoria ocupada por la lista de figuras que compone el mundo en 2D.

    zona1

    zona3

    zona2

    avion1

    avion2

    avion3avion4

    Campo de visin

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    136

    BorrarNodos: libera toda la memoria ocupada por la lista de puntos que delimita una regin prohibida o un campo devisin.

    BorrarTrayecs: libera toda la memoria ocupada por la lista de tramos que define la trayectoria de un avin.

    b) Movimiento de figuras (slo aviones)En este mdulo se definen las funciones que nos permiten mover los aviones (son las nicas figuras que tienen dichacapacidad).

    MueveFigura: los aviones describen una serie dada de trayectorias en funcin del instante en que nos encontremos(esto viene dado en el fichero de entrada que describe el mundo). Adems, cada una de estas trayectorias tiene unaaceleracin especifica para cada rueda. Con estas aceleraciones correspondientes al tramo del instante actual se cal-cula la nueva velocidad.

    AplicaMov: con la nueva velocidad ya calculada se aplica sobre la posicin y direccin del avin para determinar sunueva posicin y velocidad.

    c) Dibujo de figuras

    Esta librera incluye la definicin de las funciones que manejan la presentacin en pantalla del seguimiento de los avio-nes. A continuacin, se indican todas las funciones que deberan componer esta librera, aunque por razones de espacioen este captulo slo se han desarrollado IniciaG, CierraG, DibujaFigura y EntraFigura.

    IniciaG: funcin que inicializa las funciones grficas.

    CierraG: funcin que cierra el modo grfico.

    DibujaMundo: presenta en la pantalla las zonas restringidas y los aviones que se han ledo del fichero y cuyascoordenadas se encuentran dentro de los lmites del campo de visin. Dibuja tambin el borde del campo devisin.

    Corte: calcula matemticamente los puntos de corte de una recta con los lados del campo de visin.

    DibujaFigura: va dibujando un avin o una zona uniendo sus vrtices y comprobando si estn dentro de la campo devisin o no.

    EntraFigura: comprueba si la figura est dentro de los limites de la pantalla, fuera o bien parte dentro y partefuera.

    Scroll: funcin que permite modificar los lmites del campo de visin que se muestra en pantalla.

    DibujaCampo: dibuja las cuatro lneas que limitan el campo de visin.

    BorraCampo: oculta las figuras del campo de visin dibujando un rectngulo negro con las dimensiones del mismo.

    BorraFigura: borra una figura del campo de visin.

    CorteLinea: comprueba si algn punto de la lnea se ha cruzado con alguna zona restringida o avin. Esto lo haceviendo si en los puntos en los que debe dibujar la lnea ya haba algo pintado.

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    137

    De estas tres libreras, nicamente vamos a ver cmo se realizarn los clculos necesarios para implementar el movimientode los aviones. Para llevar a cabo estos clculos tenemos en cuenta las siguientes consideraciones del problema:

    El avin esta dotado de dos motores, uno en cada ala sobre las cuales se puede aplicar una determinada velocidadlineal (v1 y v2).

    Dichas alas no pueden girar, con lo que para que el avin pueda girar lo que hacemos es aplicar una velocidad mayoro menor al motor de un ala que al de la otra.

    Las alas estn separadas por una distancia r.

    El avin en un determinado instante se encuentra en una posicin (X,Y) y con una direccin u con respecto del ejevertical.

    Existen dos posibles movimientos diferentes que puede describir un mvil:

    Traslacin. Desplazamiento definido por la velocidad lineal v:

    Posicin = Velocidad * Tiempo

    Fig. 5.7. Desplazamiento definido por la velocidad lineal.

    Rotacin. Movimiento sobre s mismo definido por la velocidad angular w:

    ngulo = Velocidad Angular * Tiempo

    Fig. 5.8. Movimiento sobre s mismo definido por la velocidad angular w.

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    138

    As pues lo que vara en cada tipo de movimiento es:

    1. Su nueva posicin (X',Y') es funcin de la posicin en la que se encontraba antes y de la v:

    2. Su direccin u que es funcin de la antigua orientacin u y de la velocidad angular aplicada w:

    As, las frmulas a aplicar son las siguientes:

    La velocidad del avin en un determinado instante es la media de las velocidades aplicadas a sus ruedas:

    v(n) = (vdcha(n)+ vizda(n)) /2

    La posicin de un avin en un determinado instante se calcula sumando la posicin que tena en el instante ante-rior con la velocidad que lleva por el tiempo.

    Tenemos que tener en cuenta tambin que el avin se mueve en cualquier direccin, con lo que en unos casos lanueva coordenada X o Y aumenta o disminuye en funcin de la direccin u en la que se mueva, con lo que tendre-mos que considerar el seno en el caso de la X y el coseno en el caso de la Y:

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    139

    X(n+1)=X(n)+v(n)senut

    Y(n+1)=Y(n)+v(n)cosut

    La velocidad angular en un determinado instante se calcula, de la misma forma que en el caso lineal, a partir de las velo-cidades lineales de las alas pero considerando la diferencia y el radio entre ellas:

    v(n)= (vdcha(n)+ vizda(n)) / r

    La direccin en la que se mueve el avin en un determinado instante se calcula a partir de la direccin que tena en elinstante anterior y de la velocidad angular del instante anterior:

    u(n+1)=u(n)+ v(n)t

    La librera que modeliza este movimiento se compone de dos funciones: en una se calcula el tramo en el que nos encontra-mos y obtiene las velocidades que deseamos aplicar, y en otra se calculan los nuevos valores de la situacin actual de la figuradefinida por las coordenadas x e y, y por la orientacin del avin determinada por el ngulo tetha.

    A continuacin, se muestra el cdigo de la primera de ellas, que recibe como argumento el tiempo actual (con el que selec-cionaremos el tramo en vigor) y el tiempo transcurrido desde la ltima actualizacin de la posicin:

    void MueveFigura( struct figura *f, float Ttotal, float Tparcial ){

    float nueva_v, nueva_w;struct trayectoria *tramo;tramo = f-> nocomun.mivelocidad.mistrayecs;while(tramo->siguiente != 0 && tramo->tramo < Ttotal) tramo = tramo->siguiente;

    nueva_v = ( tramo->adcha + tramo->aizda ) / 2.0;nueva_w = ( tramo->aizda - tramo->adcha ) /

    f->nocomun.mivelocidad.r;AplicaMov( f, na, nalfa, Tparcial );

    }

    Esta funcin primero calcula la nueva v y w del tramo actual, y una vez obtenidas estas velocidades se llama a la funcinAplicaMov que modifica los valores de posicionamiento de la figura. La funcin que mueve la figura es entonces:

    void AplicaMov( struct figura *f, float nv, float nw, float Tparcial ){

    f->nocomun.mivelocidad.v = nv;f->x = f->x + ( f->v * sin(f->nocomun.mivelocidad.tetha)* tf );

    f->y = f->y + ( f->v * cos(f->nocomun.mivelocidad.tetha) * tf );f->nocomun.mivelocidad.w = nw;f->nocomun.mivelocidad.tetha = f->nocomun.mivelocidad.tetha +

  • 5. Programacin estructurada5.3 Programacin estructurada y orientacin a objetos

    140

    f->nocomun.mivelocidad.w * tf;if( f->nocomun.mivelocidad.tetha > 2 * 3.1416 )for(;(f->nocomun.mivelocidad.tetha =

    f->nocomun.mivelocidad.tetha - 2 * 3.1416)> 2 * 3.1416;);

    else if( f->nocomun.mivelocidad.tetha < 0 )for(;(f->nocomun.mivelocidad.tetha =

    f->nocomun.mivelocidad.tetha + 2 * 3.1416) < 0;);

    }

    Las lneas finales de esta funcin tienen por objeto impedir que el ngulo tetha sea mayor que 2 * pi. En dicho caso, habr dadouna vuelta completa y debe tomar los valores prximos a cero que correspondan al giro.

  • 5. Programacin estructuradaEjercicios

    141

    Ejercicios

    Crea una librera de funciones para operar con nmeros complejos.

    Desarrolla las funciones nombradas en este captulo para jugar al ajedrez.

    Genera un programa que haciendo uso de la librera artculo explicada en este captulo permita realizar una bs-queda de un producto y su posterior compra, completando la implementacin de las funciones de las libreras delibros y DVD cuya declaracin ha sido indicada en el texto.

    Implementa las funciones, la librera de creacin y destruccin de figuras correspondiente al ejemplo de seguimientode aviones en el espacio areo.

    4

    3

    2

    1

  • Explica por qu razn las libreras se definen mediante dos ficheros, uno de extensin .h y otro .c.

    Describe qu tienen en comn la visin clsica y la moderna de la programacin estructurada.

    Enumera las ventajas de la programacin estructurada sobre la programacin tradicional.3

    2

    1

    5. Programacin estructuradaEvaluacin

    142

    Evaluacin

  • 5. Programacin estructuradaActividades prcticas

    143

    Actividades prcticas

    Desarrolla una librera de funciones ms que permita aviones inteligentes, esto es, que su movimiento no est pre-fijado mediante tramos, sino que sea capaz de moverse por el mundo que dibujemos segn una lgica de control(por ejemplo, evitando las zonas restringidas y otros aviones). Para ello, se deber dotar a dicha figura de un des-tino que pretende alcanzar y de sensores que le permitan percibir el mundo.

    Crea otra librera de funciones que permita que existan figuras mviles controladas por el usuario. Esto es, quemediante cuatro teclas (arriba, abajo, izquierda y derecha) permita a un usuario guiar una figura mvil por el mundo.

    Propn una ampliacin al ejemplo de gestin de productos en una tienda desarrollando las libreras asociadas a lasotras estructuras necesarias para la aplicacin: Proveedores, Clientes, Empleados y Pedidos.

    3

    2

    1