Fundamentos de programación con Módula-2 (11)

 

TEMA 5
Estructuras Básicas de la Programación Imperativa

 

Este Tema se dedica a introducir las estructuras básicas de la programación imperativa: Secuencias, Selección e Iteración, indicando la manera de realizar dichas estructuras en Modula-2. Aunque existen otras estructuras, que se introducen en temas posteriores, en este tema se ha preferido insistir fundamentalmente en los conceptos subyacentes en estas estructuras básicas, prescindiendo de los aspectos específicos de un lenguaje particular.

Inicialmente se presentan sólo las estructuras básicas IF-THEN-ELSE y WHILE, y su codificación en Modula-2. Posteriormente se mencionan las estructuras particulares IF-ELSIF-ELSE y FOR derivadas de las anteriores, justificándolas por la comodidad de su uso.


5.1 Programación estructurada

La programación estructurada es una metodología de programación que fundamentalmente trata de construir programas que sean fácilmente comprensibles. Un programa no solamente debe funcionar correctamente, sino que además debe estar escrito de manera que se facilite su comprensión posterior.

Normalmente en todos los programas se tienen que realizar algunas correcciones o modificaciones después de trascurrido un cierto tiempo. En ese momento se trata de evitar lo que a veces llega a suceder, desgraciadamente: si el programa no está claramente escrito, ni el mismo programador que construyó el programa es capaz de entender cómo funciona.

Esta metodología está basada en la técnica de desarrollo de programas por refinamientos sucesivos, tal como se ha expuesto en el Tema anterior. Inicialmente, se plantea la operación global a realizar por el programa, y se descompone en otras más sencillas. A su vez, estas últimas vuelven a ser descompuestas nuevamente en otras todavía más elementales. Este proceso de descomposición continúa hasta que todo se puede escribir utilizando las estructuras básicas disponibles en el lenguaje de programación que se está empleando.

5.1.1 Representación de la estructura de un programa
La estructura de los programas imperativos se representa tradicionalmente mediante diagramas de flujo, llamados en inglés "flow-chart". Estos diagramas contienen dos elementos básicos, correspondientes a condiciones y acciones (Figura 5.1). Las acciones se representan mediante rectángulos, y las condiciones mediante rombos. Las condiciones equivalen a preguntas a las que se puede responder SI o No.

figura(5_1) 
    Figura 5.1 Símbolos de acción y condición.

El flujo de control durante la ejecución del programa se refleja mediante líneas o vías que van de un elemento a otro. Las acciones tienen una sola vía de entrada o comienzo y una de terminación o salida. Las condiciones tienen una vía de entrada, y dos vías de salida marcadas con SI y NO. Durante la ejecución, cuando el flujo llega a la entrada de una acción, la acción se realiza y el flujo se dirige a su salida. Cuando se llega a la entrada de una condición, la condición se evalúa, y si resulta

figura(5_2) 
     Figura 5.2 Ejemplo de diagrama de flujo (a) y acción compuesta (b).

ser cierta se continúa por la salida SI, mientras que si es falsa se continúa por la salida NO. La figura 5.2 contiene un ejemplo sencillo de diagrama de flujo. En esta figura se indica también cómo un fragmento del diagrama, que tenga un solo punto de entrada y uno de salida, puede ser visto globalmente como una acción única, pero compuesta.

La parte de diagrama de flujo en el interior de una acción compuesta constituye la estructura o esquema de dicha acción. La programación estructurada recomienda descomponer las acciones usando las estructuras más sencillas posibles. Entre ellas se reconocen tres estructuras básicas, que son: Secuencia, Selección e Iteración. Estas tres estructuras están disponibles en todos los lenguajes modernos de programación imperativa en forma de sentencias del lenguaje. Combinando unos esquemas con otros se pueden llegar a construir programas con una estructura tan complicada como sea necesario.

figura(5_3)
    Figura 5.3. Secuencia

5.1.2 Secuencia
La estructura más sencilla para emplear en la descomposición es utilizar una secuencia de acciones o partes que se ejecuten de forma sucesiva. En la figura 5.3 se muestra una secuencia de acciones.

La estructura secuencial ya ha sido utilizada en los ejemplos realizados en los temas anteriores. Todos ellos han sido resueltos como una secuencia de sentencias elementales del lenguaje.

5.1.3 Selección
La estructura de Selección consiste en ejecutar una acción u otra, dependiendo de una determinada condición que se analiza a la entrada de la estructura. En la Figura 5.4 se puede ver la estructura de selección. Si la condición analizada (?) da como resultado SI se realiza la acción A y si el resultado es NO se realiza la acción B. Como se puede observar sólo tiene una única entrada y una única salida.

Figura(5_4)
     Figura 5.4 Selección

5.1.4 Iteración
La Iteración es la repetición de una acción mientras que se cumpla una determinada condición. La estructura de iteración más general es aquella en que la condición se analiza a la entrada de la estructura y antes de iniciar cada nueva repetición. En la Figura 5.5 se muestra esta estructura de iteración. Cada vez que se analiza la condición (?) se pueden dar dos resultados.

Figura(5_5)
     Figura 5.5 Iteración

Si el resultado es SI se ejecuta nuevamente la acción. Una vez ejecutada la acción se vuelve a analizar la condición (?). En el momento que el resultado es NO se alcanza el punto final de la estructura. También en este caso sólo existe un punto de entrada y un punto de salida.

Puesto que el flujo de ejecución vuelve hacia atrás siguiendo un camino cerrado, la estructura de iteración se denomina también bucle.

5.1.5 Estructuras anidadas
Cualquier parte o acción del programa puede a su vez estar constituida por cualquiera de las estructuras descritas. Por tanto, el anidamiento entre ellas puede ser tan complejo como sea necesario.

Mediante la técnica de refinamientos sucesivos se definen inicialmente las estructuras más externas del programa y en los pasos sucesivos se va detallando la estructura de cada acción compuesta. Este proceso finalmente da lugar a que todo el programa quede escrito utilizando las estructuras básicas descritas en este apartado anidadas unas dentro de otras.

5.2 Expresiones condicionales

Para poder utilizar las estructuras de Selección e Iteración es necesario expresar las condiciones (?) que controlan ambas estructuras. Esto se realiza mediante la construcción de expresiones condicionales. Estas expresiones sólo pueden dar como resultado dos valores: SI (cierto), cuando se cumple la condición de la expresión, y NO (falso), en caso de que no se cumpla.

Una primera forma de construir expresiones condicionales es mediante el empleo de operadores de comparación en expresiones aritméticas. Estos operadores permiten realizar comparaciones entre dos valores del mismo tipo. Las operaciones de comparación disponibles y sus operadores en Modula-2 son las siguientes:

                     Comparación                         Operador Modula-2
                > Mayor que                                 >
                < Menor que                                 <
                = Igual a                                       =
                >= Mayor o igual que                     >=
                <= Menor o igual que                     >=
                <> Diferente a                               <>    #

Los símbolos de operadores Modula-2 con dos caracteres deben escribirse precisamente en ese orden, y sin espacios en blanco entre ellos. El operador de desigualdad puede escribirse de dos maneras, tal como se indica.

Veamos un ejemplo. Sean las variables declaradas siguientes:

VAR
   largo, ancho : INTEGER;
   presion, temperatura : REAL;
   letra, modelo : CHAR;

Con los operadores de comparación se pueden formar expresiones condicionales tales como las siguientes:

largo > 5
ancho = largo
presion <= 23.5
modelo = "Z"
letra <> modelo
presion # temperatura

Con los operadores de comparación sólo es posible realizar un única comparación entre dos valores. Sin embargo, es bastante normal que las condiciones sean más complejas. Pueden construirse condiciones que impliquen a más de dos valores como condiciones compuestas de varias condiciones simples.

Las condiciones compuestas se construyen como expresiones lógicas. Cada término de una expresión lógica podrá ser una expresión condicional simple. Las operaciones lógicas entre dos expresiones simples E1, E2 y los correspondientes operadores disponibles en Modula-2 son los siguientes:

                 Operación lógica                    Operador Modula-2
         Conjunción (E1 y E2)                        AND    &
         Disyunción (E1 o E2)                        OR
         Negación (no E1)                              NOT   ~

Los símbolos de los operadores lógicos de Modula-2 son las palabras que se indican, y que deben escribirse precisamente así, en mayúsculas (los operadores de conjunción y negación pueden escribirse también con los signos especiales "ampersand" y "tilde", respectivamente).

La operación de conjunción E1 AND E2 da resultado cierto si tanto E1 como E2 son ciertas. La operación de disyunción E1 OR E2 da resultado cierto si una de las dos, E1 o E2, o ambas, son ciertas. El operador NOT se aplica a un solo término y niega el resultado de dicho término. Este operador se utiliza cuando una condición queda expresada de manera más sencilla como complemento de otra.

Con estos nuevos operadores es posible construir condiciones complejas tales como las siguientes:

(largo > 5) AND (ancho < 7)
(modelo = "A") OR (modelo = "Z")
NOT (letra = "Q")
(temperatura <= 123.7) & (presion < 12.3)

con el significado que fácilmente se puede deducir. La razón del empleo de paréntesis es indicar el orden preciso de ejecución de las operaciones: primero las comparaciones y posteriormente las operaciones lógicas. Por defecto, se realizan primero las operaciones lógicas y posteriormente las comparaciones.

La complejidad de las expresiones puede ser tan grande como sea necesario; el número de términos lógicos que pueden combinarse es ilimitado. Además, cada valor numérico se puede obtener mediante una expresión aritmética. Por ejemplo, son expresiones condicionales válidas las siguientes:

(largo < 3) AND (ancho < 9) AND (largo*ancho < 25)
NOT ((letra = "Q") OR (letra = "Z"))
(3.5*temperatura – presion/5.6) < 54.6

En la evaluación de estas expresiones complejas el orden que se sigue viene fijado por un nivel de prioridad que tienen asignadas las distintas operaciones. Es decir, cada operador tiene una prioridad determinada. Si no se utilizan paréntesis el orden de evaluación es el siguiente:

1º Operador de Negación:                NOT ~
2º Operadores Multiplicativos:          * / DIV MOD AND &
3º Operadores Aditivos:                   + – OR
4º Operadores de Comparación:       > < = >= <= <> #

Dentro del mismo nivel las operaciones se evalúan en el orden en que están escritas en la expresión, de izquierda a derecha. Así, si se hubiera prescindido de los paréntesis en las últimas expresiones:

largo < 3 AND ancho < 9 AND largo*ancho < 25
NOT letra = "Q" OR letra = "Z"
3.5*temperatura – presion/5.6 < 54.6

y siguiendo los criterios de evaluación anteriores, estas expresiones serían equivalentes a las que se indican a continuación, en las que se ha marcado con paréntesis el orden de la evaluación por defecto:

largo < (3 AND ancho) < ((9 AND largo)*ancho) < 25
(NOT letra) = ("Q" OR letra) = "Z"
((3.5*temperatura) – (presion/5.6)) < 54.6

Con estas expresiones sólo se trata de mostrar las reglas de evaluación por defecto, dado que como se puede observar, las dos primeras expresiones están sintácticamente mal construidas y no tienen ningún sentido.

Las reglas BNF que definen cómo se pueden escribir expresiones, además de las expresiones aritméticas, incluyen aquellas expresiones que expresan condiciones y son las siguientes:

Expresión ::=
   Expresión_simple [ Operador_comparador Expresión_simple ]

Expresión_simple ::= [ + | – ] Termino { Operador_sumador Termino }

Termino ::= Factor { Operador_multiplicador Factor }

Factor ::=
   Identificador_de_Variable | Identificador_de_Constante | Valor_Constante | (Expresión) | NOT Factor

Operador_comparador ::= > | < | = | >= | <= | <> | #
Operador_sumador ::= + || OR
Operador_multiplicador ::= * | / | DIV | MOD | AND | &

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s