curso de modula-2 (incompleto).pdf

171
Tema 3. Introducción al lenguaje de programación Modula-2 1 Informática Facultad de Ciencias (Matemáticas) Departamento de Lenguajes y Ciencias de la Computación UNIVERSIDAD DE MÁLAGA Apuntes para la asignatura Informática Facultad de Ciencias (Matemáticas) http://www.lcc.uma.es/personal/pepeg/mates Tema 3. Introducción al lenguaje de programación Modula-2 3.1 Valores y tipos ................................................................ ................................ .... 3 3.2 Representación de constantes ................................................................ ........... 3 3.2.1 Valores numéricos enteros ................................................................ ............ 4 3.2.2 Valores numéricos reales ................................................................ .............. 4 3.2.3 Caracteres ................................................................ ................................ .... 5 3.2.4 Cadenas de caracteres (Strings)................................................................ ... 5 3.3 Tipos predefinidos ................................................................ .............................. 6 3.3.1 El tipo INTEGER ................................................................ ........................... 6 3.3.2 El tipo CARDINAL ................................................................ ......................... 7 3.3.3 El tipo REAL................................................................ ................................ .. 7 3.3.4 El tipo LONGREAL................................................................ ........................ 8 3.3.5 El tipo CHAR ................................................................ ................................ . 9 3.4 Expresiones aritméticas................................................................ ...................... 9 3.5 Identificadores ................................................................ ................................ .. 10 3.6 Constantes ................................................................ ................................ ....... 12 3.7 Variables ................................................................ ................................ ........... 13 3.7.1 Declaración de variables ................................................................ .............14 3.7.2 Sentencia de asignación ................................................................ ............. 14 3.8 Operaciones de Entrada y Salida. ................................ ................................ .... 16 3.8.1 Operaciones de Salida ................................................................ ................ 16 3.8.2 Operaciones de Entrada ................................................................ ............. 18 3.9 Estructura general de un programa ................................................................ .. 20 Bibliografía Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de Educación a Distancia.

Upload: gerardodoac

Post on 26-Dec-2015

46 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 1

Informática Facultad de Ciencias (Matemáticas)

Departamento de Lenguajes y Ciencias dela Computación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)

http://www.lcc.uma.es/personal/pepeg/mates

Tema 3. Introdu cción al lengu aje de programaciónModu la-2

3.1 Valores y tipos ................................................................ ................................ ....3

3.2 Representación de constantes ................................................................ ...........3

3.2.1 Valores numéricos enteros................................................................ ............4

3.2.2 Valores numéricos reales................................................................ ..............4

3.2.3 Caracteres ................................................................ ................................ ....5

3.2.4 Cadenas de caracteres (Strings)................................................................ ...5

3.3 Tipos predefinidos ................................................................ .............................. 6

3.3.1 El tipo INTEGER ................................................................ ........................... 6

3.3.2 El tipo CARDINAL................................................................ ......................... 7

3.3.3 El tipo REAL................................................................ ................................ ..7

3.3.4 El tipo LONGREAL................................................................ ........................ 8

3.3.5 El tipo CHAR................................................................ ................................ .9

3.4 Expresiones aritméticas................................................................ ...................... 9

3.5 Identificadores ................................................................ ................................ ..10

3.6 Constantes ................................................................ ................................ .......12

3.7 Variables................................................................ ................................ ...........13

3.7.1 Declaración de variables ................................................................ .............14

3.7.2 Sentencia de asignación ................................................................ .............14

3.8 Operaciones de Entrada y Salida. ................................ ................................ ....16

3.8.1 Operaciones de Salida................................................................ ................16

3.8.2 Operaciones de Entrada ................................................................ .............18

3.9 Estructura general de un programa ................................................................ ..20

Bibliografía• Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de

Educación a Distancia.

Page 2: Curso de Modula-2 (Incompleto).pdf

2 3.1 Valores y tipos

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

Page 3: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 3

Informática Facultad de Ciencias (Matemáticas)

Introdu cc iónModula-2 fue diseñado por Niklaus Wirth y es uno de los lenguajes de programación de altonivel más utili zado actualmente para la enseñanza de la programación de ordenadores. Existenvarias versiones de este lenguaje. Nos centraremos en el resto del curso en el estudio de una delas versiones más populares: TopSpeed Modula-2.

Una de las características que diferencia a un lenguaje de programación de otras notacionespara expresar algoritmos, como el pseudocódigo, es la menor flexibili dad del primero. Enefecto, un programa escrito en un lenguaje de programación de alto nivel consta de una serie deinstrucciones (o sentencias) que indican al ordenador los pasos a seguir para resolver ciertoproblema. Al conjunto de reglas que dictan cuáles son las instrucciones posibles y el modo decombinarlas se denomina sintaxis del lenguaje. En este tema comenzaremos el estudio de lasintaxis del lenguaje Modula-2. Para definir cada una de las reglas utili zaremos la notaciónBNF. Finalizaremos el tema con un ejemplo completo de un programa escrito en Modula-2 queel alumno podrá probar en la primera práctica de la asignatura.

3.1 Valores y tiposTodo programa de ordenador manipula una serie de datos para obtener unos resultados.Definimos dato como un elemento de información que puede tomar un valor entre variosposibles.

En programación, un dato puede tomar valores de una sola clase. No tiene sentido decir que elnombre de una persona es “24” . Tampoco lo tiene decir que el número de personas en una clasees “Pedro” . A las distintas clases de valores se denominan tipos. Así, un dato tiene asociadoun tipo que representa cual es la clase de valores que puede tomar. Algunos ejemplos de tiposson:

• Valores numéricos enteros positi vos y negativos: 100, -24, 36, ...

• Valores numéricos enteros y positi vos: 0, 1, 2, 3, ...

• Valores numéricos reales: 3.1415, -16.18,...

• Valores carácter: ‘a’ , ‘b’ , ‘ c’ ,...

Para cada tipo habrá una serie de operaciones que se le pueda aplicar. Así, tiene sentido sumardos valores numéricos, pero no dos letras. Se llama tipo abstracto de datos a un conjuntode valores junto con las operaciones que permiten manipular éstos.

Dentro de un programa existirán dos tipos de valores:

• Valores constantes: se trata de valores cuya magnitud no cambia durante cualquierejecución del programa.

• Valores variables: la magnitud puede tener distintos valores en distintos puntos delprograma.

3.2 Representación d e constantesUno de los objetivos de los lenguajes de programación es evitar las ambigüedades oimprecisiones que existen en los lenguajes naturales. Por ejemplo, los anglosajones utili zan lacoma para separar mill ares, mientras que nosotros la usamos para separar la parte entera de ladecimal:

Page 4: Curso de Modula-2 (Incompleto).pdf

4 3.2 Representación d e constantes

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

348,536 anglosajones trescientos cuarenta y ocho mil quinientos treinta y seis

España trescientos cuarenta y ocho con quinientas treinta y seis

Estudiaremos a continuación las distintas reglas que sigue el lenguaje Modula-2 pararepresentar valores de tipo numérico y de tipo carácter.

3.2.1 Valores numéricos enteros

Los valores numéricos enteros representan un número exacto de unidades y no pueden tenerparte fraccionaria. Un valor entero en Modula-2 se escribe con una secuencia de 1 o más dígitosdel 0 al 9 no separados entre ellos y precedido opcionalmente de los signos mas (+) o menos (-).Ejemplos de valores válidos son:

2

+56

0

-2345

1000

Ejemplos de valores no válidos son:

123,32 NO se pueden insertar comas

22.56 NO se pueden insertar puntos

13B7 NO se pueden insertar letras

Usando la notación BNF:

Valor_Entero ::= [ + | - ] Secuencia_Digitos

Secuencia_Digitos ::= Digito { Digito }

Digito ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

3.2.2 Valores numéricos reales

Los valores numéricos reales permiten expresar cualquier cantidad, incluyendo fracciones deunidad. En Modula-2, se pueden representar de dos modos: notación decimal habitual onotación científica.

En la notación decimal habitual, un valor real se escribe con una parte entera terminada siempreen un punto (.) seguida, opcionalmente, por una secuencia de dígitos que constituyen la partedecimal. Ejemplos de valores válidos son:

-0.78

5.

+234.53

En la notación científica, un valor real se escribe como una mantisa, que es un número real ennotación decimal habitual, seguido de la letra E y un exponente entero que indica la potencia de10 por la que se multipli ca la mantisa. Ejemplos de valores válidos son:

-0.78E+2 equivale a –0.78 x 102

5.E-3 equivale a 5.0 x 10-3 = 0.005

+234.53E4 equivale a 234.53 x 104

Ejemplos de valores no válidos son:

.234 Es necesario al menos un dígito en la parte entera

Page 5: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 5

Informática Facultad de Ciencias (Matemáticas)

2,56 NO se pueden insertar comas

13.4B7 NO se puede insertar la letra B

Obsérvese que podemos escribir un mismo valor de distintos modos:

45.6 456.E-14.56E+1 45.60E+0 456000.00E-4

La definición usando notación BNF es:

Valor_Real ::= Valor_Real_Decimal | Valor_Real_Científica

Valor_Real_Decimal ::= Valor_Entero . [ Secuencia_Digitos ]

Valor_Real_Científica ::= Valor_Real_Decimal Factor_Escala

Factor_Escala ::= E Valor_Entero

3.2.3 Caracteres

Además de tipos numéricos, el lenguaje de programación Modula-2 permite operar valores detipo carácter. Se trata de las letras y signos que constituyen un texto. El valor correspondiente aun carácter concreto se expresa en Modula-2 escribiendo dicho carácter entre comill as (“situado en la tecla correspondiente al número 2 del teclado de un PC) o apóstrofos (‘ situadoen la tecla correspondiente al cierre de interrogación). Ejemplos de valores válidos son:

‘a’ Representa a la letra a minúscula

“A” Representa también a la letra a minúscula

“?” Representa el carácter correspondiente al cierre de interrogación

Ejemplos de valores no válidos son:

a Deben ir entre comill as o apóstrofes.

‘ab’ Solo puede ir una letra

‘a” Debe empezar y acabar con el mismo delimitador

Algunas observaciones son:

• El espacio en blanco (‘ ‘) es un carácter válido. A veces lo representaremos con ‘b’ .

• Hay que distinguir entre el número entero 7 y la letra ‘7’ .

• El valor correspondiente al carácter apóstrofo solo se puede representar entre comill as(“ ’ ” ) y viceversa (‘ “ ‘)

Usando notación BNF:

Valor_Caracter ::= ‘ Caracter_menos_apostrofo ‘ | “ Caracter_menos_comillas “

Caracter_menos_comillas ::= a | b | c | ... | 1 | 2 | 3 | ... símbolos

Caracter_menos_comillas ::= a | b | c | ... | 1 | 2 | 3 | ... símbolos

3.2.4 Cadenas de caracteres (Strings)

Normalmente no es suficiente trabajar con caracteres sueltos. Suele interesar trabajar conpalabras o frases. Estos valores se representan con cadenas de caracteres o Strings. Una cadenade caracteres se escribe como una secuencia de caracteres entre apóstrofos o comill as.Ejemplos válidos son:

“Coche” Representa la palabra Coche

‘Coche’ Idem al anterior

Page 6: Curso de Modula-2 (Incompleto).pdf

6 3.3 Tipos predefinidos

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

“La casa es verde” Representa una frase

Algunas observaciones son:

• Si una cadena incluye apóstrofos en su interior sólo podrá escribirse entre comill as yviceversa. Ejemplo “ Incluir entre ‘apóstrofos’ texto” .

• Es posible definir una cadena que no contenga ningún carácter. A ésta se llama cadenavacía y se escribe como “” o ‘’ .

Usando notación BNF:

Valor_Cadena ::= ‘ { Caracter_menos_apostrofo } ‘ | “ { Caracter_menos_comillas } “

3.3 Tipos predefinidosEn programación, un dato puede tomar valores de una sola clase y que a dicha clase se llamatipo del dato. En Módula-2 existen tipos de datos predefinidos y sentencias para que elprogramador defina nuevos tipos. Algunos de los tipos de datos predefinidos se designan conlos siguientes nombres: INTEGER, CARDINAL, REAL, LONGREAL, CHAR y BOOLEAN.Estudiaremos los cinco primeros a continuación. Estudiaremos el tipo BOOLEAN y losmecanismos para definir nuevos tipos en temas posteriores.

3.3.1 El tipo INTEGER

En TopSpeed Modula-2 los valores de este tipo son los valores numéricos enteros positi vos ynegativos comprendidos en el rango [-32768 , 32767]. La representación de cualquiera de estosvalores en la memoria del ordenador es exacta (no se producen errores de precisión aloperarlos).

En caso de no recordar estos valores, podemos hacer referencia a ellos con las expresionesMIN( INTEGER) y MAX( INTEGER) .

Las operaciones definidas para valores de este tipo son las siguientes:

• a + b. Suma de los enteros a y b

• a – b. Diferencia de los enteros a y b

• a * b. Producto de los enteros a y b

• a DIV b. Cociente resultante de dividir el entero a por el entero b.

• a MOD b. Resto resultante de dividir el entero a por el entero b.

• ABS(a). Valor absoluto del entero a.

• + a. Devuelve el valor del entero a inalterado.

• - a. Devuelve el valor del entero a negado.

Como puede observarse, los signos + y – tienen un doble significado según se usen comooperadores infijos entre dos enteros o prefijos frente a un único entero.

El operador DIV devuelve la parte entera resultante de dividir un número entero por otro. MODdevuelve el resto correspondiente. Cuando el divisor es cero se produce un error. Se cumplesiempre la siguiente regla:

a MOD b = a – b (a DIV b)

Algunos ejemplos de uso de estos operadores son los siguientes:

Page 7: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 7

Informática Facultad de Ciencias (Matemáticas)

Operación Resultado

10 DIV 3 3

10 MOD 3 1

(-20) DIV (-7) 2

(-20) MOD (-7) -6

17 DIV (-3) -5

17 MOD (-3) 2

10 DIV 0 Error

ABS (-2) 2

Cuando se están operando datos de tipo INTEGER hay que tener en cuenta el rango de valoresválidos. Si durante algún momento se produce un resultado fuera de dicho rango, el programaacabará con un error (suponemos que la opción de chequeo de rangos del compilador estáactivada). Debido a esto, la propiedad asociativa no es válida para los datos del tipo INTEGERy ciertos operadores. Por ejemplo

Operación Resultado

(32767 + 1) –10 Error

32767 + (1-10) 32758

ya que en la primera expresión la suma se sale del rango válido.

3.3.2 El tipo CARDINAL

En TopSpeed Modula-2 los valores de este tipo son los valores numéricos enteros positi voscomprendidos en el rango [0 , 65535]. La representación de cualquiera de estos valores en lamemoria del ordenador es exacta (no se producen errores de precisión al operarlos).

En caso de no recordar el valor máximo, podemos nombrarlo con la expresión MAX( CARDINAL) .

Con excepción de la operación de cambio de signo o negación las operaciones son las mismasque para el tipo INTEGER.

Es un error intentar operar un dato de tipo INTEGER con otro de tipo CARDINAL. Sólo sepueden operar datos del mismo tipo.

3.3.3 El tipo REAL

En TopSpeed Modula-2 los valores de este tipo son los valores numéricos reales positi vos ynegativos comprendidos en el rango [-3.4x1038, +3.4x1038]. La representación de estos valoresen la memoria del ordenador no es exacta (se producen errores de precisión al operarlos). Semanejan valores aproximados.

Las operaciones definidas para valores de este tipo son las siguientes:

• a + b. Suma de los reales a y b

• a – b. Diferencia de los reales a y b

• a * b. Producto de los reales a y b

• a / b. Cociente de los reales a y b

• ABS(a). Valor absoluto del real a.

Page 8: Curso de Modula-2 (Incompleto).pdf

8 3.3 Tipos predefinidos

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

• + a. Devuelve el valor del real a inalterado

• - a. Devuelve el valor del real a negado.

En el caso de los reales la división no devuelve el cociente entero, sino el valor real resultantede dividir el cociente por el divisor. Para el tipo REAL NO existen las operaciones DIV y MOD.

Operación Resultado

10.5 / 0.2 52.5

-15.4E2 + 450.0 -1090.0

3.3.4 El tipo L ONGREAL

En TopSpeed Modula-2 los valores de este tipo son los valores numéricos reales positi vos ynegativos comprendidos en el rango [-1.7x10308, +1.7x10308]. La representación de estos valoresen la memoria del ordenador no es exacta (se producen errores de precisión al operarlos). Semanejan valores aproximados.

Las operaciones definidas para valores de este tipo son las mismas que para el tipo REAL. Paravalores de este tipo están también definidas las siguientes operaciones:

• Sin (a): Devuelve el seno del valor LONGREAL a como un valor de tipo LONGREAL.

• Cos(a): Devuelve el coseno del valor LONGREAL a como un valor de tipoLONGREAL.

• Tan(a): Devuelve la tangente del valor LONGREAL a como un valor de tipoLONGREAL.

• ASin (a): Devuelve el arco-seno del valor LONGREAL a como un valor de tipoLONGREAL.

• ACos(a): Devuelve el arco-coseno del valor LONGREAL a como un valor de tipoLONGREAL.

• ATan(a): Devuelve la arco-tangente del valor LONGREAL a como un valor de tipoLONGREAL.

• Sqrt (a): Devuelve la raíz cuadrada del valor LONGREAL a como un valor de tipoLONGREAL.

• Exp(a): Devuelve la función exponencial del valor LONGREAL a como un valor detipo LONGREAL.

• Log(a): Devuelve el logaritmo en base e del valor LONGREAL a como un valor de tipoLONGREAL.

• Log10 (a): Devuelve el logaritmo en base 10 del valor LONGREAL a como un valor detipo LONGREAL.

En el caso de las funciones trigonométricas, todos los ángulos que se manejan están expresadosen radianes, NO en grados.

Estas operaciones, a diferencia de todas las vistas hasta el momento, no están disponibles demodo directo. Se encuentran en un módulo de biblioteca (MATHLIB) y es necesario quesean importadas por el programa antes de ser usadas. Veremos posteriormente como seimportan operaciones de una biblioteca.

NOTA: Estas operaciones NO están definidas para valores del tipo REAL.

Page 9: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 9

Informática Facultad de Ciencias (Matemáticas)

3.3.5 El tipo CHAR

Este tipo incluye como valores todos los caracteres disponibles en el ordenador. Además de loscaracteres alfabéticos (letras), se incluyen caracteres numéricos y de puntuación.

Existen tres operaciones definidas para valores de este tipo:

• ORD(x): Toma como argumento un carácter y devuelve su posición dentro de la tablaASCII.

• CHR(x): Toma como argumento un valor entre 0 y 255 devuelve el carácter que ocupadicha posición dentro de la tabla ASCII.

• CAP(x): Toma como argumento un carácter y si éste es una letra minúscula devuelve laletra mayúscula correspondiente. En otro caso, devuelve el mismo carácter que tomacomo argumento.

Nótese que las funciones CHR y ORD son inversas la una de la otra:

CHR(ORD (x)) = x ORD(CHR (x)) = x.

Ejemplos de uso son:

Operación Resultado

ORD(‘A’) 65

CHR(65) ‘A’

CHR(66) ‘B’

CAP(‘q’) ‘Q’

CAP(‘Q’) ‘Q’

CAP(‘?’ ) ‘?’

3.4 Expresiones aritméticasUna expresión aritmética representa un cálculo a realizar con valores. Para ello se combinanoperandos y operadores.

Si no se utili zan paréntesis, el orden en que se realizan las operaciones es el siguiente:

1º Cambios de signos: + y – como prefijos

2º Operadores multipli cativos *, /, DIV, y MOD

3º Operadores aditi vos: + y – como infijos

Si aparece más de un operador del mismo nivel, las operaciones se realizan de izquierda aderecha. Si una expresión va precedida de un cambio de signo se entiende que solamente afectaal próximo operando. Si se quiere que éste afecte a toda la expresión, ésta deberá incluirse entreparéntesis.

Algunos ejemplos son:

Expresión Equivale a

5 * 30 + 5 (4*30)+5

334 DIV 6 MOD 4 * 5 ((334 DIV 6) MOD 4) * 5

-5 * 10 MOD 3 ((-5) * 10) MOD 3

(5 + 10) * 4 + 5 ((5 + 10) * 4) + 5

En caso de duda es mejor utili zar los paréntesis.

Page 10: Curso de Modula-2 (Incompleto).pdf

10 3.5 Identificadores

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

En Modula-2, es un error operar datos de tipos distintos con los operadores aritméticos. En casode que sea necesario operar valores de tipos distintos utili zaremos las funciones de conversiónREAL y TRUNC:

• REAL(a): toma un valor de tipo INTEGER o CARDINAL y devuelve el REALequivalente.

• TRUNC(a): toma un valor de tipo REAL y devuelve el INTEGER o CARDINALequivalente. Para ello elimina la parte decimal del número original.

Expresión Equivale a

5.5 + REAL(10) 15.5

5.0 + REAL (10) 15.0

5.0 + 10 ERROR

5 + TRUNC(10.5) 15

5 + TRUNC(10.0) 15

Obsérvese que el tipo del resultado siempre coincide con el tipo de los operandos (REAL en losdos primeros casos e INTEGER o CARDINAL en los dos últimos).

3.5 IdentificadoresEn cualquier programa aparece una serie de datos que son manipulados por éste. La manera dehacer referencia a los diferentes elementos que intervienen en un programa es darles un nombreparticular a cada uno de ellos. En programación, se llaman identificadores a los nombresusados para identificar cada elemento del programa.

En Modula-2, un identificador es una palabra formada por caracteres alfabéticos o numéricosseguidos (sin espacios en blanco o signos de puntuación intercalados) y que debe comenzar poruna letra. Pueden usarse las letras mayúsculas y minúsculas del alfabeto inglés y los dígitos del0 al 9. No se puede usar ni la eñe ni vocales acentuadas en un identificador, aunque sí sepueden usar en valores de tipo carácter y cadenas de caracteres.

Ejemplos de identificadores válidos son:

Indice DiaDelMes Ejemplo1IdentificadorMuyLargo

Ejemplos de identificadores no válidos:

3Ejemplo No pueden comenzar por un dígito

Ejemplo$ No se pueden usar signos de puntuación

Dia Del Mes No se pueden intercalar espacios

Año No se puede usar la eñe

En Modula-2, se distinguen las letras mayúsculas y minúsculas, por lo que son identificadoresdiferentes DiaSemana , Diasemana y DIASEMANA.

La definición de un identificador usando la notación BNF es:

Page 11: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 11

Informática Facultad de Ciencias (Matemáticas)

Identificador ::= Letra { Letra | Dígito }

Dígito ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

Letra ::= A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |

P | Q | R | S | T | U | V | W | X | Y | Z |

a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |

p | q | r | s | t | u | v | w | x | y | z |

Sin embargo, no todos los identificadores construidos usando la definición anterior son válidos.Existen una serie de palabras que tienen un significado especial y que, por tanto, no pueden serusadas como identificadores. Se trata de las palabras reservadas y los identificadorespredefinidos.

La li sta de palabras reservadas en TopSpeed Modula-2 es la siguiente:

AND FORWARD PROCEDURE

ARRAY FROM QUALIFIED

BEGIN GOTO RECORD

BY IF REPEAT

CASE IMPLEMENTATION RETURN

CONST IMPORT SET

DEFINITION IN THEN

DIV LABEL TO

DO LOOP TYPE

ELSE MOD UNTIL

ELSIF MODULE VAR

END NOT WHILE

EXIT OF WITH

EXPORT OR

FOR POINTER

La li sta de identificadores predefinidos en TopSpeed Modula-2 es la siguiente:

ABS FLOAT ODD

ADDRESS HALT ORD

ADR HIGH PROC

BITSET INC REAL

BOOLEAN INCL SHORTADDR

BYTE INTEGER SHORTCARD

CAP LONGCARD SHORTINT

CARDINAL LONGINT SIZE

CHAR LONGREAL TRUE

CHR LONGWORD TRUNC

DEC MAX VAL

DISPOSE MIN VSIZE

EXCL NEW WORD

FALSE NULLPROC

El programador puede redefinir los identificadores predefinidos, aunque esto no es una buenapráctica de programación, ya que confundiría a otros programadores que leyesen el programa yesperasen el significado habitual. Por otro lado, no es posible redefinir las palabras reservadas.

Page 12: Curso de Modula-2 (Incompleto).pdf

12 3.6 Constantes

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

3.6 ConstantesUna constante es un valor fijo que se utili za en un programa. El valor debe ser siempre elmismo en cualquier ejecución del programa.

Algunos ejemplos de constantes son el número de meses del año, el número de días de unasemana y la constante matemática π.

Es posible asociar un nombre a una constante mediante una declaración de constante. Asípodemos asignar al identificador PI el valor 3.141592 mediante la siguiente declaración:

CONST PI = 3.141592;

La declaración se inicia con la palabra reservada CONST, seguida del nombre de la constanteque se está definiendo, el signo igual y por último, el valor asociado. La declaración terminacon un punto y coma.

Una vez definida la constante puede utili zarse en expresiones. Las siguientes expresiones sonequivalentes:

2. * 3.141592 2. * PI

También es posible declarar más de una constante a la vez en un programa. Para ello secomienza con la palabra reservada CONST y se prosigue con las distintas declaracionesseparadas por punto y coma:

CONSTDIASSEMANA = 7;MESESANYO = 12;NUMEROE = 2.718281;LETRAPUNTO = '.';

Como puede observarse, es habitual definir una constante en cada línea de texto y situar elcomienzo de cada declaración de constante a la misma altura horizontal dentro de la línea. Aesta práctica se llama indentación. No es obligatoria pero si bastante conveniente ya quemejora la legibili dad del programa.

Cada constante tiene asociado de modo automático un tipo:

DIASSEMANA Tipo INTEGER o CARDINAL

MESESANYO Tipo INTEGER o CARDINAL

NUMEROE Tipo REAL o LONGREAL

LETRAPUNTO Tipo CHAR

Es posible declarar el valor de una constante mediante una expresión siempre que todos losoperandos que intervengan en ésta sean valores constantes y que las operaciones seanpredefinidas del lenguaje:

CONSTRADIO = 5.3;DIAMETRO = 2 .0*RADIO;

La notación BNF para las declaraciones de constantes es la siguiente:

Declaración_de_Constantes ::= CONST { Asociación_de_Constante ; }

Asociación_de_Constante ::= Identificador = Expresión _Constante

Expresión_Constante ::= ...

Definiremos qué es una expresión constante en temas posteriores.

Page 13: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 13

Informática Facultad de Ciencias (Matemáticas)

3.7 VariablesEl concepto de variable en programación es distinto al concepto de variable algebraica. Lasvariables algebraicas representan valores de modo que una vez asociada la variable a un valordeterminado dicho valor no cambia.

❏ Ejemplo: Sea la siguiente ecuación:

12 =x

el valor asociado a la variable x en este caso es x = ½.

En programación el concepto de variable es distinto y está asociado a la memoria delordenador. La memoria del ordenador mantiene, además de las instrucciones del programa, unaserie de datos. Una vez que el programa almacena un dato en una de las posiciones de lamemoria su valor se mantiene. Sin embargo, es posible modificar el valor cuantas veces sedesee.

Una variable representa un valor almacenado en la memoria del ordenador, el cual puede serusado tantas veces como se desee. El valor de la variable puede ser modificado en cualquiermomento, y será el nuevo valor el que estará almacenado en ella a partir de entonces.

Podemos ver una variable como una caja en la cual es posible almacenar un único valor en unmomento dado. Es posible en todo momento consultar cuál es el valor almacenado en la caja.También es posible almacenar un nuevo valor en la caja de modo que el valor antiguo se pierdey el valor de la caja pasa a ser desde ese momento el nuevo valor almacenado.

Las variables de un programa se designan mediante nombres o identificadores. El identificadorde una variable representa el valor almacenado en dicha variable. El programador puede elegirlos nombres más apropiados para las variables que utili ce en su programa.

3.7.1 Declaración d e variables

En un programa en Modula-2 es necesario declarar cada una de las variables que se utili ce. Paracada variable usada es necesario especificar su nombre y el tipo de valores que puede tomar.Esto quiere decir que si una variable se declara con tipo INTEGER, por ejemplo, podráalmacenar en un momento un único valor entero (un 3, un –20 ó 15000) pero no podráalmacenar un valor de otro tipo (CHAR o REAL, por ejemplo).

❏ Ejemplo: Para usar una variable cuyo nombre sea Edad y que almacene un valor de tipoentero es necesario declararla del siguiente modo:

VAR Edad : INTEGER;

Como puede observarse, una declaración de variable consta de la palabra reservada VAR seguidadel nombre de la variable, un signo de dos puntos y el nombre del tipo de valor que puedetomar la variable. La declaración termina con un punto y coma.

Es posible declarar más de una variable usando una única palabra VAR:

VAR Dia : INTEGER;Mes : INTEGER;Anyo : INTEGER;Letra : CHAR;

Page 14: Curso de Modula-2 (Incompleto).pdf

14 3.7 Variables

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Si varias variables tienen el mismo tipo pueden declararse conjuntamente escribiendo susnombres seguidos, separados por comas. El ejemplo anterior puede escribirse de formaabreviada:

VAR Dia, Mes, Anyo : INTEGER;Letra : CHAR;

La descripción BNF de la declaración de variables es la siguiente:

Declaración_de_Variables ::= VAR { Lista_de_Variables ; }

Lista_de_Variables ::= Lista_de_Identificadores : Tipo

Lista_de_Identificadores ::= Identificador { , Identificador }

Tipo ::= INTEGER | CARDINAL | REAL | LONGREAL | CHAR | ...

La definición de Tipo se completará en temas posteriores.

3.7.2 Sentencia de asignación

La forma de conseguir que una variable guarde un nuevo valor es mediante la sentencia deasignación. Mediante esta sentencia es posible:

• Inicializar una variable: una variable declarada contiene un valor indeterminado hasta queexplícitamente se le da uno. Al hecho de dar un valor inicial a una variable se le llamainicialización de la variable.

• Modificar el valor que tenga: es posible modificar el valor que tenga una variable de modoque desde ese momento pase a contener un nuevo valor.

La forma de la sentencia de asignación es la siguiente:

Sentencia_de_Asignación ::= Nombre_de_Variable := Expresión

Nombre_de_Variable ::= Identificador

Expresión ::= ...

Una sentencia de asignación consta del nombre de la variable que se quiere modificar, eloperador de asignación (los caracteres dos puntos e igual seguidos y sin espacios entre ellos) yuna expresión que indica el nuevo valor de la variable.

El modo en el cual se ejecuta una sentencia de asignación es el siguiente:

1) Se calcula el resultado correspondiente a la expresión que aparece a la derecha deloperador de asignación.

2) Se almacena el valor calculado en la variable cuyo nombre aparece a la izquierda deloperador de asignación.

Para que una sentencia de asignación sea correcta es imprescindible que el tipo de la expresióna la derecha del operador de asignación sea compatible con el tipo declarado para la variablecuyo nombre aparece a la izquierda. Suponiendo las siguientes declaraciones de variables:

VAR Num1 : INTEGERNum2 : CARDINAL;Num3 : REAL;Letra1, Letra2 : CHAR;

son válidas las siguientes sentencias de asignación:

Num1:= -10;

Page 15: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 15

Informática Facultad de Ciencias (Matemáticas)

Num2:= 32+24;Num3:= 1.5E2;Letra1 := ‘1’;Letra2 := ‘Ñ’;

NOTA: En Modula-2 es necesario separar las distintas instrucciones del programa con elsímbolo punto y coma (;). Además es habitual escribir cada instrucción en una línea. Estoúltimo no es obligatorio.

Sin embargo, las siguientes asignaciones no son válidas:

Num1 := 40000; El valor máximo para un dato INTEGER es 32767

Num2 := -20; Un dato CARDINAL no puede tomar valores negativos.

Num3 := 10; La constante 10 es un entero y Num3 es REAL;

Letra1 := 1; Letra1 debe almacenar un carácter, no un número

Letra2 := ‘ab’; Letra2 puede almacenar un único carácter

Si intervienen variables o constantes en la expresión a la derecha de una sentencia deasignación, se usará el valor que tengan en dicho momento. Por ejemplo la siguiente secuenciade asignaciones

CONSTDIASSEMANA = 7;

VAR a, b, c : INTEGER;

a := DIASSEMANA;b := 2 * a;c := a + b;

dejará como valores almacenados en las variables a, b y c los valores 7, 14 y 21respectivamente.

Un caso que requiere cierta atención es aquél en el que la variable que está siendo modificadaforma parte de la expresión. Por ejemplo:

a := DIASSEMANA;a := a + 1;

A la hora de ejecutar la segunda sentencia de asignación se siguen los pasos que vimos alprincipio de este apartado:

1) Se calcula el valor de la expresión a la derecha del operador de asignación: a + 1 = 7 +1 = 8

2) Se almacena dicho valor en la variable que aparece a la izquierda: el nuevo valor de lavariable a pasa a ser 8.

Como puede observarse, la sentencia a := a + 1 tiene como resultado que la variable a vea suvalor incrementado en una unidad. También es posible decrementar el valor de una variable enun unidad (a := a – 1 ), o en cualquier número de unidades (a := a + 20 hace que el valoralmacenado en la variable a aumente en veinte unidades).

Dado que es muy habitual incrementar y decrementar el valor de variables Modula-2 cuentacon dos instrucciones para ello INC y DEC:

INC(x) ≡ x := x + 1

DEC(x) ≡ x := x + 1

INC(x, 10) ≡ x := x + 10

Page 16: Curso de Modula-2 (Incompleto).pdf

16 3.8 Operaciones de Entrada y Salida

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

DEC(x, 10) ≡ x := x - 10

Veamos un ejemplo de cómo van modificándose los valores de las variables durante laejecución de un pequeño programa:

VAR Posi : CARDINAL;Dato : INTEGER;EjeX, EjeY : REAL;

EjeX EJeY Dato Posi Sentencias

? ? ? ? Ejex := 34.89;

34.89 ? ? ? Dato := 67;

34.89 ? 67 ? Posi := TRUNC(EjeX) + Dato;

34.89 ? 67 101 Dato := TRUNC(EjeY) + Posi;

34.89 ? ? 101 EjeY := EjeX + REAL(Posi);

34.89 135.89 ? 101 Dato := Posi DIV 5;

34.89 135.89 20 101

3.8 Operaciones de Entrada y SalidaLa mayoría de los programas necesitan una serie de datos. Estos datos suelen ser introducidospor una persona usando alguna unidad de entrada (generalmente el teclado del ordenador). Senecesitan instrucciones que permitan a un programa escrito en Modula-2 pedir un dato desde elteclado (o desde otra unidad de entrada) y guardarlo en una variable. A este tipo deinstrucciones se les llama operaciones de entrada.

De un modo similar, la mayoría de los programas suelen calcular unos resultados que hay queemiti r al exterior a través de una unidad de salida (generalmente la pantalla del ordenador).Necesitamos instrucciones que permitan a un programa escrito en Modula-2 enviar resultadosal exterior. A este tipo de instrucciones se les denomina operaciones de salida.

En Módula-2 las instrucciones para efectuar E/S se encuentran en módulos de biblioteca, esdecir, módulos preprogramados disponibles para el programador. La biblioteca donde estánimplementadas estas instrucciones depende del compilador de Modula-2 que se utili ce. En elcaso de Top Speed Modula-2 están contenidas en la biblioteca IO (Input-Output) y se describena continuación.

3.8.1 Operaciones de Salida

Las principales operaciones de salida definidas en el modulo de biblioteca IO son lassiguientes:

• WrChar(c) : escribe en pantalla el valor de c que debe ser una expresión de tipo CHAR.

El siguiente trozo de programa:

WrChar(‘h’);WrChar(‘o’);WrChar(‘l’);WrChar(‘a’);WrChar( CHR( ORD(‘!’)));

producirá la siguiente salida en la pantalla del ordenador:

hola!

Page 17: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 17

Informática Facultad de Ciencias (Matemáticas)

• WrLn: hace que el resultado correspondiente a la próxima operación de salida se muestre enla siguiente línea de pantalla.

El siguiente trozo de programa:

WrChar(‘h’); WrLn;WrChar(‘o’); WrLn;WrChar(‘l’); WrLn;WrChar(‘a’); WrLn;WrChar( CHR( ORD(‘!’)));

producirá la siguiente salida en la pantalla del ordenador:

h

o

l

a

!

• WrStr(s) : escribe la cadena de caracteres s en pantalla.

El siguiente trozo de programa:

WrStr(‘hola b¿qué hay?’); WrLn;WrStr(‘entre “comillas”’);

producirá la siguiente salida en la pantalla del ordenador:

hola b¿qué hay?

entre “comillas”

• WrInt(i,a) : escribe en pantalla el valor de i que debe ser una expresión de tipoINTEGER. El valor de a indica el número de posiciones reservadas para escribir i en lapantalla. En caso de que i requiera un número de posiciones menor del reservado, lasposiciones sobrantes se rellenarán con espacios en blanco. Si el número de posicionesindicado por a es menor que el número de caracteres necesarios para imprimir i , seimprimirá i ignorando lo indicado por a.

El siguiente trozo de programa:

WrInt(123,5); WrLn;WrInt(45,1); WrLn;WrInt(67,0); WrLn;WrInt(-89,6); WrLn;WrInt(1000+500, 6);

producirá la siguiente salida en la pantalla del ordenador:

bb123

45

67

bbb- 89

bb1500

Es habitual utili zar un ancho cero, de este modo el valor ocupará tantas posiciones enpantalla como necesite.

Page 18: Curso de Modula-2 (Incompleto).pdf

18 3.8 Operaciones de Entrada y Salida

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

• WrCard(c,a) : idéntico al anterior, pero el valor c debe ser de tipo CARDINAL.

• WrReal(r,p,a) : Escribe el valor de la expresión r , que debe ser de tipo REAL, enpantalla. Los números reales siempre se muestran usando notación científica y con un únicodígito en la parte entera. El significado de a es el mismo que en WrInt . Se mostrarán p-1cifras en la parte fraccionaria.

El siguiente trozo de programa:

WrReal(1.2345, 1, 10); WrLn;WrReal(1.2345, 2, 10); WrLn;WrReal(12.345, 5, 0); WrLn;WrReal(12.345, 6, 0); WrLn;

producirá la siguiente salida en la pantalla del ordenador:

bbbbb 1.E+0

bbbb1.2E+0

1.2345E+1

1.23450E+1

• WrLngReal(r,p,a) : igual al anterior pero r debe ser una expresión de tipo LONGREAL.

NOTA: El símbolo b representa un espacio en blanco.

3.8.2 Operaciones de Entrada

Las principales operaciones de entrada definidas en el módulo de biblioteca IO son lassiguientes:

• RdChar() : lee un dato de tipo CHAR del teclado.

• RdInt() : lee un número de tipo INTEGER del teclado.

• RdCard() : lee un número de tipo CARDINAL del teclado.

• RdReal() : lee un número de tipo REAL del teclado.

• RdLngReal() : lee un número de tipo LONGREAL del teclado.

Estas instrucciones se usan de la misma forma que un valor dentro de programa, por lo que no

pueden aparecer como instrucciones aisladas dentro del mismo (cosa que ocurría con las de

salida vistas anteriormente) sino sólo formando parte de una expresión.

El modo usual de utili zar estas operaciones es mediante una sentencia de asignación, en cuyaparte izquierda aparece el nombre de la variable en la cual se quiere guardar el valor leído delteclado. En la parte derecha de la sentencia de asignación aparece la operación de entrada. Eltipo de la variable en la parte izquierda debe coincidir con el tipo de dato que lee la operación.

Tras cada llamada a una de estas funciones, el programa se detiene a la espera de que el usuariointroduzca un valor. Cuando el usuario introduce el dato y pulsa la tecla <ENTER>, elprograma continúa ejecutándose y el valor es asignado a la variable en la parte izquierda de lasentencia de asignación.

Tras cada una de estas operaciones de entrada es conveniente ejecutar la operación RdLn (quedebe importarse también del módulo de biblioteca IO) para evitar complicaciones.

El siguiente trozo de programa (suponiendo que la variable Num está declarada con tipoINTEGER) lee un valor entero del teclado, lo almacena en la variable Num, suma 10 al valorleído y muestra el resultado por pantalla:

Page 19: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 19

Informática Facultad de Ciencias (Matemáticas)

Num := RdInt();RdLn;Num := Num + 10;WrInt(Num, 0);

Al ejecutar el programa anterior, el ordenador se detiene al ll egar a la instrucción RdInt() ymuestra un cursor parpadeante para indicar al usuario que está a la espera de que introduzca undato:

_

En este punto el usuario debe introducir el dato y pulsar la tecla <ENTER>:

120_

Al pulsar la tecla <ENTER> el dato 120 es asignado a la variable Num.. Además, el cursor pasaa la siguiente línea de pantalla de modo que la próxima operación de salida comenzará en dichalínea:

120

_

La asignación Num := Num + 10 hace que el valor de la variable Num pase a ser 130. Porúltimo, la operación WrInt(Num,0) muestra el valor de la variable Num con el ancho que seanecesario:

120

130

Es normal preceder las operaciones de entrada con operaciones de salida que indiquen alusuario qué dato debe introducir. El siguiente programa resulta más claro para el usuario:

WrStr(“Introduzca un número entero: “);Num := RdInt();RdLn;Num := Num + 10;WrStr(“El número introducido más diez es: “);WrInt(Num, 0);

Al ejecutar este último programa, el ordenador muestra el mensaje “Introduzca un númeroentero: “ y un cursor parpadeante, lo cual indica que está a la espera de que el usuariointroduzca un dato entero:

Introduzca un número entero: _

Una vez que el usuario introduce el número y pulsa la tecla <ENTER> el cursor pasa a lasiguiente línea:

Introduzca un número entero: 120

_

Page 20: Curso de Modula-2 (Incompleto).pdf

20 3.9 Estructura general de un p rograma. Ejemplo

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Por último, se incrementa en diez el valor de la variable y ejecutan las dos operaciones desalida finales:

Introduzca un número entero: 120

El número introducido más diez es: 130

3.9 Estructura general de un p rograma. EjemploCon los elementos introducidos en este tema es posible escribir programas completos enModula-2. El siguiente ejemplo muestra un programa que lee el radio de un círculo desde elteclado, calcula el área de dicho círculo y lo escribe por pantalla:

MODULE Circulo;FROM IO IMPORT WrStr, RdReal, RdLn, WrReal;CONST

PI = 3.1416; (* El número PI *) PRECISION = 5; (* Nº de dígitos al escribir reales *)

ANCHO = 0; (* Calcular ancho necesario automáticamente *)VAR

Radio, Area : REAL;BEGIN

WrStr(‘Introduce el radio: ‘); Radio := RdReal();

RdLn; Area := PI*Radio*Radio; WrStr(‘El área del círculo es ‘); WrReal(Area,PRECISION,ANCHO)END Circulo.

Podemos distinguir las siguientes partes dentro del programa:

• Cabecera: todo programa debe comenzar con la palabra reservada MODULE seguida deun identificador, que indica el nombre del programa, y un signo punto y coma. En elpresente ejemplo se ha elegido como nombre del programa el identificador Circulo . Elprograma debe finalizar con la palabra reservada END seguida del nombre del programa (elmismo identificador usado en la cabecera) y un punto.

• Listas de importación: a continuación es necesario enumerar los módulos de bibliotecausados por el programa, especificando cada una de las operaciones utili zadas. Los módulosde bibliotecas contienen elementos que se utili zan con frecuencia en el desarrollo dedistintos programas, por lo que están disponibles en el lenguaje, y por lo tanto, no esnecesario programarlos. Para utili zarlos hay que indicarlo en la li sta de importación. Estose puede hacer de dos formas:

1. Forma implícita:

IMPORT NombreBiblioteca;

En este caso se puede utili zar cualquier elemento definido en la biblioteca refiriéndonos aél mediante su nombre precedido por el del módulo.

2. Forma explícita:

FROM NombreBiblioteca IMPORT ListaElementos;

Page 21: Curso de Modula-2 (Incompleto).pdf

Tema 3. Introdu cc ión al lengu aje de programación Modu la-2 21

Informática Facultad de Ciencias (Matemáticas)

En este caso sólo se pueden utili zar los elementos especificados en ListaElementosrefiriéndonos a él sólo por su nombre. Este es el caso del ejemplo.

Cada compilador de Módula-2 tiene sus propias bibliotecas y define las características delos procedimientos que contiene. Este es un aspecto a revisar siempre que, aun usando elmismo lenguaje, cambiemos de compilador.

• Declaraciones: en esta sección se declaran las distintas constantes y variables que sonutili zadas en el programa. El programa ejemplo usa tres valores constantes (PI , PRECISIONy ANCHO) y dos variables de tipo REAL (Radio y Area ).

• Parte Ejecutiva: comienza con la palabra reservada BEGIN y en ella aparecen lasinstrucciones que constituyen el programa, separadas entre sí con el signo punto y coma.

Es posible incluir en cualquier punto del programa un comentario. Un comentario es unasecuencia de caracteres que es ignorada por el compilador. Se usan para documentar elprograma, de manera que aunque no contribuyan a resolver el problema, sí ayudan a mejorar lacomprensión del programa. Se insertan en el programa escribiendo un texto entre los símbolos(* y *) .

Usando la notación BNF, la estructura de un programa en Modula-2 es la siguiente:

Modulo_de_Programa ::= Cabecera_de_Programa

{ Lista_de_Importación }

{ Declaraciones }Parte_Ejecutiva

Fin_de_Programa

Cabecera_de_Programa ::= MODULE Nombre_de_Programa ;

Lista_de_Importación ::= FROM Nombre_de_Biblioteca IMPORT Lista_de_Operaciones ; |IMPORT Nombre_de_Biblioteca ;

Lista_de_Operaciones ::= Nombre_de_Operación { , Nombre_de_Operación }

Declaraciones ::= Declaración_de_Constante | Declaración_de_Variable

Parte_Ejecutiva ::= BEGIN Secuencia_de_Sentencias

Secuencia_de_Sentencias ::= Sentencia { ; Sentencia }

Sentencia ::= Sentencia_de_Asignación | ...

Fin_de_Programa ::= END Nombre_de_Programa .

Nombre_de_Programa ::= Identificador

Nombre_de_Biblioteca ::= Identificador

Nombre_de_Operación ::= Identificador

Podemos observar que tanto la li sta de importación como las declaraciones pueden aparecercero, una o más veces en un programa. Completaremos la definición de sentencia a lo largo delcurso.

Page 22: Curso de Modula-2 (Incompleto).pdf
Page 23: Curso de Modula-2 (Incompleto).pdf

Relación d e prob lemas. Tema 3. 1

Informática Facultad de Ciencias (Matemáticas)

Relación d e Problemas (Tema 3)1. Escribir un programa que lea desde el teclado dos valores de tipo INTEGER y escriba en

pantalla su suma, su diferencia, su producto, su cociente y su resto.

2. Escribir un programa que pida una letra desde el teclado, la pase a mayúscula e imprimael resultado por pantalla.

3. Escribir un programa que lea el radio y la altura de un cili ndro desde el teclado y escribapor pantalla el área y volumen correspondiente.

NOTA: El área y volumen del cili ndro de altura h y radio R es:

Area = 2πR2+2πRh

Volumen = πR2h

4. Escribir un programa que lea desde el teclado una cantidad de segundos y muestre porpantalla el número de horas, minutos y segundos equivalentes.

5. Escribir un programa que lea un carácter del teclado y escriba por pantalla su códigodentro de la tabla ASCII.

6. a) ¿Qué ocurre al ejecutar el siguiente programa?

MODULE Prueba;FROM IO IMPORT WrInt;VAR Num : INTEGER;BEGIN Num := MAX( INTEGER); Num := Num + 10 – 100; WrInt (Num, 0)END Prueba.

b) ¿Cómo puede solucionarse el problema?

c) ¿Qué ocurre si cambiamos el programa por el siguiente?

MODULE Prueba;FROM IO IMPORT WrCard;VAR Num : CARDINAL;BEGIN Num := MAX( INTEGER); Num := Num + 10 – 100; WrCard (Num, 0)END Prueba.

7. Escribe un programa que lea del teclado la longitud de los dos catetos de un triángulorectángulo, calcule la longitud de la hipotenusa y la escriba por pantalla.

8. Escribe un programa que lea la longitud del lado de un cuadrado y escriba en pantalla suárea y su perímetro.

9. Escribe un programa que lea un carácter del teclado y escriba en pantalla el carácter quele sigue en el código ASCII.

Page 24: Curso de Modula-2 (Incompleto).pdf

2 3.9 Estructura general de un p rograma. Ejemplo

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

10. Encuentra los errores en el siguiente programa:

MODULE Erroneo;FROM IO IMPORT WrInt;CONST PRECISION = 2; ANCHO = 0;VAR Num1 : INTEGER; Num2 : CARDINAL; Num3 : REAL;BEGIN Num1 := 10; Num2 := -100; Num3 := 13.; Letra := ‘A’ Num3 := Num3 + 1; WrStr(“Valor número 1: “); WrInt(Num1, ANCHO); WrLn; WrStr(“Valor número 2: “); WrCard(Num2, ANCHO); WrLn; WrStr(Valor número 3:); WrReal(Num3, PRECISION, ANCHO); WrLn; WrStr(“Valor letra: “); WrChar(Letra); WrLnEND Erroneo.

Page 25: Curso de Modula-2 (Incompleto).pdf

Tema 4. Diseño d e Algoritmos. Estructuras de selecc ión 1

Informática. Facultad de Ciencias (Matemáticas)

Departamento de Lenguajes y Ciencias dela Computación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)

http://www.lcc.uma.es/personal/pepeg/mates

Tema 4. Diseño d e Algoritmos. Estructuras deselecc ión

4.1 Composición secuencial de instrucciones........................................................... 2

4.2 Selección entre acciones alternativas................................................................ .2

4.2.1 El tipo BOOLEAN en Modula-2 ................................................................ .....3

4.2.2 Expresiones booleanas................................................................ .................3

4.2.2.1 Operadores relacionales ................................................................ .........3

4.2.2.2 Operadores booleanos................................................................ ............4

4.2.2.3 Evaluación en cortocircuito................................................................ ......6

4.2.3 Sentencias de selección en Modula-2........................................................... 6

4.2.3.1 Sentencia IF THEN ELSIF ELSE............................................................. 6

4.2.3.2 Sentencia CASE................................................................ .................... 10

Bibliografía• Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de

Educación a Distancia.

• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

• Fundamentos de programación. L. Joyanes. McGraw-Hill

Page 26: Curso de Modula-2 (Incompleto).pdf

2 4.1 Composición secuencial de instrucc iones

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

4.1 Composición secuencial de instrucc ionesLa forma más simple de componer instrucciones en un lenguaje de programación es lasecuencia: se ejecutan las distintas acciones una tras otra según su orden físico dentro delprograma. Podemos representar esta forma de composición con el siguiente diagrama de flujo:

Instrucción A

Instrucción B

Figura 1. Composición secuencial de A y B

En Modula-2 la composición de dos instrucciones se consigue escribiendo una tras otra,separándolas por un carácter punto y coma. Por ejemplo, el siguiente programa compone dosinstrucciones de escritura secuencialmente:

MODULE Secuencia;FROM IO IMPORT WrStr;BEGIN

WrStr (“ A “);WrStr (“ B “)

END Secuencia.

La sintaxis BNF de la estructura de secuencia en Modula-2 es:

Secuencia_de_Sentencias ::= Sentencia { ; Sentencia }

4.2 Selecc ión entre acc iones alternativasA la hora de describir algoritmos, puede ser necesario especificar dos o más caminosalternativos a seguir en función de cierta condición. La estructura de selección permite ejecutaruna acción u otra, dependiendo de una determinada condición que se analiza a la entrada de laestructura. El diagrama correspondiente a esta estructura es:

Page 27: Curso de Modula-2 (Incompleto).pdf

Tema 4. Diseño d e Algoritmos. Estructuras de selecc ión 3

Informática. Facultad de Ciencias (Matemáticas)

NoSíCondición

Acción A Acción B

Figura 2. Estructura de selección

Para ejecutar una estructura de selección, se evalúa primero la condición. Si ésta es cierta seejecutará la acción A. Si la condición es falsa se ejecutará la acción B. Veremos posteriormenteque ésta es sólo una de las distintas instrucciones de selección disponibles en Modula-2.

La condición debe ser una expresión booleana: expresión que puede ser cierta o falsa.Estudiamos las expresiones booleanas en los siguientes puntos.

4.2.1 El tipo BOOLEAN en Modu la-2

El tipo BOOLEAN es el tipo de aquellas variables que sólo pueden tomar dos valores:VERDADERO o FALSO, (TRUE y FALSE en Modula-2).

Un ejemplo de uso de datos booleanos puede verse en el siguiente programa, que asigna a lavariable EsAlto el valor VERDADERO y a la variable EsRubio FALSO:

MODULE Booleano;VAR

EsAlto, EsRubio : BOOLEAN;BEGIN

EsAlto := TRUE;EsRubio := FALSE

END Booleano.

Existe una función predefinida que devuelve un valor de tipo booleano. Se trata de la funciónODD. Esta función toma como argumento un número no REAL (de tipo INTEGER oCARDINAL) y devuelve el valor TRUE si el número es impar o FALSE si es par. No existe unafunción predefinida para ver si un número es par, pero puede usarse la expresión NOT ODD.

4.2.2 Expresiones boo leanas

Una de las formas de construir expresiones booleanas es mediante los operadores relacionales.

4.2.2.1 Operadores relacionales

Los operadores relacionales son operadores binarios que permiten comparar dos valores delmismo tipo. Son binarios porque tienen dos argumentos. Los operadores relacionales enModula-2 son:

Page 28: Curso de Modula-2 (Incompleto).pdf

4 4.2 Selecc ión entre acc iones alternativas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

> mayor que< menor que= igual a>= mayor o igual que<= menor o igual que<> # distinto a

Figura 1. Operadores relacionales

Los símbolos con dos caracteres deben escribirse en ese orden y sin separadores entre ellos. Eloperador distinto a puede escribirse de dos formas.

El resultado de una operación relacional es VERDADERO o FALSO, o sea es de tipoBOOLEAN. Así:

2.3 < 8.5 ≡ TRUE

5 < 3 ≡ FALSE

n >= 4 ≡ Es correcta sólo si n es de tipo INTEGER o CARDINAL, y el resultadodepende del valor de n.

‘a’ < ‘d’ ≡ TRUE

‘A’ < 25 ≡ Error, ya que ‘A’ tiene tipo CHAR y 25 tiene tipo INTEGER oCARDINAL

n*m <= x+8 ≡ Es correcta si n,m,x tienen tipo INTEGER o CARDINAL y el resultadodepende de los valores de n, m y x.

Si EsPar es una variable de tipo BOOLEAN y N de tipo INTEGER o CARDINAL podemosescribir sentencias como:

EsPar := (N MOD 2 = 0);

ya que (N MOD 2 = 0) es una expresión booleana, de modo que tras la ejecución de estasentencia EsPar contendrá TRUE si N es un número par y FALSE en otro caso.

4.2.2.2 Operadores boo leanos

Podemos construir expresiones booleanas más complicadas con los operadores booleanos.Estos son:

AND & Conjunción lógicaOR Disyunción lógicaNOT ~ Negación lógica

Figura 2. Operadores booleanos

Los dos primeros operadores son binarios, mientras que el último es unario (tiene un únicoargumento). A diferencia de los operadores relacionales, los tipos de los argumentos deben serexpresiones booleanas (no son válidas expresiones de cualquier tipo).

La expresión A AND B es cierta si tanto A como B son ciertas. La expresión A OR B es cierta siA es cierta o B es cierta o si ambas son ciertas. Por último NOT A es cierta si y sólo si A es falsa.Podemos expresar esto mediante la siguiente tabla de verdad:

Page 29: Curso de Modula-2 (Incompleto).pdf

Tema 4. Diseño d e Algoritmos. Estructuras de selecc ión 5

Informática. Facultad de Ciencias (Matemáticas)

A B A AND B A OR B NOT A

TRUE TRUE TRUE TRUE FALSE

TRUE FALSE FALSE TRUE

FALSE TRUE FALSE TRUE TRUE

FALSE FALSE FALSE FALSE

Figura 3. Tabla de verdad de los operadores booleanos

Podemos construir expresiones complejas combinando estos operadores con los relacionales:

(x>=5)AND(x<=10) ≡ TRUE si x ∈ [5,10] (x ha de tener tipo INTEGER oCARDINAL)

EsAlto OR EsRubio ≡ TRUE si es alto o rubio (EsAlto y EsRubio deben tenertipo BOOLEAN)

((x>=5)AND(x<=10))

OR

((x>=20)AND(x<=25))

≡ TRUE si x ∈ [5,10] o x ∈ [20,25] (x debe tener tipoINTEGER o CARDINAL)

NOT EsAlto ≡ TRUE si no es alto (EsAlto debe tener tipo BOOLEAN)

Es necesario manejar correctamente estos operadores y conocer algunas equivalencias lógicasque permiten simpli ficar estas expresiones. Así, por ejemplo:

NOT (A = B) ≡ A <> B

NOT (A AND B) ≡ (NOT A) OR (NOT B)

NOT (A OR B) ≡ (NOT A) AND (NOT B)

Estas igualdades se pueden demostrar mediante una tabla de verdad. En estas tablas seevalúan las expresiones con todas las combinaciones de argumentos posibles y se compruebaque siempre se obtiene el mismo resultado. Por ejemplo, para demostrar la segundaequivalencia la tabla de verdad es:

Α Β Α & Β ∼( Α & Β) ( ∼Α) ( ∼Β) ( ∼Α)OR( ∼Β)

TRUE TRUE TRUE FALSE FALSE FALSE FALSE

TRUE FALSE FALSE TRUE FALSE TRUE TRUE

FALSE TRUE FALSE TRUE TRUE FALSE TRUE

FALSE FALSE FALSE TRUE TRUE TRUE TRUE

Figura 4. Tabla de verdad, para equivalencia de expresiones

A la hora de construir una expresión booleana debemos de tener en cuenta la precedencia de losoperadores. Así la expresión NOT X AND Y , con X = FALSE e Y = FALSE , tendría valor TRUE siprimero actúa el operador AND y FALSE si primero actúa NOT.

Para evitar este tipo de ambigüedades se establece una prioridad entre los operadores booleanos(igual que ocurre con los operadores aritméticos +, -, ...). En Modula-2, si no utili zamosparéntesis, el orden de evaluación es el siguiente:

1º Operador de negación: NOT ∼ + - (unarios)

2º Operadores de multipli cación: * / DIV MOD AND &

3º Operadores de adición: + - OR

4º Operadores de relacionales: < > = >= <= <> #

Page 30: Curso de Modula-2 (Incompleto).pdf

6 4.2 Selecc ión entre acc iones alternativas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Dentro del mismo nivel las expresiones se evalúan en el orden en que están escritas, es decir, deizquierda a derecha.

El ejemplo citado anteriormente se corresponde con (NOT X) AND Y. Si hubiésemos queridoexpresar la otra posibili dad deberíamos haber usado paréntesis: NOT (X AND Y) . Es buenacostumbre usar paréntesis, aunque no sean necesarios, para aclarar el significado deexpresiones complejas.

Por último, veamos la sintaxis para las expresiones (booleanas y aritméticas) en Modula-2 (porahora):

Expresión ::= Expresión_simple [ Operador_Comparador Expresión_Simple]

Expresión_Simple ::= [+|- ] Termino {Operador_Sumador Término}

Término ::= 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 | &

Valor_Constante ::= Valor_Entero | Valor_Real | Valor_Carácter | Valor_Cadena | Valor_Bool

Valor_Bool ::= TRUE | FALSE

4.2.2.3 Evaluación en cortocircuito

El modo en que Modula-2 evalúa las expresiones booleanas se llama evaluación encortocircuito. En Modula-2 no siempre se evalúa la expresión completa, sino sólo aquella parteque es necesaria para conocer el valor. Así, si en una expresión conjunción (AND) el primertérmino es FALSE, no es necesario evaluar el resto de la expresión, ya que el resultado globalde la expresión será FALSE. Por ejemplo dada la siguiente expresión:

(b > 10) AND (a MOD b = 0)

si b es menor o igual que 10, no se evaluará la segunda parte de la expresión. Lo mismo ocurresi la expresión global es una disyunción (OR) y la primera subexpresiones es TRUE. En estecaso, la expresión global tendrá como resultado TRUE sin que se evalúe el resto de laexpresión.

Debido a esto, la propiedad conmutativa no se cumple en general al utili zar operadoresbooleanos. Por ejemplo, la expresión (10 > 7) OR (100 DIV 0 = 3) será evaluada a TRUE,ya que, al evaluarse la primera parte de la disyunción (10 > 7) a TRUE, la segunda parte (100

DIV 0 = 3) no es evaluada. Sin embargo, la evaluación de la expresión (100 DIV 0 = 3)

OR (10 > 7) hace que se produzca un error, ya que al intentar evaluar la primera parte (100

DIV 0 = 3) se produce un error debido a la división por cero.

4.2.3 Sentencias de selecc ión en Modu la-2

Existen dos sentencias de selección en Modula-2: la binaria y la múltiple. Pasamos a estudiarcada una de ellas.

4.2.3.1 Sentencia IF THEN ELSIF ELSE

En Modula-2 la sentencia de selección binaria puede adoptar la siguiente forma:

Page 31: Curso de Modula-2 (Incompleto).pdf

Tema 4. Diseño d e Algoritmos. Estructuras de selecc ión 7

Informática. Facultad de Ciencias (Matemáticas)

IF Condición THENAcción A

ELSEAcción B

END

La ejecución de esta sentencia consiste en evaluar primero la condición. Si ésta es verdadera(TRUE), se ejecuta la acción A. En otro caso, si la condición fuese falsa (FALSE), se ejecutaríala acción B. Siempre se ejecuta alguna acción, o bien A o bien B, pero nunca ambas. Eldiagrama de flujo correspondiente es:

NoSíCondición

Acción A Acción B

Figura 5. Selección binaria

La condición debe ser una expresión de tipo BOOLEAN. Las palabras IF THEN ELSE ENDsepararan las distintas partes de la sentencia (condición, acción A y acción B). Un ejemplo deuso de la sentencia es el siguiente:

IF ODD(N) THENWrStr (“El nº es impar”)

ELSEWrStr (“El nº es par”)

END

A veces no es necesario hacer nada si la condición no se cumple. En este caso la sentencia deselección puede carecer de la parte ELSE:

IF Condición THENAcción

END

El diagrama de flujo en este caso es:

Page 32: Curso de Modula-2 (Incompleto).pdf

8 4.2 Selecc ión entre acc iones alternativas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

NoSíCondición

Acción

Figura 6. Selección simplificada

No hay restricciones sobre el tipo de sentencias que puede aparecer en una rama de unasentencia de selección. Puede, por ejemplo, aparecer una secuencia de sentencias

IF x < 0 THENx := -x;WrStr (“Signo cambiado”)

ELSEWrStr (“Signo sin cambiar”)

END

También puede aparecer otra sentencia de selección. A esto es lo que se llama anidamientode sentencias de selección. Un ejemplo de anidamiento es el siguiente trozo de programa,que escribe la cali ficación correspondiente a la nota contenida en la variable REAL Nota :

IF Nota < 5.0 THENWrStr (“Suspenso”)

ELSEIF Nota < 7.0 THEN

WrStr (“Aprobado”)ELSE

IF Nota < 9.0 THENWrStr (“Notable”)

ELSEIF Nota < 10.0 THEN

WrStr (“Sobresaliente”)ELSE

WrStr (“Matrícula”)END

ENDEND

END

A la estructura anterior también se llama selección en cascada. El diagrama de flujocorrespondiente al ejemplo es:

Page 33: Curso de Modula-2 (Incompleto).pdf

Tema 4. Diseño d e Algoritmos. Estructuras de selecc ión 9

Informática. Facultad de Ciencias (Matemáticas)

NoSíNota < 5.0

EscribirSuspenso

NoSíNota < 7.0

EscribirAprobado

NoSíNota < 9.0

Escribir Notable

NoSíNota < 10.0

EscribirSobresaliente

EscribirMatrícula

Figura 7. Selección en cascada

Este tipo de situaciones es habitual, por lo que Modula-2 posee una sintaxis más simple paraestos casos. Se usa para ello la palabra reservada ELSIF. El ejemplo anterior se puede escribirtambién del siguiente modo:

IF Nota < 5.0 THENWrStr (“Suspenso”)

ELSIF Nota < 7.0 THENWrStr (“Aprobado”)

ELSIF Nota < 9.0 THENWrStr (“Notable”)

ELSIF Nota < 10.0 THENWrStr (“Sobresaliente”)

ELSEWrStr (“Matrícula”)

END

Obsérvese que el significado de la selección en cascada es distinto al del siguiente código (quese corresponde con una secuencia de sentencias de selección):

IF Nota < 5.0 THENWrStr (“Suspenso”)

END;IF (Nota >= 5.0) AND (Nota < 7.0) THEN

WrStr (“Aprobado”)END;IF (Nota >= 7.0) AND (Nota < 9.0) THEN

WrStr (“Notable”)END;IF (Nota >= 9.0) AND (Nota < 10.0) THEN

WrStr (“Sobresaliente”)END;IF Nota = 10.0 THEN

WrStr (“Matrícula”)END;

El diagrama de flujo para éste último trozo de código es:

Page 34: Curso de Modula-2 (Incompleto).pdf

10 4.2 Selecc ión entre acc iones alternativas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

NoSíNota < 5.0

EscribirSuspenso

NoSí Nota ∈[5.0,7.0)

EscribirAprobado

NoSíNota = 10.0

EscribirMatrícula

Figura 8. Selección NO en cascada

En la selección en cascada, una vez que una condición es cierta no se comprueba ninguna otra.Aquí siempre se comprueban todas las condiciones. La selección en cascada es más eficiente.

La sintaxis BNF de la sentencia de selección es:

Sentencia_IF ::= IF Expresión THEN Secuencia_de_Sentencias

{ ELSIF Expresión THEN Secuencia_de_Sentencias }

[ ELSE Secuencia_de_Sentencias ]END

donde Expresión debe ser obligatoriamente de tipo BOOLEAN.

4.2.3.2 Sentencia CASE

La sentencia de selección múltiple se utili za para ejecutar distintas sentencias en función de losdistintos valores que pueda tomar una expresión. El esquema de esta sentencia es:

CASE Expresión OFlistas de valores : acción |listas de valores : acción |

ELSEacción por defecto

END

Para ejecutar esta sentencia, se evalúa primero la expresión. A continuación, se inspeccionanlas distintas li stas de valores, hasta encontrar una con un valor que coincida con el resultado de

Page 35: Curso de Modula-2 (Incompleto).pdf

Tema 4. Diseño d e Algoritmos. Estructuras de selecc ión 11

Informática. Facultad de Ciencias (Matemáticas)

la expresión. La acción correspondiente a ese valor es ejecutada. Si el resultado de la expresiónno aparece en ninguna de las li stas, se ejecuta la acción por defecto.

El siguiente ejemplo muestra el código para un trozo de programa que escribe el nombre del díade la semana almacenado en la variable Dia (de tipo CARDINAL):

CASE Dia OF1 : WrS tr (“Lunes”) |2 : WrStr (“Martes”) |3 : WrStr (“Miercoles”) |4 : WrStr (“Jueves”) |5 : WrStr (“Viernes”) |6 : WrStr (“Sábado”) |7 : WrStr (“Domingo”)

ELSEWrStr (“Error: día no válido”)

END;

A cada caso se puede asociar más de un valor. Esto puede hacerse de tres formas:

• Separando distintos valores con comas. (por ejemplo 1,2,3)

• Escribiendo dos valores separados por dos puntos. En este caso se está especificandoun rango de valores. (por ejemplo 1..5)

• Combinando estas dos formas. (por ejemplo 1, 3..4)

La siguiente sentencia escribe si el número almacenado en la variable Dia corresponde a un díalaborable o no:

CASE Dia OF1..5 : WrStr (“Laborable”) |6 : WrStr (“Depende”) |7 : WrStr (“Festivo”)

ELSEWrStr (“Error: día no vál ido”)

END;

Algunas reglas relativas a esta sentencia son:

• La alternativa ELSE puede no aparecer, pero si el resultado de la expresión no coincidecon ninguno de los casos, el programa acabará con un error (sin embargo, esto noocurre en TopSpeed Modula-2). Si queremos que para ciertos valores no se haga nada,entonces estos valores se deben de asociar con una acción vacía.

• Un mismo valor nunca puede aparecer en distintas alternativas.

• El tipo de la expresión a evaluar no puede ser REAL. Ha de ser un tipo ordinal.

• Los distintos valores en las alternativas son expresiones constantes (no puedenintervenir variables)

• El tipo de la expresión y de los distintos valores debe coincidir.

La sintaxis BNF para esta sentencia es:

Page 36: Curso de Modula-2 (Incompleto).pdf

12 4.2 Selecc ión entre acc iones alternativas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Sentencia_CASE ::= CASE Expresión OF

Caso { | Caso }

[ ELSE Secuencia_de_sentencias ]END

Caso ::= Lista_de_Valores : Secuencia_de_Sentencias

Lista_de_Valores ::= Valores { , Valores }

Valores ::= Expresión_Constante [ .. Expresión_Constante ]

La sentencia de selección múltiple es equivalente a la selección en cascada (esta última será laque debamos usar cuando el tipo de expresión sea REAL):

CASE Expresión OFv1 :

SentenciaA |v2..v4 :

SentenciaB |v5,v6,v7 :

SentenciaC |...

ELSESentenciaH

END

≡≡

Valor := Expresión;IF Valor = v1 THEN

SentenciaAELSIF (Valor >= v2) AND (Valor <= v4)THEN

SentenciaBELSIF (Valor = v5) OR (Valor = v6) OR (Valor = v7) THEN

SentenciaC...ELSE

SentenciaH

END

Page 37: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 4) 1

Informática. Facultad de Ciencias (Matemáticas)

Relación d e Problemas (Tema 4)1. Si la variable valor es de tipo BOOLEAN, ¿cómo se puede escribir de otro modo la

condición o pregunta valor = TRUE ?, ¿ y valor = FALSE ?.

2. Si la variable cierto es de tipo BOOLEAN, y a, b son de tipo INTEGER, ¿a qué sonequivalentes las siguientes expresiones ?

i) cierto := (a<b) AND (b<a)

ii ) cierto := (a<=b) OR (b<=a)

3. Si x e y son variables de tipo BOOLEAN, ¿cuál es la relación entre las siguientes dosexpresiones?:

i) x <> y

ii ) (x OR y) AND NOT (x AND Y)

Demuéstralo mediante una tabla de verdad.

4. Si p, q y r son variables booleanas, comprueba las siguientes igualdades usando tablas deverdad:

i) (p OR r) AND (q OR r) ≡ (p AND q) OR r

ii ) (p AND r) OR (q AND r) ≡ (p OR q) AND r

5. Escribe un programa que determine el mayor de tres números enteros.

6. Escribe un programa que sin utili zar sentencias de asignación escriba ordenados de menora mayor tres números almacenados en variables de tipo entero.

7. Escribe un programa que dado un número entero introducido por teclado compruebe si espar o no.

8. Escribe un programa que lea tres números d, m y a que representan una fecha (día, mes yaño) y calcule el día de la semana correspondiente usando la congruencia de Zeller:

día = (700 + (26x - 2) DIV 10 + d + y + y DIV 4 + z DIV 4 - 2z) MOD 7

donde los valores de x, y, z son:

si m ≤ 2 si m ≥ 3

x m + 10 m - 2

y (a - 1) MOD 100 a MOD 100

z (a - 1) DIV 100 a DIV 100

El valor de día estará entre 0 y 6, (0 significa Domingo, 1 Lunes, etc. )

NOTA: Este algoritmo es solo válido para el calendario gregoriano, que fue introducidoen distintos países en distintas fechas (el 14 de Septiembre de 1942 en Inglaterra, porejemplo).

9. Escribe un programa que determine el menor número de monedas y bill etes de curso legalequivalentes a cierta cantidad de pesetas leídas del teclado.

NOTA: Considera que existen bill etes de 10.000, 5.000, 2.000, 1.000 y monedas de 500,100, 25, 5 y 1 pesetas.

10. Escribe un programa que lea dos letras minúsculas y determine:

Page 38: Curso de Modula-2 (Incompleto).pdf

2 Relación d e Problemas (Tema 4)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

• el número de letras que las separan

• la letra o dos letras centrales del intervalo que determinan, pero en mayúsculas

11. Escribe un programa que determine si un año es bisiesto. Un año es bisiesto si es múltiplode 4 (por ejemplo 1984). Sin embargo, los años múltiplos de 100 sólo son bisiestoscuando a su vez son múltiplos de 400 (por ejemplo 1800 no es bisiesto, mientras que 2000lo será).

12. Escribe un programa que calcule el número de días de un mes, dados los valoresnuméricos del mes y año.

NOTA: considera los años bisiestos para Febrero.

13. El domingo de Pascua es el primer domingo después de la primera luna llena posterior alequinoccio de primavera, y se determina mediante el siguiente cálculo sencill o:

A = año MOD 19

B = año MOD 4

C = año MOD 7

D = (19 * A + 24) MOD 30

E = (2 * B + 4 * C + 6 * D + 5) MOD 7

N = (22 + D + E)

Donde N indica el día del mes de Marzo si N es menor o igual que 31 o Abril si es mayorque 31 (el 32 indicaría el 1 de Abril ). Construye un programa que determine fechas dedomingos de Pascua.

14. Escribe un programa que dados los conjuntos de puntos pertenecientes a la circunferenciacuya ecuación es x2 + y2 = 16, a la elipse x2/36 + y2 /16 = 1 y a la recta y = 2x + 1, indiquepara una pareja de coordenadas x e y , leídas desde el teclado, el conjunto o conjuntos alos que pertenece.

15. Un sistema de ecuaciones lineales:

ax + by = c

dx + ey = f

se puede resolver con las siguientes fórmulas:

x = (ce - bf) / (ae - bd)

y = (af - cd) / (ae - bd)

Diseña el programa que lea los coeficientes a, b, c, d, e, f y muestre los valores de x e y.

NOTA: Estudia el caso en que (ae - bd) = 0.

16. Desarrolla un programa que calcule las raíces correspondientes a una ecuación desegundo grado ax2 + bx + c = 0.

NOTA: Estudia el caso de raíces complejas (valor del discriminante < 0) y el caso a = 0.

17. Escribe un programa que lea un número de tipo CARDINAL, y si tiene exactamentecuatro cifras, escriba si es capicúa o no.

18. Escribe un programa que lea un número de tipo CARDINAL, y si tiene exactamentecuatro cifras, escriba si el número es igual a la suma de los cuadrados de sus cifras.

Page 39: Curso de Modula-2 (Incompleto).pdf

Tema 5. Estructuras iterativas 1

Informática. Facultad de Ciencias (Matemáticas)

Departamento de Lenguajes y Ciencias dela Computación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)

http://www.lcc.uma.es/personal/pepeg/mates

Tema 5. Estructuras iterativas

5.1 Bucles................................................................ ................................ .................2

5.2 Estructuras iterativas en Modula-2................................................................ ......3

5.2.1 La sentencia FOR ................................................................ ......................... 3

5.2.2 La sentencia WHILE ................................................................ ..................... 7

5.2.3 La sentencia REPEAT................................................................ ...................8

5.2.4 Las sentencias LOOP y EXIT................................................................ ......10

5.3 Diseño de bucles ................................................................ .............................. 13

5.3.1 Anidamiento de bucles................................................................ ................13

5.3.2 Bucles infinitos ................................................................ ............................ 14

Bibliografía• Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de

Educación a Distancia.

• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

• Fundamentos de programación. L. Joyanes. McGraw-Hill .

Page 40: Curso de Modula-2 (Incompleto).pdf

2 5.1 Bucles

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Introdu cc iónLas estructuras de selección, estudiadas en el tema anterior, no son suficientes para describircualquier algoritmo. Es habitual que ciertas partes de un algoritmo deban repetirse varias vecescon objeto de resolver un problema. La repetición es un concepto importante a la hora dedescribir algoritmos. Los lenguajes de programación disponen de una serie de sentencias quepermiten repetir varias veces algunos segmentos del programa. A este tipo de sentencias se lesdenomina sentencias iterativas. En este tema, estudiamos las sentencias iterativas queposee el lenguaje de programación Modula-2.

5.1 BuclesUn término muy utili zado en el argot informático es bucle. Un bucle es un segmento dealgoritmo que se repite varias veces. Podemos distinguir dos tipos de bucles:

• Bucles deterministas: son aquellos para los cuales el número de repeticiones esconocido a priori.

❏ Ejemplo: Supongamos que tenemos un ordenador que sólo es capaz de sumaruna unidad a un número. Escribir un algoritmo que lea un número del teclado, lesume diez y muestre el resultado por pantalla.

Un posible algoritmo que utili za un bucle determinista para resolver este problemaes el siguiente:

1. Leer un número desde el teclado

2. Repetir 10 veces

2.1. Sumar uno al valor del número

3. Escribir el valor del número

• Bucles no deterministas o indeterministas: son aquellos para los cuales nose conoce a priori el número de veces que se van a repetir. El bucle se repite hastaque se alcanza cierta condición. La condición es conocida a priori, pero no sabemoscuántas veces es necesario repetir el bucle para que la condición se alcance.

❏ Ejemplo: Escribir un algoritmo que lea números desde teclado hasta que se leaun valor cero. El algoritmo debe calcular la suma total de los números leídos ymostrar el resultado por pantalla.

Un algoritmo que utili za un bucle no determinista para resolver este problema es elsiguiente:

1. Guardar el valor cero en la variable suma

2. Leer un número desde el teclado

3. Mientras que el valor del número leído sea distinto de cero

3.1. Sumar el valor del número leído a la variable suma

3.2. Volver a leer el número desde el teclado

4. Escribir el valor de la variable suma

Page 41: Curso de Modula-2 (Incompleto).pdf

Tema 5. Estructuras iterativas 3

Informática. Facultad de Ciencias (Matemáticas)

En este caso, no sabemos a priori cuántas veces se repetirán los pasos 3.1 y 3.2. Sinembargo, sabemos que dichos pasos dejarán de repetirse en el momento en que selea un valor cero desde el teclado. Conocemos a priori la condición pero no elnúmero de repeticiones.

5.2 Estructuras iterativas en Modu la-2Modula-2 dispone de cuatro sentencias iterativas distintas. Pasemos a estudiar cada una deellas.

5.2.1 La sentencia FOR

La sentencia FOR permite repetir, un número de veces conocido a priori, una serie deinstrucciones. La sentencia FOR es el modo más adecuado de expresar bucles definidos enModula-2.

La forma más simple que toma esta sentencia es la siguiente:

FOR Variable := Valor1 TO Valor2 DOAcciones

END

Las palabras FOR, TO, DO y END son palabras reservadas del lenguaje y delimitan cada unade las partes de la sentencia. La variable que aparece a la izquierda del signo de asignación sellama variable de control del bucle. El valor de esta variable se modifica en cada repeticióndel bucle. El conjunto de acciones que aparecen entre las palabras DO y END constituyen elcuerpo del bucle.

El significado de la sentencia FOR es el siguiente: se ejecutan las acciones entre las palabrasDO y END tantas veces como indique la expresión (Valor2-Valor1+1) . La primera vez que seejecuten estas acciones, el valor de la variable de control es Valor1 . La segunda vez que seejecuten las acciones, el valor de la variable de control es Valor1+1 . El valor de la variable decontrol es incrementado en una unidad tras cada repetición, de modo que la última vez que seejecuten las acciones el valor de la variable de control es Valor2 .

❏ Ejemplo: Escribir un programa en Modula-2 que lea un número Num del teclado y calcule elsumatorio de los números naturales menores o iguales a Num ( 1+2+3+ ... + (Num-1)+Num ).El programa debe mostrar el resultado del sumatorio por pantalla.

Supongamos que no conocemos la siguiente equivalencia:

∑=

−=N

i

NNi

1 2

)1(

Para calcular el sumatorio anterior podemos utili zar una variable Suma cuyo valor inicial seacero. Primero, sumaremos a esta variable el valor uno. A continuación, el valor dos.Repetiremos este paso hasta sumar el valor Num. El algoritmo que calcula el sumatorio es:

Suma := 0;Suma := Suma + 1;Suma := Suma + 2;...Suma := Suma + (Num-1);Suma := Suma + Num;

o de un modo más breve:

Page 42: Curso de Modula-2 (Incompleto).pdf

4 5.2 Estructuras iterativas en Modu la-2

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

1. Asignar a la variable Suma el valor cero.

2. Repetir Num veces (variando el valor de i desde uno hasta Num)

2.1. Sumar i al valor de la variable Suma

El modo más adecuado de expresar el paso 2 de este algoritmo en Modula-2 es usando lasentencia FOR. Se obtiene el siguiente programa:

MODULE Suma;FROM IO IMPORT RdCard, RdLn, WrCard, WrStr;VAR

Num, Suma, i : CARDINAL;BEGIN

WrStr(“Dame un número: “);Num := RdCard(); RdLn;

Suma := 0;FOR i := 1 TO Num DO

Suma := Suma + iEND;

WrStr(“La suma de los primeros “);WrCard(Num,0);WrStr(“ números naturales es “);WrCard(Suma,0)

END Suma.

Podemos especificar que la variable de control se incremente en un valor distinto a uno trascada repetición de las acciones dentro del bucle. Para ello se utili za la palabra reservada BYseguida del valor a sumar a la variable de control.

❏ Ejemplo: Escribir un programa en Modula-2 que lea del teclado un número impar Num ycalcule el sumatorio de los números naturales impares menores o iguales a Num ( 1+3+ ... +(Num-2)+Num ).

Para calcular el sumatorio anterior podemos utili zar una variable Suma cuyo valor inicial seacero. Sumaremos primero a esta variable el valor uno. A continuación el valor tres.Repetiremos este paso hasta sumar el valor Num. El algoritmo que calcula el sumatorio es:

1. Asignar a la variable Suma el valor cero.

2. Repetir (variando el valor de i desde uno hasta Num de dos en dos)

2.1. Sumar i al valor de la variable Suma

Se obtiene el siguiente programa:

MODULE Suma;FROM IO IMPORT RdCard, RdLn, WrCard, WrStr;VAR

Num, Suma, i : CARDINAL;BEGIN

WrStr(“Dame un número: “);Num := RdCard(); RdLn;

IF NOT ODD(Num) THENWrStr(“El número no es impar”)

ELSESuma := 0;FOR i := 1 TO Num BY 2 DO

Suma := Suma + iEND;

Page 43: Curso de Modula-2 (Incompleto).pdf

Tema 5. Estructuras iterativas 5

Informática. Facultad de Ciencias (Matemáticas)

WrStr(“La suma de los primeros “);WrCard(Num,0);WrStr(“ números impares naturales es “);WrCard(Suma, 0)

ENDEND Suma.

El valor que aparece tras la palabra reservada BY puede ser también negativo. En dicho caso, lavariable de control del bucle es decrementada en el valor indicado tras cada repetición delbucle.

La sintaxis BNF para la sentencia FOR es la siguiente:

Sentencia_FOR ::= FOR Identificador_de_Variable :=

Expresión_Inicial TO Expresion_Final [ BY Paso ] DO

Secuencia_de_Sentencias

END

Expresión_Inicial ::= Expresión

Expresión_Final ::= Expresión

Paso ::= Expresión_Constante

Obsérvese que la expresión que aparece tras la palabra BY debe ser una expresión constante(no puede contener ni variables ni operadores no predefinidos).

El diagrama de flujo que representa la sentencia FOR depende del signo de la expresiónconstante Paso:

No

SíVariable > Final

Inicial ← Valor1Final ← Valor2

Variable ← Inicial

Acciones

Variable←Variable+Paso

No

SíVariable < Final

Inicial ← Valor1Final ← Valor2

Variable ← Inicial

Acciones

Variable←Variable+Paso

Figura 1. Bucle FOR con paso positivo. Figura 2. Bucle FOR con paso negativo.

La condición de salida del bucle es que el valor de la variable de control sea estrictamentemayor (o menor en el caso de que el Paso sea negativo) que el valor de la expresión queaparece tras la palabra TO. Adviértase que dicha expresión se calcula una sola vez, antes decomprobar la condición del bucle por primera vez. En cada repetición del bucle, la condición es

Page 44: Curso de Modula-2 (Incompleto).pdf

6 5.2 Estructuras iterativas en Modu la-2

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

comprobada antes de ejecutar el cuerpo del bucle. La variable de control es actualizada trasejecutar el cuerpo del bucle, antes de volver a comprobar la condición.

❏ Ejemplo: El cuerpo del siguiente bucle se ejecuta cero veces, ya que la condición de salida escierta la primera vez.

FOR i := 1 TO 0 DOWrCard(i,0); WrLn

END

❏ Ejemplo: El cuerpo del siguiente bucle se ejecuta dos veces (con valores para la variable i deuno y tres) ya que la condición de salida es cierta la tercera vez.

FOR i := 1 TO 4 BY 2 DOWrCard(i,0); WrLn

END

❏ Ejemplo: El cuerpo del siguiente bucle se ejecuta diez veces (con valores para la variable ientre uno y diez) ya que el valor para la expresión que aparece tras la palabra TO es calculadouna única vez y no se vuelve a calcular tras cada repetición.

Fin := 5;FOR i := 1 TO 2*Fin DO

WrCard(i,0) ; WrLn;Fin := 15

END

Algunas consideraciones sobre la sentencia FOR son las siguientes:

• El tipo de la variable de control puede ser básico (excepto REAL y LONGREAL),enumerado o subrango (ver tema sobre tipos definidos por el programador).

❏ Ejemplo: El siguiente bucle muestra por pantalla todas las letras mayúsculas(excepto la letra eñe mayúscula que está fuera del rango [‘ A’ ..’Z’ ] en la tablaASCII).

FOR Letra := ‘A’ TO ‘Z’ DOWrChar(Letra)

END

• Los tipos de las expresiones Valor1 y Valor2 deben ser compatibles con el tipo dela variable de control.

• El tipo de la expresión constante Paso debe ser entero.

• La variable de control no puede ser:

1) Una componente de una variable estructurada (ver tema sobre arrays).

2) Una variable anónima (ver tema sobre punteros).

3) Una variable importada de otro módulo (ver tema sobre módulos).

4) Un parámetro formal (ver tema sobre subprogramas).

• El programador no debe escribir en el cuerpo del bucle ninguna sentencia quemodifique el valor de la variable de control.

Page 45: Curso de Modula-2 (Incompleto).pdf

Tema 5. Estructuras iterativas 7

Informática. Facultad de Ciencias (Matemáticas)

• El valor de la variable de control está indefinido tras la finalización del bucle FOR.

❏ Ejemplo: No sabemos qué valor se escribe por pantalla tras del siguiente bucle.

FOR i := 1 TO 10 DO...

END;WrInt(i, 0);

5.2.2 La sentencia WHILE

La sentencia WHILE permite repetir, mientras que sea cierta una condición, una serie deinstrucciones. La sentencia WHILE debe utili zarse exclusivamente para expresar buclesindefinidos.

La forma que toma esta sentencia es la siguiente:

WHILE Condición DOAccio nes

END

Las palabras WHILE, DO y END son palabras reservadas del lenguaje y delimitan cada una delas partes de la sentencia. La condición que aparece entre las palabras WHILE y DO esdenominada condición de permanencia del bucle. La condición de permanencia debe seruna expresión de tipo booleano. El conjunto de acciones que aparecen entre las palabras DO yEND constituyen el cuerpo del bucle.

El diagrama de flujo correspondiente a esta sentencia es el siguiente:

NoCondición

Acciones

Figura 3. La sentencia WHILE.

Obsérvese que la condición se vuelve a evaluar, para cada repetición del bucle, antes de ejecutar elcuerpo. Se permanece dentro del bucle mientras que la condición sea cierta (es por esto que lacondición se llama de permanencia). Podría ocurrir que el cuerpo del bucle no llegara a ejecutarse,en caso de que la condición fuese falsa la primera vez que se comprueba.

La sintaxis de la sentencia WHILE, utili zando la notación BNF, es:

Page 46: Curso de Modula-2 (Incompleto).pdf

8 5.2 Estructuras iterativas en Modu la-2

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Sentencia_WHILE ::= WHILE Condición DO

Secuencia_de_Sentencias

END

Condición ::= Expresión

❏ Ejemplo: Escribir un programa que, dado un número natural Tope, calcule el mínimo valor deN tal que 0+1+2+...+(N-1)+N ≥ Tope.

Un posible algoritmo para resolver este problema es el siguiente:

1. Leer del teclado el valor de la variable Tope

2. Guardar el valor cero en la variable Suma

3. Guardar el valor cero en la variable N

4. Mientras que el valor de la variable Suma sea menor al de la variable Tope

4.1. Sumar uno a la variable N

4.2. Sumar N a la variable Suma

5. Escribir el valor de la variable N

Este algoritmo da lugar al siguiente diagrama de flujo y su correspondiente programa enModula-2:

MODULE Suma;FROM IO IMPORT RdCard, RdLn, WrCard, WrStr;VAR

Tope, N, Suma : CARDINAL;BEGIN

WrStr(“Dame el tope a s umar: ”);Tope := RdCard(); RdLn;

Suma := 0;N := 0;WHILE Suma < Tope DO

N := N+1;Suma := Suma + N

END;

WrStr(“El mínimo N que cumple la condición es ”);WrCard(N,0)

END Suma.

No

INICIO

Suma < Tope

EscribirN

FIN

suma ← 0N ← 0

N ← N + 1Suma ← Suma + N

LeerTope

5.2.3 La sentencia REPEAT

La sentencia REPEAT permite repetir una serie de instrucciones hasta que cierta condición seacierta. La sentencia REPEAT debe utili zarse exclusivamente para expresar bucles indefinidos.

La forma que toma esta sentencia es la siguiente:

Page 47: Curso de Modula-2 (Incompleto).pdf

Tema 5. Estructuras iterativas 9

Informática. Facultad de Ciencias (Matemáticas)

REPEATAccion es

UNTIL Condición

Las palabras REPEAT y UNTIL son palabras reservadas del lenguaje y delimitan cada una delas partes de la sentencia. La condición que aparece tras la palabras UNTIL es denominadacondición de salida del bucle. La condición de salida debe ser una expresión de tipobooleano. El conjunto de acciones que aparecen entre las palabras REPEAT y UNTILconstituyen el cuerpo del bucle.

El diagrama de flujo correspondiente a esta sentencia es el siguiente:

NoCondición

Acciones

Figura 4. La sentencia REPEAT.

Obsérvese que la condición se vuelve a evaluar, para cada repetición del bucle, después deejecutar el cuerpo. Se sale del bucle una vez que la condición sea cierta (es por esto que lacondición se llama de salida). El cuerpo del bucle se ejecuta al menos una vez.

La sintaxis de la sentencia REPEAT, utili zando la notación BNF, es:

Sentencia_REPEAT ::= REPEAT

Secuencia_de_Sentencias

UNTIL Condición

❏ Ejemplo: Escribir un programa que calcule una aproximación al número e utili zando lasiguiente igualdad:

�+++== ∑∞

= !2

1

!1

11

!

1

0i ie

Dado que es imposible sumar infinitos términos, el programa dejará de sumar términos una vezque el valor del último término sumado sea menor a una diezmilésima.

Llamemos término i-ésimo al término 1/i!. Es interesante observar que, conocido el valor deltérmino i-ésimo, basta con multipli car éste por 1/(i+1) para obtener el valor del términosiguiente.

En el algoritmo utili zaremos tres variables. La variable i indicará, en todo momento, el ordendel término que estemos sumando. La variable Termino almacenará siempre el valor deltérmino actual. Por último, la variable Suma irá acumulando la suma de términos.

El diagrama de flujo correspondiente al algoritmo y su correspondiente programa en Modula-2son los siguientes:

Page 48: Curso de Modula-2 (Incompleto).pdf

10 5.2 Estructuras iterativas en Modu la-2

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

MODULE NumeroE;FROM IO IMPORT WrLngReal, WrStr;CONST

DIEZMILESIMA = 1.0/10000.0;PRECISION = 10;

ANCHO = 0;VAR

i, Termino, Suma : LONGREAL;BEGIN

i := 0.;Termino := 1.;Suma := Termino;REPEAT

i := i+1.;Termino := Termino * (1.0/i);Suma := Suma + Termino

UNTIL Termino < DIEZMILESIMA;

WrStr(“La aproximación al número e es ”);WrLngReal(Suma,PRECISION,ANCHO)

END NumeroE.

No

INICIO

Término <1/10000

EscribirSuma

FIN

i ← 0Término ← 1

Suma ←Término

i ← i + 1Término ← Término*(1/i)Suma ← Suma+Término

5.2.4 Las sentencias LOOP y EXIT

La sentencia LOOP permite repetir indefinidamente una serie de instrucciones.

La forma que toma esta sentencia es la siguiente:

LOOPAcciones

END

Las palabras LOOP y END son palabras reservadas del lenguaje y delimitan el cuerpo delbucle.

El diagrama de flujo correspondiente a esta sentencia es el siguiente:

Acciones

Figura 5. La sentencia LOOP.

Obsérvese que el cuerpo del bucle es ejecutado indefinidamente. Nunca se pasa a la instrucciónsiguiente al bucle.

La sentencia EXIT puede ser utili zada para sali r de un bucle LOOP. La ejecución de unasentencia EXIT, dentro del cuerpo de un bucle LOOP, hace que el bucle finalice y que laejecución del programa continúe con la instrucción siguiente a la palabra reservada END.

El modo habitual de combinar las sentencias LOOP y EXIT es el siguiente:

Page 49: Curso de Modula-2 (Incompleto).pdf

Tema 5. Estructuras iterativas 11

Informática. Facultad de Ciencias (Matemáticas)

LOOPAcción A;IF Condición THEN

EXITEND;Acción B

END

El diagrama de flujo correspondiente a esta construcción es:

No

Condición

Acción A

Acción B

Figura 6. Las sentencias LOOP y EXIT.

La sintaxis de las sentencias LOOP y EXIT, utili zando la notación BNF, es:

Sentencia_LOOP ::= LOOP

Secuencia_de_Sentencias

END

Sentencia_EXIT ::= EXIT

Algunas consideraciones sobre estas sentencias son:

• La sentencia EXIT sólo puede aparecer dentro del cuerpo de un bucle LOOP. No sepuede usar la sentencia EXIT para sali r de un bucle FOR, WHILE o REPEAT.

• Cuando una sentencia EXIT aparece en un bucle LOOP anidado dentro de otro bucleLOOP, la ejecución de dicha sentencia sólo hará que abandone el bucle LOOP másinterno.

• Si la comprobación de la condición de salida se hace justo al principio del bucle LOOP,se debe sustituir el bucle LOOP por uno WHILE equivalente:

LOOPIF Condición THEN WHILE NOT Condición DO

EXIT ≡≡ AccionesEND; ENDAcciones

END

• Si la comprobación de la condición de salida se hace justo al final del bucle LOOP, sedebe sustituir el bucle LOOP por uno REPEAT equivalente:

Page 50: Curso de Modula-2 (Incompleto).pdf

12 5.2 Estructuras iterativas en Modu la-2

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

LOOPAcciones REPEATIF Condición THEN ≡≡ Acciones

EXIT UNTIL CondiciónEND;

END

• De los dos puntos anteriores, se deduce que sólo se debe utili zar las combinación delas sentencias LOOP y EXIT cuando la condición de salida está situada en un puntointermedio del cuerpo del bucle.

• Modula-2 no limita el número de sentencias EXIT que pueden aparecer dentro de unbucle LOOP. El uso de esta característica del lenguaje hace que los programasresultantes sean difíciles de entender. Además de ser un mal estilo de programación, eluso de esta característica del lenguaje no es necesaria. Por todo esto, es muy importanteevitar que aparezca más de una sentencia EXIT dentro de cada bucle LOOP.

❏ Ejemplo: Escribir un programa que lea dos números enteros del teclado, de modo que elsegundo sea mayor que el primero.

Utili zaremos dos variables enteras (Menor y Mayor ). Leeremos un valor en la variable Menor yrepetiremos el proceso de leer otro número en la variable Mayor hasta que éste seaestrictamente mayor al primero.

El diagrama de flujo correspondiente al algoritmo y su correspondiente programa en Modula-2son los siguientes:

MODULE Numeros;FROM IO IMPORT WrStr, WrInt, RdInt, RdLn;VAR

Menor, Mayor : INTEGER;BEGIN

WrStr(“Dame un número: “);Menor := RdIn t(); RdLn;WrStr(“Dame un número mayor: “);LOOP

Mayor := RdInt(); RdLn;IF Mayor > Menor THEN

EXITEND;WrStr(“Debe ser mayor. Prueba de nuevo”)

ENDWrStr(“Los números son: “);WrInt(Menor,0);WrStr(“ y “);WrInt(Mayor,0)

END Numeros.

No

INICIO

Mayor > Menor

EscribirMenor y Mayor

FIN

LeerMenor

Escribir“Dame un nº”

Escribir“Dame otro mayor”

LeerMayor

Escribir“Prueba otra vez”

Page 51: Curso de Modula-2 (Incompleto).pdf

Tema 5. Estructuras iterativas 13

Informática. Facultad de Ciencias (Matemáticas)

5.3 Diseño d e bucles

5.3.1 Anidamiento de bucles

Modula-2 no impone ningún tipo de restricciones sobre el tipo de sentencias que puedenaparecer en el cuerpo de un bucle. En concreto, dentro del cuerpo de un bucle puede aparecerotro bucle. A esto se le llama anidamiento de bucles.

❏ Ejemplo: Escribir un programa que calcule el factorial de un número leído del teclado sinusar la operación de multipli cación.

Desarrollamos primero un algoritmo que calcula el producto de dos números enteros y positi vosi y f . Para ello, sumamos f veces el valor de i:

� �� ���

vecesf

iiifi +++=×

Para realizar el cálculo anterior, hay que repetir la acción sumar i un número predeterminadode veces (f veces). El modo más adecuado de expresar esto es mediante una sentencia FOR:

MODULE Producto;FROM IO IMPORT RdCard, RdLn, WrCard, WrStr;VAR

i, f, Producto, j : CARDINAL;BEGIN

WrStr(“Dame un número: ”);i := RdCard(); RdLn;WrStr(“Dame otro: ”);f := RdCard(); RdLn;

Producto := 0;FOR j := 1 TO f DO

Producto := Producto + iEND;

WrStr(“El producto es ”);WrCard (Producto, 0)

END Producto.

Para calcular el factorial de un número n debemos calcular la siguiente expresión:

���� ����� ��

productosn

nnnn 12)2()1(! ××−×−×=

Para realizar el cálculo anterior, hay que repetir n veces la acción multipli car por i (variando elvalor de i desde uno hasta n). De nuevo, el modo más adecuado de expresar esto es medianteun bucle FOR:

MODULE Fact;FROM IO IMPORT RdCard, RdLn, WrCard, WrStr;VAR

n, i, f : CARDINAL;BEGIN

WrStr(“Dame un número: ”);n := RdCard(); RdLn;

f := 1;FOR i := 1 TO n DO

f := f * iEND;

Page 52: Curso de Modula-2 (Incompleto).pdf

14 5.3 Diseño d e bucles

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

WrStr(“El factorial es ”);WrCard (f, 0)END Fact.

Podemos utili zar el primer algoritmo para calcular el producto f * i . Combinando los dosalgoritmos, obtenemos un algoritmo que calcula el factorial de un número sin usar la operaciónde multipli cación:

MODULE FactSum;FROM IO IMPORT RdCard, RdLn, WrCard, WrStr;VAR

n, i, j, f, Producto : CARDINAL;BEGIN

WrStr(“Dame un número: ”);n := RdCard(); RdLn;

f := 1;FOR i := 1 TO n DO

Producto := 0;FOR j = 1 TO f DO

Producto := Producto + i ≡ f := f * iEND;f := Producto

END;

WrStr(“El factorial es ”);WrCard (f, 0)

END FactSum.

Nótese que ha sido necesario anidar dos bucles FOR para resolver el problema.

❏ Ejercicio: Dibuja el diagrama de flujo correspondiente a este algoritmo. Sigue los pasos quese realizarían para calcular 3! usando el algoritmo anterior.

Al diseñar un algoritmo con bucles anidados, tanto el comienzo como el final del bucle anidadodeben estar dentro del bucle exterior. Así, el siguiente anidamiento de bucles es correcto:

WHILE Condición DOAccionesREPEAT

AccionesUNTIL CondiciónAcciones

END

El siguiente anidamiento no es correcto, ya que el bucle REPEAT está anidado en el bucleWHILE y debe acabar antes que éste último:

WHILE Condición DOAccionesREPEAT

AccionesEND

UNTIL CondiciónAcciones

Otra consideración importante es que a la hora de anidar bucles FOR, es imprescindible utili zaruna variable de control distinta para cada uno de ellos. Por ejemplo,

Page 53: Curso de Modula-2 (Incompleto).pdf

Tema 5. Estructuras iterativas 15

Informática. Facultad de Ciencias (Matemáticas)

FOR i := 1 TO 3 DOFOR j := 1 TO 2 DO

WrChar(‘*’)END

END

Obsérvese que este trozo de programa escribe seis asteriscos por pantalla.

5.3.2 Bucles infinitos

Un bucle infinito es un bucle que nunca acaba.

La ejecución de un programa que contiene un bucle infinito no acaba. En TopSpeed Modula-2,el programador puede interrumpir un programa de este tipo pulsando simultáneamente lasteclas Ctrl y C.

A veces, el bucle infinito es debido a que el programador olvidó alguna sentencia en el cuerpodel bucle.

❏ Ejemplo: El siguiente bucle no acaba ya que falta una sentencia en el cuerpo que incrementeel valor de la variable N:

Suma := 0;N := 0;WHILE N <= 100 DO

Suma := Suma + NENDWrCard(Suma,0)

En otras ocasiones, el bucle infinito se debe a que es imposible alcanzar la condición definalización del bucle. Este tipo de situaciones se suelen deber a un error de diseño delprograma.

❏ Ejemplo: El siguiente bucle no acaba ya que la variable N nunca alcanzará un valor negativo:

Suma := 0;N := 100;WHILE N >= 0 DO

Suma := Suma + N;N := N + 1

ENDWrCard(Suma,0)

Con objeto de evitar la aparición de bucles infinitos, es importante comprobar que lascondiciones de finalización de un bucle serán alcanzadas.

Page 54: Curso de Modula-2 (Incompleto).pdf
Page 55: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 5) 1

Informática. Facultad de Ciencias (Matemáticas)

Relación d e problemas (Tema 5)1. Escribir un programa que lea una li sta de valores reales positi vos terminada por un

número negativo y calcule la media de esta li sta.

2. Escribe un programa que lea un número entero positi vo por teclado y determine si es

primo o compuesto.

3. Diseña un programa que escriba en pantalla la tabla de multipli car de un numero del 1 al 9

introducido desde el teclado.

4. Escribir un programa que lea una li sta de valores enteros positi vos terminada por 0 y

determine los valores máximo y mínimo.

5. Escribe un programa que calcule e imprima en pantalla los N primeros números primos,

siendo N un número que se introduce por teclado.

6. Escribe un programa que calcule el valor de seno x dado por:

Seno x xx x x

= − + − +3 5 7

3 5 7! ! !

Este programa debe leer dos variables x y precisión donde x es un ángulo en radianes y

precisión debe ser positi va y menor que 1. La serie debe sumarse hasta que el valor

absoluto del último sumando sea menor que precisión , incluyendo este último sumando

en la suma.

NOTA: El término con numerador xn de la serie se puede calcular multipli cando el previo

por −× −

x

n n

2

1( )

7. Un bill ete de segunda clase en tren de Londres a París vale normalmente 80 libras. Sin

embargo, existen tarifas especiales en los siguientes casos:

65 años o más: 52.60 libras

12-15 años: 55.00 libras

4-11 años: 40.20 libras

menos de 4 años: gratis

Supón que se quiere averiguar el coste total para una famili a. Escribe un programa que lea

la edad de cada miembro de la famili a y calcule el coste total de los bill etes.

Page 56: Curso de Modula-2 (Incompleto).pdf

2 Relación d e Problemas (Tema 5)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

8. Si x0 es una aproximación a a entonces una aproximación mejor es:

x xa

x1 00

1

2= +

Podemos repetir esto con x1 y obtener una nueva aproximación. Este proceso, que es una

aplicación del método de Newton-Raphson, se puede generalizar a:

x xa

xnn n

n+ = +

=1

1

212, , , �

Escribir un programa que lea los valores de a y precisión. El programa debe calcular la

raíz de a utili zando el método descrito. El programa se detiene cuando el valor absoluto

de la diferencia entre dos aproximaciones consecutivas es menor que precisión. El valor

inicial para la iteración será a/2. El programa debe mostrar en pantalla todos las

aproximaciones obtenidas.

9. Escribir tres programas para calcular el factorial de un número entero leído desde el

teclado utili zando las sentencias FOR, WHILE y REPEAT.

10. Escribir un programa que visualice en pantalla una figura similar a la siguiente:

**********

Siendo el número de líneas un dato que se lee al principio del programa.

11. Un número es perfecto si coincide con la suma de todos sus divisores excepto el mismo.

Por ejemplo 28 es perfecto ya que sus divisores son 1, 2, 4, 7, 14 y 1+2+4+7+14 = 28.

Escribe un programa que determine si un número leído del teclado es perfecto.

12. Para encontrar el máximo común divisor (mcd) de dos números enteros se puede emplear

el algoritmo de Euclides: dados los números a y b (siendo a > b) se divide a por b

obteniendo el cociente q1 y el resto r1. Si r1 ≠ 0, se divide b por r1, obteniendo el cociente

q2, y el resto r2. Si r2 ≠ 0 se divide r1 por r2 obteniendo cocientes y restos sucesivos. El

proceso continúa hasta obtener un resto igual a 0. El resto anterior a éste es el máximo

común divisor de los números iniciales (a y b). Escribe un programa que lea dos números

enteros positi vos del teclado y calcule su máximo común divisor y su mínimo común

múltiplo (mcm).

NOTA: obtener el mínimo común múltiplo a partir de la siguiente igualdad:

Page 57: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 5) 3

Informática. Facultad de Ciencias (Matemáticas)

mcd (a,b) * mcm (a,b) = a * b

13. Diseñar un programa que calcule el cociente entero y el resto correspondiente para dos

números naturales dados por teclado, sin utili zar los operadores DIV y MOD.

14. Escribir un programa que lea un número N y calcule el término N-ésimo de la sucesión de

Fibonacci:

Fibonacci

Fibonacci

Fibonacci n Fibonacci n Fibonacci n si n

( )

( )

( ) ( ) ( ) ,

1 0

2 1

1 2 2

=== − + − >

Realizar los ejercicios 3, 8 y 10 como práctica en el laboratorio.

Page 58: Curso de Modula-2 (Incompleto).pdf

4 Relación d e Problemas (Tema 5)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Relación complementaria (Tema 5)1. Escribir un programa que calcule y visualice el más grande, el más pequeño y la media de

N números. El valor N se solicitará al principio del programa y los números serán

introducidos por teclado.

2. Encontrar el número natural N más pequeño tal que la suma de los N primeros números

enteros exceda una cantidad introducida por teclado.

3. El valor exp(x) se puede calcular mediante la siguiente serie:

exp( )! ! !

xx x x= + + + +11 2 3

2 3�

Escribir un programa que lea un valor x de teclado y calcule el valor de exp(x) deteniendo

el cálculo cuando el valor del último término sumado sea inferior a una diezmilésima.

4. Escribir un programa que calcule una aproximación al número π sabiendo que

π4

11

3

1

5

1

7

1

9= − + − + − �

para ello sumará términos de la serie anterior mientras que sus valores absolutos sean

mayores a una diezmilésima y del valor obtenido despejará π.

5. Diseña un programa que multiplique dos números enteros mediante el algoritmo de la

multipli cación rusa. Este algoritmo multipli ca por 2 el multipli cando y divide por dos el

multipli cador hasta que el multipli cador toma el valor 1. Después suma todos los

multipli candos correspondientes a multipli cadores impares. Dicha suma es el producto de

los números originales.

Ejemplo: 37 * 12 = 444 (multipli cador: 37, multipli cando:12)

37 1218 24 9 48 4 96 2 192 1 384

12 + 48 + 384 = 444

6. Escribe un algoritmo que lea un número natural N y un carácter. La salida debe ser unrombo compuesto del carácter y de la anchura que especifica el número N. Por ejemplo, siN es 5 y el carácter es *, el rombo sería:

Page 59: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 5) 5

Informática. Facultad de Ciencias (Matemáticas)

7. Escribe un algoritmo que imprima una pirámide de dígitos como la de la figura, tomandocomo entrada el número de filas de la misma siendo este número menor o igual que 9.

�� � �

� � � � �� � � � � � �

� � � � � � �� �

8. Escribir un programa que lea del teclado un número N (expresado en base 10), una base B

y pase N a base B.

9. Escribe un programa que determine si la cadena “abc” aparece en una sucesión de

caracteres cuyo final viene dado por un punto.

Page 60: Curso de Modula-2 (Incompleto).pdf

Tema 6. Procedimientos y funciones 1

Informática. Facultad de Ciencias (Matemáticas)

Departamento de Lenguajes y Ciencias dela Computación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)http://www.lcc.uma.es/personal/pepeg/mates

Tema 6. Procedimientos y funciones

6.1 Concepto de subprograma ................................................................ .................2

6.2 Definición y llamadas a subprogramas ............................................................... 3

6.3 Parámetros formales y reales ................................................................ .............5

6.4 Paso de parámetros por valor y por referencia ...................................................6

6.5 Procedimientos y Funciones................................................................ ...............8

6.5.1 Diferencias entre procedimientos y funciones ...............................................8

6.5.2 Funciones predefinidas ................................................................ ...............10

6.5.3 Procedimientos predefinidos ................................................................ .......10

6.6 Uso de parámetros ................................................................ ........................... 11

6.6.1 Parámetros de entrada................................................................ ................11

6.6.2 Parámetros de salida ................................................................ .................. 11

6.6.3 Parámetros de entrada y salida................................................................ ...12

6.7 Anidamiento de subprogramas. Ámbitos........................................................... 12

6.7.1 Estructura de bloques ................................................................ .................12

6.7.2 Redefinición de elementos ................................................................ ..........13

6.7.3 Efectos laterales................................................................ .......................... 14

6.7.4 Doble referencia................................................................ .......................... 15

6.8 Sintaxis BNF para subprogramas ................................................................ .....15

Bibliografía• Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de

Educación a Distancia.

• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

Page 61: Curso de Modula-2 (Incompleto).pdf

2 6.1 Concepto de subp rograma

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Introdu cc iónCualquier programa de ordenador que realice una labor útil suele tener una extensiónconsiderable. El diseño de un algoritmo complejo de una sola vez es una labor complicada.Vimos como la metodología de diseño descendente permite distinguir diferentes partes en ladescripción de un algoritmo, de modo que la agrupación de éstas constituya el algoritmocompleto. Estudiamos en este tema los mecanismos del lenguaje de programación Modula-2que permiten dividir un programa complejo en partes más manejables que puedan serposteriormente combinadas.

6.1 Concepto de subp rogramaUn subprograma es una parte de un programa. Desde el punto de vista de la programación,un subprograma es un trozo de programa que se escribe por separado y que puede ser utili zadoinvocándolo mediante su nombre.

Esto hace que distingamos dentro de un programa el programa principal (el algoritmocorrespondiente al módulo raíz) y subprogramas (los demás módulos). Cada subprogramapuede a su vez estar dividido en otros subprogramas.

Supongamos que queremos escribir un programa que calcule el perímetro de un triángulo convértices A, B y C:

A

C

B

Figura 1. Triángulo de vértices A, B y C

El diagrama de bloques para el algoritmo puede ser:

LeerCoordenada A

Leer Vértices

CálculoPerímetro Triángulo

LeerCoordenada B

CalcularPerímetro

LeerCoordenada C

ImprimirPerímetro

Figura 2. Diagrama de bloques para cálculo del perímetro del triángulo

El problema de calcular el perímetro de un triángulo puede dividirse en tres subproblemas: leerlas coordenadas, calcular el perímetro e imprimir el perímetro. A su vez, el primero de estossubproblemas puede dividirse en tres subproblemas: leer la coordenada A, leer la coordenada By leer la coordenada C.

Page 62: Curso de Modula-2 (Incompleto).pdf

Tema 6. Procedimientos y funciones 3

Informática. Facultad de Ciencias (Matemáticas)

El aspecto del programa resultante es el siguiente:

MODULE Perimetro;...PROCEDURE LeerVertices;

...PROCEDURE LeerUnaCoordenada...;BEGIN...END LeerUnaCoordenada;

...BEGIN

(* Leer las tres coordenadas *)LeerUnaCoordenada...;LeerUnaCoordenada...;LeerUnaCoordenada...;

END LeerVertices;

PROCEDURE CalcularPerimetro...;BEGIN

...END CalcularPerimetro;

PROCEDURE ImprimirPerimetro...;BEGIN

...END ImprimirPerimetro;

BEGINLeerVertices...CalcularPerimetro...ImprimirPerimetro...

END Perimetro.

Vemos como cada subprograma aparece descrito en la parte declarativa del programa(declaración de subprograma) y luego se usa escribiendo su nombre en la parte ejecutiva(llamada a subprograma).

Es deseable que en el cuerpo del programa principal se evite la aparición excesiva deestructuras de control (selección y repetición) utili zando subprogramas. De esta forma, elcuerpo del programa principal estará constituido fundamentalmente por llamadas asubprogramas.

Se suelen emplear subprogramas en los siguientes casos:

• En programas complejos: si un programa complejo se escribe sin subprogramasresulta difícil de entender. Dividiéndolo en subprogramas podemos centrarnos en cadamomento en un problema más pequeño que el problema original.

• Cuando se repite dentro de un algoritmo algún tipo de tratamiento: en estecaso podemos escribir un subprograma que describe cómo se hace el tratamiento unasola vez y realizar una llamada a este subprograma cada vez que queramos usar eltratamiento.

6.2 Definición y llamadas a subp rogramasCuando para describir un algoritmo A se necesita emplear otro algoritmo B, de dice que elalgoritmo A llama al algoritmo B. En el ejemplo anterior el algoritmo principal ll ama a losalgoritmos LeerVertices , CalcularPerimetro e ImprimirPerimetro . El algoritmoLeerVertices llama al algoritmo LeerUnaCoordenada .

Page 63: Curso de Modula-2 (Incompleto).pdf

4 6.2 Definición y llamadas a subp rogramas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

A veces, un subprograma depende del valor de una o más variables. Por ejemplo, nos puedeinteresar escribir un subprograma EscribeSumatorio que dado un número N calcule el valorde la suma 1 + 2 + ... + (N-1) + N y escriba el resultado por pantalla. Para distintos valores de Nel subprograma obtiene distintos resultados. En este caso decimos que el subprogramaEscribeSumatorio está parametrizado por N, o que N es un parámetro del subprogramaEscribeSumatorio . Un subprograma puede depender de cero, uno o más parámetros.

Lo primero que debemos hacer para utili zar un subprograma es declararlo. La primera partede la declaración de un subprograma es su cabecera. En la cabecera de un subprograma seindica el nombre de éste y los parámetros o argumentos que toma (especificando para cada unosu tipo). La sintaxis que sigue Modula-2 para esto es:

PROCEDURE Nombre (argumento1 : Tipo1; argumento2 : Tipo2; ... );

En la cabecera del subprograma aparece la palabra reservada seguida del nombre delsubprograma. Este nombre debe ser un identificador válido. A continuación, y entre paréntesis,se escribe la li sta de argumentos separados por puntos y comas. El nombre de cada argumentodebe ser también un identificador. Detrás de cada argumento se especificará su tipo precedidode un signo dos puntos. Si hay varios argumentos seguidos con el mismo tipo, podemosabreviar y escribirlos separados por comas, indicando una sola vez el tipo de todos ellos.

La cabecera del subprograma EscribeSumatorio comentado previamente es:

PROCEDURE EscribeSumatorio ( N : CARDINAL );

Después de la cabecera del subprograma viene su cuerpo. La declaración finaliza con la palabraEND seguida del nombre del subprograma. En el cuerpo, aparecen las declaraciones de loselementos necesarios para el subprograma y tras la palabra reservada BEGIN el códigonecesario para resolver el subproblema. La declaración completa para el ejemplo es:

PROCEDURE EscribeSumatorio ( N : CARDINAL );VAR Suma, i : CARDINAL;BEGIN

Suma := 0;FOR i := 1 TO N DO

Suma := Suma + iEND;WrCard (S uma, 0)

END EscribeSumatorio;

Podemos observar que las variables Suma e i se declaran dentro del subprograma y no en elprograma principal. Esto se hace así porque sólo son necesarias para el cómputo que hace elsubprograma. A estas variables se les llama variables locales del subprograma. Las variableslocales de un subprograma se crean automáticamente cada vez que se llama al subprograma y sedestruyen cada vez que se sale del subprograma. Por esto NO CONSERVAN EL VALOR quetenían de una llamada a otra. Tampoco toman valores iniciales por defecto; es el programador elencargado de proporcionárselos.

Una vez que tenemos un subprograma declarado, podemos utili zarlo dentro del cuerpo de otrosubprograma (en condiciones que especificaremos un poco más adelante) o del programaprincipal. Para utili zar el subprograma hay que llamarlo. La llamada a un subprograma serealiza utili zando su nombre seguido de los valores (entre paréntesis y separados por comas)con los que queremos que trabaje el subprograma. Una llamada a un subprograma con Nparámetros se escribe:

NombreSubprograma (parámetro1, parámetro2, ... ,parámetroN)

Si queremos llamar al subprograma EscribeSumatorio para que calcule la suma de losprimeros 50 naturales escribiremos:

Page 64: Curso de Modula-2 (Incompleto).pdf

Tema 6. Procedimientos y funciones 5

Informática. Facultad de Ciencias (Matemáticas)

EscribeSumatorio (50)

6.3 Parámetros formales y realesSupongamos que queremos escribir un programa que escriba por pantalla todos los númerosprimos menor a uno dado (Max). Para ello, escribiremos primero un subprograma que dado unnúmero Num escriba por pantalla si es primo y en otro caso no escriba nada:

PROCEDURE EscribirSiPrimo (Num : CARDINAL);VAR

Divisor : CARDINAL;EsPrimo : BOOLEAN;

BEGINEsPrimo := TRUE;Divisor := 2;WHILE EsPrimo AND (Divisor <= Num DIV 2) DO

EsPrimo := Num MOD Divisor <> 0;Divisor := Divisor + 1

END;IF EsPrimo THEN

WrCard (Num, 0); WrLnEND

END EscribirSiPrimo;

El programa principal leerá el número Max del teclado y llamará a este subprograma para todoslos valores en el intervalo [1,Max]:

MODULE Primos;FROM IO IMPORT WrCard, RdCard, RdLn, WrStr, WrLn;VAR

Max, i : CARDINAL;

PROCEDURE EscribirSiPrimo (Num : CARDINAL);VAR

Divisor : CARDINAL;EsPrimo : BOOLEAN;

BEGINEsPrimo := TRUE;Divisor := 2;WHILE EsPrimo AND (Divisor <= Num DIV 2) DO

EsPrimo := Num MOD Divisor <> 0;Divisor := Divisor + 1

END;IF EsPrimo THEN

WrCard (Num, 0); WrLnEND

END EscribirSiPrimo;

BEGINWrStr (“Dame el máximo: “);Max := RdCard(); RdLn;WrStr (“Los primos menores son:”); WrLn;FOR i := 1 TO Max DO

EscribirSiPrimo(i)END

END Primos.

Se llaman parámetros formales a la li sta de parámetros que aparece en la declaración de unsubprograma parametrizado. En el ejemplo, Num es un parámetro formal del subprogramaEscribirSiPrimo .

Page 65: Curso de Modula-2 (Incompleto).pdf

6 6.4 Paso de parámetros por valor y por referencia

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Se llaman parámetros reales a la li sta de parámetros que aparece en la llamada alsubprograma. En el ejemplo, i es un parámetro real en la llamada a EscribirSiPrimo . Losparámetros reales pueden ser, además de variables, expresiones y por lo tanto valores (a veces,sólo pueden ser variables). En una llamada como EscribirSiPrimo(143) , el parámetro real es143 .

Los parámetros formales de un subprograma son opcionales, esto es, se pueden escribirsubprogramas no parametrizados, pero si aparecen deben seguir una serie de normas:

• El número de parámetros reales en una llamada a un subprograma parametrizado debeser igual al número de parámetros formales en la definición de dicho subprograma.

• La correspondencia entre parámetros formales y reales es por posición. El i-ésimoparámetro real se corresponde con el i-ésimo parámetro formal.

• El tipo del i-ésimo parámetro real debe ser compatible (o igual si es por referencia) conel declarado para el i-ésimo formal.

• Los nombres de un parámetro formal y su correspondiente real pueden ser distintos.

Así, con el siguiente programa:

MODULE Ejemplo;FROM IO IMPORT WrReal;VAR x, y : REAL;

PROCEDURE EscribirDivCuadrados (x, y : REAL);CONST

PRECISION = 5;ANCHO = 0;

VAR Cociente : REAL;BEGIN

Cociente := (x * x) / (y * y);WrReal (Cociente, PRECISION, ANCHO)

END EscribirDivCuadrados;BEGIN

x := 1.0;y := 2.0;EscribirDivCuadrados (y, x)

END Ejemplo.

El resultado que obtenemos es 4.0/1.0 = 4.0, ya que la correspondencia entre parámetrosformales y reales está dada por el orden y no por los nombres.

El efecto producido por la llamada a un subprograma puede resumirse como:

1) Se evalúan las expresiones que aparezcan en los argumentos (parámetros reales).

2) Se crean las variables correspondientes a los parámetros formales.

3) Se asignan los valores calculados en 1) a los correspondientes parámetros formales.

4) Se crean las variables locales al subprograma.

5) Se ejecuta el código correspondiente al subprograma.

6) Se destruyen las variables locales y las correspondientes a los parámetros formales.

7) Se continúa el programa por la instrucción siguiente a la llamada al subprograma.

6.4 Paso de parámetros por valor y por referenciaConsideremos el siguiente programa, en el que declaramos un subprograma EscribirModuloque escribe por pantalla el módulo de un complejo con parte real Real y parte imaginaria Imag :

Page 66: Curso de Modula-2 (Incompleto).pdf

Tema 6. Procedimientos y funciones 7

Informática. Facultad de Ciencias (Matemáticas)

MODULE Ejemplo;FROM IO IMPORT WrLngReal, WrStr, WrLn;FROM MATHLIB IMPORT Sqrt;VAR x, y : LONGREAL;

PROCEDURE EscribirModulo (Real, Imag : LONGREAL);VAR Modulo : LONGREAL;BEGIN

WrStr ("El módulo del complejo ");WrLngReal (Real, 5, 0);WrStr (" ");WrLngReal (Imag, 5, 0);WrStr (" i es: ");Real := Real * Real;Imag := Imag * Imag;Modulo := Sqrt (Real + Imag);WrLngReal (Modulo, 5, 0);WrLn

END EscribirModulo;

BEGINx := 5.0;y := 6.0;EscribirMod ulo (x, y);WrLngReal (x, 5, 0); WrLn;WrLngReal (y, 5, 0); WrLn

END Ejemplo.

La salida producida por pantalla al ejecutar este programa es:

El módulo del complejo 5.0000E+0 6.0000E+0 i es: 7.8102E+05.0000E+06.0000E+0

Al realizar la llamada al subprograma los valores de x (5.0) e y (6.0) se copian en losparámetros formales Real y Imag . A continuación, se pasa a ejecutar el subprograma: seescribe la primera línea por pantalla, Real pasa a valer 25.0, Imag pasa a valer 36.0, Módulopasa a valer Sqrt (61.0), se escribe este valor por pantalla ( “7.8102E+0”) y se salta a lasiguiente línea de pantalla. Después de esto, se vuelve al programa principal y continuamos pordonde se dejó: se escriben por pantalla los valores de x e y en distintas líneas ( 5.0000E+0 y6.0000E+0). Lo importante de este ejemplo es que al cambiar el valor de los parámetrosformales (Real e Imag ) dentro del subprograma, el valor de los parámetros reales (x e y) se haconservado.

A este modo de pasar parámetros se le llama paso de parámetros por valor. Losparámetros reales y formales representan variables distintas, aunque al ll amar al subprogramase copian los valores de las reales sobre las correspondientes formales. Los argumentos realesen la llamada al subprograma pueden darse en forma de expresiones, cuyos tipos deben serCOMPATIBLES EN ASIGNACIÓN con los tipos de los argumentos formales.

Existe otra forma de pasar parámetros conocida como paso de parámetros porreferencia. En este caso, a la hora de realizar la llamada al subprograma, no se copian losvalores de los parámetros reales en los formales, sino que se identifican parámetros reales yformales, de modo que cada vez que cambiemos el valor de un parámetro formal en elsubprograma estaremos cambiando el valor del parámetro real original. Para indicar quequeremos que un parámetro pase por referencia utili zaremos la palabra reservada VAR delantede dicho argumento en la cabecera del subprograma. En nuestro ejemplo:

PROCEDURE EscribirModulo ( VAR Real, Imag : LONGREAL);

Page 67: Curso de Modula-2 (Incompleto).pdf

8 6.5 Procedimientos y Funciones

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

En este caso estamos pasando ambos parámetros por referencia y el resultado que obtenemospor pantalla es:

El módulo del complejo 5.0000E+0 6.0000E+0 i es: 7.8102E+02.5000E+03.6000E+0

Cada parámetro puede independientemente estar declarado por valor o referencia:

PROCEDURE EscribirModulo ( VAR Real : LONGREAL; Imag : LONGREAL);

Por referencia sólo el primero

PROCEDURE EscribirModulo (Real : LONGREAL; VAR Imag : LONGREAL);

Por referencia sólo el segundo

Si un argumento está declarado por referencia no podremos pasar como parámetros realesexpresiones, sino SOLO VARIABLES. Para argumentos declarados por referencia, el tipo de lavariable pasada como parámetro debe ser EXACTAMENTE EL MISMO que el del parámetroformal correspondiente.

Tanto el paso por valor como el paso por referencia tienen sus ventajas e inconvenientes:

• Paso por valor:

• Ventajas: Aísla el efecto del subprograma a su propio ámbito. Esto hace más fácilde seguir los programas. Si se usa paso por valor y se sigue el programa principal sinentrar en los subprogramas, se sabe que las variables sólo cambian si cambian en elprincipal.

• Desventajas: Utili za más memoria. El parámetro real y el formal ocupan cada unosu propio trozo de memoria en el ordenador.

• Paso por referencia:

• Ventajas: Utili za menos memoria. El parámetro formal y real son los mismos yocupan el mismo espacio de memoria.

• Desventajas: Sólo permite variables como parámetros reales y el seguimiento delprograma resulta más complejo.

6.5 Procedimientos y Funciones

6.5.1 Diferencias entre procedimientos y funciones

Todos los subprogramas vistos hasta ahora son procedimientos. Un procedimiento es unsubprograma que toma opcionalmente una serie de parámetros y hace algo con ellos. Ejemplosde procedimientos son las instrucciones de salida de datos del módulo de biblioteca IO.

Sin embargo, cuando se diseña un algoritmo aparecen con frecuencia operaciones que calculanun valor simple a partir de ciertos parámetros o argumentos:

• Calcular el volumen de un cubo de lado l: se calcula el valor l3 a partir del parámetro l.

• Calcular la potencia xn : se calcula el valor x elevado a n a partir de dos argumentos x yn.

• Calcular el máximo de dos números a y b: se devuelve el mayor de a y b.

Page 68: Curso de Modula-2 (Incompleto).pdf

Tema 6. Procedimientos y funciones 9

Informática. Facultad de Ciencias (Matemáticas)

Todas estas operaciones se pueden considerar subprogramas del tipo función. Una función esun subprograma que calcula como resultado un valor simple a partir de otros valores dadoscomo argumentos. Una función se asemeja bastante al concepto de función matemática conargumentos:

î >

=

==

casootroenb

basiabaMaximo

xnxPotencia

lloVolumenCubn

,

,),(

),(

)( 3

La definición de una función es similar a la de un procedimiento. Sin embargo, la cabecera deuna función incluye al final el tipo de valor que devuelve precedido de dos puntos. Para losejemplos anteriores las cabeceras en Modula-2 son:

PROCEDURE VolumenCubo (l : REAL) : REAL;PROCEDURE Potencia (x : REAL; n : CARDINAL) : REAL;PROCEDURE Máximo (a, b : REAL) : REAL;

En el cuerpo de la función se debe indicar el valor devuelto. Esto se hace mediante la sentenciaRETURN. La declaración completa de las funciones anteriores es:

PROCEDURE VolumenCubo (l : REAL) : REAL;BEGIN

RETURN (l*l*l)END VolumenCubo;

PROCEDURE Potencia (x : REAL; n : CARDINAL) : REAL;VAR i : CARDINAL;

Pot : REAL;BEGIN

Pot := 1.0;FOR i := 1 TO n DO

Pot := Pot * xEND;RETURN Pot

END Potencia;

PROCEDURE Maximo (a, b : REAL) : REAL;VAR Max : REAL;BEGIN

IF (a>b) THENMax := a

ELSEMax := b

END;RETURN Max

END Maximo;

El tipo de la expresión que sigue a la sentencia RETURN debe ser COMPATIBLE ENASIGNACIÓN con el tipo declarado en la cabecera. Al ejecutarse la sentencia RETURN lafunción termina y se vuelve al programa llamante (aunque hubiese más instrucciones en lafunción). Dentro del cuerpo de una función puede aparecer más de una sentencia RETURN. Sinembargo, esto es una mala práctica de programación y debe ser evitado. Como buena norma deprogramación, EXIGIREMOS que dentro del cuerpo de una función sólo haya una sentenciaRETURN y que ésta sea la última sentencia en el cuerpo de la función (salvo en el caso defunciones recursivas de las que hablaremos en un tema posterior).

La llamada a un procedimiento constituye una sentencia del programa por sí sola. Sin embargo,la llamada a una función representa un valor y no es una sentencia por sí sola. Para construiruna sentencia con una llamada a función debemos hacer algo con el valor que devuelve

Page 69: Curso de Modula-2 (Incompleto).pdf

10 6.5 Procedimientos y Funciones

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

(asignarlo a una variable compatible, escribirlo por pantalla, hacer que forme parte de unaexpresión, etc. ...). Una llamada a función sólo puede aparecer en donde pueda aparecer unaexpresión del tipo de la función. Así, son llamadas válidas a funciones:

x := VolumenCubo(3.0); (* Si x es REAL *)WrReal (Maximo(1.0, 2.0), 5, 0);x := Maximo (Potencia(10.0, 5), Volumen(8.0)); (* Si x es REAL *)

Pero no lo es:

x := x + 1.0;VolumenCubo(3.0); ...

Como ejemplo, las operaciones de entrada del módulo de biblioteca IO son funciones.

6.5.2 Funciones predefinidas

Modula-2 dispone de una serie de funciones predefinidas, que pueden usarse el cualquierprograma sin ser importadas. La li sta de estas funciones es:

ABS(X) CAP(C) CHR(X) FLOAT(X) HIGH(A)MAX(T) MIN(T) ODD(X) ORD(C) SIZE(T)TRUNC(R) VAL(T,X)

En los argumentos C representa un valor de tipo carácter, X de tipo número, T el nombre de untipo y A un array (ver tema sobre tipos de datos estructurados). Hemos descrito todas en lostemas anteriores excepto HIGH(A) (que veremos en el tema sobre tipos de datos estructurados)y VAL(T, X) que devuelve el valor de X convertido al tipo T. Algunas de estas funcionesutili zan tipos como argumentos, cosa que el programador no puede hacer con los subprogramasdefinidos por él.

6.5.3 Procedimientos predefinidos

También existen procedimientos predefinidos en Modula-2. Estos son:

DEC(X) : Decrementa en 1 el valor de la variable X. X debe ser de tipo ordinal.

DEC(X,N) : Decrementa en N el valor de la variable X que debe ser de tipoordinal. N puede ser CARDINAL o INTEGER pero siempre positi va

EXCL(S,X) : Excluye el elemento X del conjunto S (ver tema sobre tipos de datosestructurados).

HALT: Hace que finalice la ejecución del programa. Esta instrucción sólodebe utili zarse en caso de que el programa alcance un error y ésteimpida que sea posible continuar con la ejecución del programa. Lainstrucción HALT debe precederse de una instrucción de salida queindique el error cometido. Nunca debe utili zarse esta sentencia paraotra cosa que no sea un error.

INC(X) : Incrementa en 1 el valor de la variable X que debe ser de tipo ordinal.

INC(X,N) : Incrementa en N el valor de la variable X que debe ser de tipo ordinal.

INCL(S,X) : Incluye el elemento X en el conjunto S (ver tema sobre tipos de datosestructurados)

Page 70: Curso de Modula-2 (Incompleto).pdf

Tema 6. Procedimientos y funciones 11

Informática. Facultad de Ciencias (Matemáticas)

6.6 Uso de parámetrosLos parámetros de un subprograma suelen utili zarse fundamentalmente de tres modos:

• Como parámetros de entrada

• Como parámetros de salida

• Como parámetros de entrada y salida

6.6.1 Parámetros de entrada

Un parámetro es de entrada cuando se usa para pasar un valor desde el programa llamanteal subprograma llamado. Este tipo de parámetros debe declararse por valor.

❏ Ejemplo: El siguiente subprograma escribe por pantalla la tabla de multipli carcorrespondiente al argumento que toma:

PROCEDURE EscribirTablaDe (Num : CARDINAL);VAR i : CARDINAL;BEGIN

FOR i := 1 TO 10 DOWrCard(Num, 0); WrStr(“ * “); WrCard(i,0);

WrStr(“ = “); WrCard(Num*i, 0); WrLn ENDEND EscribirTablaDe;

El modo de usar el suprograma es el siguiente:

...WrStr(“La tabla del 7 es”); WrLn;EscribirTablaDe (7);...

6.6.2 Parámetros de salida

Un parámetro es de salida cuando se usa para pasar un valor desde el subprograma llamadoal programa llamante. Este tipo de parámetros debe declararse por referencia.

Para comunicar un valor desde un subprograma al programa llamante debe utili zarse unafunción. Sin embargo, una función sólo puede devolver un resultado. Si el subprograma ha dedevolver más de un valor, es necesario utili zar parámetros de salida.

❏ Ejemplo: El siguiente subprograma convierte un punto expresado en coordenadas polares alos valores correspondientes en coordenada cartesianas. Los dos primeros parámetros son deentrada y los dos últimos de salida:

PROCEDURE PolaresACartesianas ( Modulo, Angulo : LONGREAL;VAR EjeX, EjeY : LONGREAL );

BEGINEjeX := Modulo * Cos(Angulo);EjeY := Modulo * Sin(Angu lo)

END PolaresACartesianas;

El modo de usar el suprograma es el siguiente:

...PolaresACartesianas (1.0, PI/2.0, x, y);WrStr(“La coordenada X es ”); WrLngReal(x, PRECISION, ANCHO);WrLn;

Page 71: Curso de Modula-2 (Incompleto).pdf

12 6.7 Anidamiento de subp rogramas. Ámbitos

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

WrStr(“La coordenada Y es ”); WrLngReal(y, PRECISION, ANCHO);...

6.6.3 Parámetros de entrada y salida

Un parámetro es de entrada y salida cuando establece una comunicación en ambossentidos entre el programa llamante y el subprograma llamado. El parámetro se usa para pasarun valor desde el programa llamante al subprograma, pero este valor puede también sermodificado por el subprograma y el programa llamante debe, también, ver el cambio. Este tipode parámetros deben declararse por referencia.

❏ Ejemplo: El siguiente subprograma toma un argumento real y lo redondea:

PROCEDURE Redondear ( VAR Num : REAL);BEGIN Num := REAL ( TRUNC (Num + 0.5))END Redondear;

El modo de usar el suprograma es el siguiente:

...x := 10.7;Redondear (x);WrReal(x, 5, 0);...

❏ Ejemplo: El siguiente subprograma intercambia los valores almacenados en dos variables detipo INTEGER, utili zando para ello una tercera variable temporal:

PROCEDURE Intercambiar ( VAR Var1, Var2 : INTEGER);VAR Temp : INTEGER;BEGIN

Temp := Var1;Var1 := Var2;Var2 := Temp

END Intercambiar;

El modo de usar el suprograma es el siguiente:

...x := 10;y := 20;Intercambiar(x,y);WrStr(“El valor de x es “); WrInt(x,0);WrLn;WrStr(“El valor de y es “); WrInt(y,0);...

6.7 Anidamiento de subp rogramas. Ámbitos

6.7.1 Estructura de bloqu es

Un subprograma se define de forma similar a un programa completo. En la parte dedeclaraciones de un subprograma pueden aparecer constantes, variables y otros subprogramas.

Page 72: Curso de Modula-2 (Incompleto).pdf

Tema 6. Procedimientos y funciones 13

Informática. Facultad de Ciencias (Matemáticas)

Si un subprograma sólo se utili za dentro de otro subprograma, debe aparecer declarado dentrode éste. Esto da lugar a lo que se llama anidamiento de subprogramas: subprogramasdeclarados dentro de otro subprograma.

Todo lo que aparece declarado dentro de un subprograma se dice que es local a éste. Estosignifica que las variables, constantes y procedimientos definidos dentro de un subprogramasólo pueden ser usadas por el propio subprograma y por los subprogramas definidos dentro deél, pero no por el programa principal o por los subprogramas externos. Así surge una estructurade bloques, de modo que los bloques más internos pueden acceder a lo declarado en los bloquesque les anidan pero no al revés:

Bloque A

Bloque D

Bloque C

Bloque B

Bloque F

Bloque G

Bloque E

Figura 3. Visibilidad entre bloques

La siguiente tabla muestra qué declaraciones ve cada bloque:

Bloque Bloques a cuyas declaraciones accedeA AB B, AC C, B, AD D, C, B, AE E, AF F, E, AG G, E, A

Además, hay que tener en cuenta que un subprograma puede llamar a otro que esté previamentedeclarado, por lo que E y F pueden llamar además al subprograma B, y G a F y B. En general, sise utili za un identificador en la declaración de otro identificador, el primero debe estardeclarado antes. Por ejemplo, si se desea utili zar una variable no local en un subprograma ladeclaración de esta variable debe ser anterior a la declaración del subprograma.

Modulo-2 permite además que un subprograma se llame a sí mismo, que es lo que se denominasubprograma recursivo. Hablaremos de esto con más detalle en un tema posterior.

Page 73: Curso de Modula-2 (Incompleto).pdf

14 6.7 Anidamiento de subp rogramas. Ámbitos

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

6.7.2 Redefinición d e elementos

Dentro de cada bloque se deben declarar los elementos necesarios dándoles los nombres másadecuados en cada caso. Puede ocurrir que dentro de un bloque se defina un elemento con elmismo nombre que un elemento definido en otro bloque y que también sea accesible. En dichocaso se pierde la accesibili dad al elemento más externo.

Sea el siguiente programa:

MODULE Ejemplo;VAR a, b, c : INTEGER;

PROCEDURE Anidado1 (a : REAL);VAR b : REAL;

PROCEDURE Anidado2;VAR c, d : CHAR;BEGIN

Cuerpo de Anidado2END Anidado2;

BEGINCuerpo de Anidado1

END Anidado1;

BEGINCuerpo del principal

END Ejemplo.

El procedimiento Anidado1 tiene visibili dad, en principio, sobre las variables a, b y c delprograma principal por estar anidado dentro de él. Sin embargo, uno de sus parámetros se llamaa y una variable local b, por lo que pierde la accesibili dad sobre las variables a y b delprograma principal. Si accedemos a las variables a y b dentro del cuerpo de Anidado1,estaremos accediendo a las suyas locales. Aún así, podremos acceder a la variable c delprincipal, ya que no hay ninguna c local. En el cuerpo del procedimiento Anidado2, sinombramos la variable c estaremos accediendo a la de tipo CHAR y si accedemos a a y b loharemos a las de Anidado1 . La variable d sólo es visible desde el cuerpo de Anidado2 .

Hay que señalar además que, si la declaración de las variables del programa principal, serealizan después de las declaraciones de los subprogramas Anidado1 y Anidado2 , éstospierden automáticamente el acceso a dichas variables: RECUERDE: SOLO SE PUEDEACCEDER A ELEMENTOS YA DEFINIDOS.

6.7.3 Efectos laterales

Hemos visto que un subprograma puede acceder a variables no locales a él, siempre que nohaya colisión de nombres. Cuando un subprograma accede a una variable que no es ni local a élni es un parámetro formal suyo decimos que se está produciendo un efecto lateral.

Este tipo de situaciones son válidas en Modula-2 pero nosotros las PROHIBIREMOStotalmente. Cuando se declara un subprograma con una serie de parámetros se está diciendoque el subprograma depende únicamente de ellos. Un efecto lateral traiciona este convenio yhace que los programas sean menos claros y más difíciles de entender.

Siempre es posible que un subprograma no efectúe efectos laterales: si un subprograma necesitauna serie de valores deben aparecer todos en la cabecera de su declaración y si necesitavariables para realizar cálculos locales a él, se deben declarar como variables locales.

Page 74: Curso de Modula-2 (Incompleto).pdf

Tema 6. Procedimientos y funciones 15

Informática. Facultad de Ciencias (Matemáticas)

6.7.4 Doble referencia

La doble referencia se produce cuando un mismo elemento se referencia con dos nombresdistintos. Esto suele ocurrir en dos situaciones concretas:

1) Cuando un subprograma utili za una variable externa que también se le pasa comoargumento

2) Cuando en la llamada a un subprograma se le pasa la misma variable en más de unargumento.

En ambos casos se pueden producir resultados difíciles de entender. Veamos un ejemplo de laprimera situación:

...VAR Global : INTEGER;...

PROCEDURE Cuadrado ( VAR Dato : INTEGER);BEGIN

Global := 5;Dato := Dato * D ato;

END Cuadrado;...Global := 3;Cuadrado (Global);...

Después de la llamada a Cuadrado(Global) la variable Global vale 25 cuando esperaríamosque valiese 9. Este tipo de situaciones se puede evitar si no usamos efectos laterales.

Un ejemplo del segundo tipo de situación es:

PROCEDURE CuadradoCubo ( VAR x1, x2, x3 : INTEGER);BEGIN

x2 := x1*x1;x3 := x1*x1*x1

END CuadradoCubo;

que devuelve el cuadrado y el cubo del primer argumento en los argumentos segundo y tercero,y la siguiente llamada:

...A := 4;CuadradoCubo (A, A, B);...

Tras la ejecución de este fragmento de programa, los valores de las variables son A = 16 y B =4096, en vez de 64. Este problema se podría haber resuelto declarando el primer argumentocomo parámetro por valor.

6.8 Sintaxis BNF para subp rogramasVeamos la sintaxis BNF para la declaración de subprogramas en Modula-2:

Declaración_Subprograma := Cabecera_Subprograma ;

Bloque

Identificador ;

Cabecera_Subprograma ::= Cabecera_de_Procedimiento | Cabecera_de_Función

Cabecera_de_Procedimiento ::= PROCEDURE Identificador [ Parámetros_Formales ]

Page 75: Curso de Modula-2 (Incompleto).pdf

16 6.8 Sintaxis BNF para subp rogramas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Cabecera_de_Función ::= PROCEDURE IdentificadorParámetros_Formales : Identificador_de_Tipo

Parámetros_Formales ::= ( [ Grupo_de_Parámetros { ; Grupo_de_Parámetros } ] )

Grupo_de_Parámetros ::= [ VAR ] Lista_de_Identificadores : Identificador_de_Tipo

Bloque ::= Parte_Declarativa Parte_Ejecutiva END

Parte_Declarativa ::= { Declaración }

Declaración ::= Declaración_de_Constantes | Declaración_de_Variables |Declaración_Subprograma

La sintaxis para la sentencia RETURN es:

Sentencia_RETURN ::= RETURN [ Expresión ]

La llamada a un procedimiento es una sentencia:

Sentencia_de_Llamada_a_Procedimiento

::= Identificador [ Parámetros_de_Llamada ]

Parámetros_de_Llamada ::= ( [Lista_de_Expresiones] )

Lista_de_Expresiones ::= Expresión { , Expresión }

Por último la llamada a una función es un factor (ver definición de Expresión):

Factor ::= Variable | Identificador_de_Constante | ...

... | Llamada_a_Función

Llamada_a_Función ::= Identificador Parámetros_de_Llamada

Obsérvese que tanto en la llamada como en la definición de procedimientos, si no hayargumentos, los paréntesis son opcionales, mientras que en las funciones son siempreobligatorios.

Page 76: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 6) 1

Informática. Facultad de Ciencias (Matemáticas)

Relación d e Problemas 61. Supongamos que tenemos un programa principal con las siguientes variables:

VAR

x, y : REAL;m : INTEGER;c : CHAR;n : CARDINAL;

y la siguiente declaración de subprograma:

PROCEDURE Prueba (a, b : INTEGER; VAR c, d : REAL; VAR e : CHAR);

Averigua cuáles de las siguientes llamadas son válidas:

1) Prueba (m+3,10,x,y,c);

2) Prueba (n+3,10,x,y,c);

3) Prueba (m, 19, x, y);

4) Prueba (m, m*m, y, x, c);

5) Prueba (m, 10, 35.0, y, ‘E’);

6) Prueba (30, 10, x, x+y, c);

2. Escribe una función que calcule las combinaciones de m elementos tomados de n en n.Para ello escribir primero otra función que calcule el factorial de un número.

NOTA: Recuérdese que

mn

m

n m n

=

−!

!( )!

Escribe otra función más eficiente que no necesite calcular el factorial.

3. Escribe una función que tome tres parámetros, dos de tipo REAL y uno de tipo CHAR. Lafunción debe sumar, restar, multipli car o dividir los valores de los dos primerosparámetros dependiendo del código indicado en el tercero (+,-,*,/) y devolver el resultado.Al diseñar esta función, supón que el tercer argumento es necesariamente uno de loscuatro (+,-,*,/).

Escribe un programa que ofrezca al usuario la posibili dad de realizar una de esas cuatrooperaciones o sali r del programa hasta que el usuario decida abandonar el programa, lealos operandos necesarios para realizar la operación, utili ce la función anterior para hacerlos cálculos y muestre el resultado en pantalla. Asegúrate de que el programa utili za lafunción anterior de forma correcta.

4. Dos números a y b se dice que son amigos si la suma de los divisores de a (salvo elmismo) coincide con b y viceversa. Diseña un programa que tenga como entrada dosnúmero naturales n y m, y muestre por pantalla todas las parejas de números amigos queexistan en el intervalo determinado por n y m.

Page 77: Curso de Modula-2 (Incompleto).pdf

2 Relación d e Problemas (Tema 6)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

5. Considera el siguiente procedimiento:

PROCEDURE Escr (C : CHAR; Long : INTEGER);BEGIN

WHILE Long > 0 DOWrChar (C);Long := Long – 1

ENDEND Escr;

a) Si Ch tiene el valor ‘X’ y Numero el valor 5, ¿cuál sería el efecto de ejecutar cadauna de las siguientes llamadas al procedimiento?:

Escr(Ch,4*Numero-12) Escr(Ch,6) Escr(5,Numero)Escr(‘/’,Numero) Escr(‘.’,6) Escr(‘p’,-10)

b) Escribe llamadas al procedimiento Escr para que cuando se ejecuten produzcanlas siguientes salidas:

• 35 guiones sucesivos

• 6 veces tantos espacios en blanco como el valor de Numero

• el valor actual de Ch 14 veces

6. Dadas las siguientes declaraciones en un determinado algoritmo:

VAR a,b,c : CARDINAL;si : BOOLEAN;

...PROCEDURE Uno(x, y : CARDINAL) : BOOLEAN;...PROCEDURE Dos(VAR x : CARDINAL; y : CARDINAL);...PROCEDURE Tres(x : CARDINAL) : CARDINAL;

¿ Cuáles de las siguientes llamadas a subprograma son válidas?

a) IF Uno(a,b) THEN...

b) Dos(a,b+3)

c) si := Uno(c,5)

d) si := Dos(c,5)

e) Dos(a,Tres(a))

f) Dos(Tres(b),c)

g) IF Tres(a) THEN ...

h) b := Tres(Dos(a,5))

i) Dos(4,c)

7. Escribe un algoritmo que tome como entrada desde teclado dos números naturales N e i , eimprima en pantalla el dígito que ocupa la posición i-ésima del número N. Si i es mayorque el número de dígitos de N, se escribirá en pantalla el valor -1. Por ejemplo, para N =25064 e i = 2, el resultado es el dígito 6, y para i = 7, el resultado es -1.

8. ¿ Qué salida produce por pantalla la ejecución del siguiente algoritmo?

MODULE Anidado;FROM IO IMPORT WrStr, WrCard, WrLn;VAR a, b, c, x, y : CARDINAL;

PROCEDURE Primero;BEGIN

Page 78: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 6) 3

Informática. Facultad de Ciencias (Matemáticas)

a := 3 * a;c := c + 4;WrStr (“Primero”);WrCard (a, 0); WrCard (b, 0); WrCard (c, 0);WrLn

END Primero;PROCEDURE Segundo;VAR b : CARDINAL;BEGIN

b := 8;c := a + c + b DIV 3;WrStr (“Segundo”);WrCard (a, 0); WrCard (b, 0); WrCard (c, 0);WrLn

END Segundo;PROCEDURE Tercero ( VAR x : CARDINAL; y : CARDINAL);BEGIN

x := x + 4;y := y + 1;WrStr (“Tercero”);WrCard (a, 0); WrCard (b , 0);WrCard (c, 0); WrCard (x, 0);WrLn

END Tercero;BEGIN

a := 3; b := 2;c := 1; x := 11;y := 22;Primero; Segundo;Tercero (a,b);WrStr (“Anidado”);WrCard (a, 0); WrCard (b, 0);WrCard (c, 0); WrCard (x, 0);WrCard (y, 0)

END Anidado.

9. Realiza un procedimiento que intercambie el valor de dos variables de tipo CHAR.

10. Escribe un procedimiento que, dadas las coordenadas polares de un número complejo (r,θ), obtenga las correspondientes cartesianas (x, y).

NOTA: Recordar que

x r

y r

= ⋅= ⋅

cos

sen

θθ

11. Escribir un programa que lea un número positi vo del teclado y escriba por pantalla losnúmeros perfectos menores a él. Para ello definir primero una función EsPerfecto quetome como parámetro un número y devuelva TRUE o FALSE dependiendo de que seaperfecto o no.

12. Escribe un programa que lea un número positi vo menor que 100 y escriba la traducción dedicha cantidad a inglés. Por ejemplo para la entrada 42 se obtendría la salida “forty two” .

Page 79: Curso de Modula-2 (Incompleto).pdf

4 Relación d e Problemas (Tema 6)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Relación complementaria 61. Escribe un algoritmo que acepte como entrada desde teclado un número entero positi vo.

El algoritmo debe producir como salida el resultado de sumar dos a dos los dígitos queaparecen en posiciones simétricas respecto al dígito central dentro del número dado comoentrada. Por ejemplo, para el número 23548 la salida es: 2+8 = 10, 3 + 4 = 7, 5 para elnúmero 6582 la salida es: 6 + 2 = 8, 5 + 8 = 13

2. Escribe un subprograma para calcular el máximo común divisor de cuatro númerosutili zando para ello otro subprograma que calcule el máximo común divisor de dosnúmeros (algoritmo de Euclides).

3. Escribe un programa que lea dos enteros positi vos correspondientes a un año y un mes, yescriba el correspondiente calendario de la siguiente forma:

D L M X J V S 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1516 17 18 19 20 21 2223 24 25 26 27 28 29

Este problema puede dividirse en las siguientes partes:

1) Leer los valores del mes y año

2) Encontrar el día de la semana en que empieza el mes (ver ejercicio sobrecongruencia de Zeller).

3) Averiguar cuántos días tiene el mes.

4) Escribir el correspondiente calendario.

Usa un subprograma separado para cada parte.

4. Escribe un programa que lea un número positi vo del teclado y escriba por pantalla losnúmeros primos menores a él. Para ello define primero una función EsPrimo que tomecomo parámetro un número y devuelva TRUE o FALSE dependiendo de que sea primo o no.

5. Escribe un programa que calcule el máximo de tres números enteros, definiendopreviamente una función que calcule el máximo de dos.

El ejercicio 3 se realizará como práctica en el laboratorio.

Page 80: Curso de Modula-2 (Incompleto).pdf

Tema 7. Tipos de datos s imples. 1

Informática Facultad de Ciencias (Matemáticas)

Departamento de Lenguajes yCiencias de la Computación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)

http://www.lcc.uma.es/personal/pepeg/mates

Tema 7. Tipos de datos s imples7.1 Concepto de tipo de datos. Clasificación................................. ......................... 2

7.1.1 Clasificación de tipos en Modula-2 ....................................................... 2

7.2 Tipos simples definidos por el programador.................................................... 4

7.2.1 Tipo enumerado ................................................................ ...................4

7.2.2 Tipo subrango ................................................................ ...................... 6

7.3 Compatibilidad de Tipos en Modula-2 .............................................................. 7

7.4 Tipos procedimiento y función................................................................ ..........8

Bibliografía• Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de

Educación a Distancia.

• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

Page 81: Curso de Modula-2 (Incompleto).pdf

2 7.1 Concepto de tipo d e datos. Clasificac ión.

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Introdu cc iónEn este tema definimos el concepto de tipo de dato en un lenguaje de programación. También seclasifican los distintos tipos de datos que proporciona el lenguaje Modula-2. Además, sepresentan las declaraciones de tipos que permiten al programador definir nuevos tipos de datos.En concreto, se estudian tres tipos de datos definibles por el programador: enumerados,subrangos y tipos subprogramas. Por último, se definen las reglas que sigue el compilador paradetectar errores de tipo en un programa.

7.1 Concepto de tipo d e datos. Clasificac ión.Un tipo de datos es una descripción formal del conjunto de valores ( o dominio ) que unavariable o expresión de dicho tipo puede tener, junto con el conjunto básico de operaciones quepueden ser aplicadas a estos valores.

En un lenguaje de alto nivel el concepto de tipo es de una gran importancia. En Modula-2, ladeclaración de una variable debe ir acompañada por la especificación de su tipo, ya que éstedetermina el espacio de memoria requerido para su almacenamiento y las combinaciones deoperadores y operandos permitidos. El tipo de una constante puede ser deducidoautomáticamente por el compilador.

El aspecto práctico más importante de los datos es el modo en que pueden ser manipulados. Paraello, a cada tipo de datos se le asocia un conjunto de operadores básicos. La selección de estosoperadores básicos es en cierta medida arbitraria, y podría haberse aumentado o disminuido. Elcriterio habitualmente seguido es seleccionar el conjunto mínimo de operadores que permita alprogramador construir cualquier operación de un modo razonablemente eficiente.

Los operadores más importantes definidos para cualquier tipo de dato son:

• La asignación (: = ). Evalúa la expresión a su derecha y guarda el resultado en lavariable a su izquierda.

• La verificación de igualdad ( = ). Comprueba si los valores a su izquierda y a suderecha son iguales.

Un mismo símbolo (por ejemplo los dos operadores anteriores) puede utili zarse como operadorpara distintos tipos de datos. Esto se denomina sobrecarga. EL operador + también estásobrecargado, ya que puede usarse para sumar valores de tipo INTEGER, CARDINAL y REAL(aunque los tipos de los dos argumentos han de ser compatibles).

7.1.1 Clasificac ión d e tipos en Modu la-2

Podemos clasificar los tipos que aparecen en el lenguaje Modula-2 como:

Page 82: Curso de Modula-2 (Incompleto).pdf

Tema 7. Tipos de datos s imples. 3

Informática Facultad de Ciencias (Matemáticas)

• Tipos simples (escalares)• Ordinales

• Predefinidos• CARDINAL, LONGCARD• INTEGER, LONGINT• CHAR• BOOLEAN

• Definidos por el programador• Enumerados• Subrango

• REAL, LONGREAL• Tipos procedimiento y función• Tipo estrucuturados

• ARRAY• RECORD• SET• FILE

• POINTER

Todos los tipos simples son tipos escalares, ya que:

a) Están formados por elementos indivisibles

b) Están ordenados, es decir, se pueden comparar usando =, <>, >, ...

Todos los tipos simples, excepto los tipos reales, son ordinales:

c) Además de a) y b) cada valor (excepto el primero y el último) tiene un predecesor y unsucesor único.

Para todos los tipos ordinales podremos usar las siguientes operaciones:

• ORD(X) es una función que devuelve un CARDINAL (de cero en adelante),correspondiente al orden de X.

• VAL(T,X) es una función que dado un tipo T y un número de orden X devuelve el valor detipo T con dicho orden. Nótese que ORD(X) = VAL ( CARDINAL, X) (X de un tipo ordinal)y CHR(X) = VAL( CHAR, X) (X valor entero entre 0 y 255) .

• INC(X) es un procedimiento que asigna a la variable X el sucesor del valor que contenga.Es un error utili zar INC(X) si X contiene el último valor posible para el tipo.

• DEC(X) es un procedimiento que asigna a la variable X el antecesor del valor quecontenga. Es un error utili zar DEC(X) si X contiene el primer valor posible para el tipo.

• INC(X,N) y DEC(X,N) . Aplican N veces INC(X) o DEC(X) respectivamente. N puede serde tipo INTEGER o CARDINAL.

• MAX(T) es una función que devuelve el máximo valor posible para el tipo T.

• MIN(T) es una función que devuelve el mínimo valor posible para el tipo T.

Recordemos que la variable de control de un bucle FOR debe ser ordinal y que el tipo de laexpresión en una sentencia CASE también.

Los operadores tienen que aplicarse a objetos de tipos de datos compatibles (iguales o no). Lainformación del tipo de dato ayuda a los compiladores a detectar operaciones inapropiadas contipos de datos no compatibles.

Page 83: Curso de Modula-2 (Incompleto).pdf

4 7.2 Tipos s imples definidos por el programador

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

7.2 Tipos s imples definidos por el programadorAunque los tipos simples predefinidos vistos son útiles para cualquier propósito (que no requieratipos estructurados), es conveniente que el programador pueda definir sus propios tipos simplespor dos razones principalmente:

1) Interpretación de cada valor. Si una variable representa un número de naranjas y otra unnúmero de personas, y representamos ambas variables con tipo CARDINAL podríamossumar naranjas y personas, lo cual no tiene mucho sentido. Sería mejor poder definir untipo NARANJAS y otro PERSONAS.

2) Dejar claro el rango de los posibles valores. Si sabemos a priori que para resolver ciertoproblema el valor de una variable nunca va a sali rse de cierto rango, es convenientedeclarar la variable con un nuevo tipo que se corresponda a dicho rango para que, en elcaso de que por error tome un valor fuera de este rango, el compilador nos avise de ello.

La especificación de nuevos tipos se realiza usando una declaración de tipo. Por ejemplo:

TYPE COLOR = ...VAR Color1, Color2: COLOR;

Una declaración de tipo debe hacerse en la parte declarativa del programa antes de la declaraciónde variables de ese tipo y consiste en la palabra reservada TYPE seguida por el nombre del tipo,el signo igual y la especificación del tipo. En notación BNF:

Declaracion_de_Tipo ::= TYPE Identificador_de_Tipo = Tipo_Enumerado |

Tipo__Subrango |

Tipo_Función |

Tipo_Procedimiento | ...

Identificador_de_Tipo ::= Identificador

7.2.1 Tipo enumerado

Consiste en una enumeración de todos los posibles valores que puede tomar una variable dedicho tipo encerrados entre paréntesis. Una variable de tipo enumerado sólo podrá tomar, en undeterminado momento, uno de esos valores.

El uso de tipos enumerados ayuda a mejorar la legibili dad de los algoritmos cuando los valoresde ciertas variables tienen una determinada interpretación. Si quisiéramos definir una variablepara que represente una situación de un problema en el que hay cinco posibles colores, (Rojo,Amarill o, Verde, Azul y Naranja) podríamos hacer lo siguiente:

CONSTRojo = 0 ;Verde = 1 ;Azul = 2 ;Amarillo = 3 ;Naranja = 4 ;

VARColor1, Color2 : CARDINAL ;

Sin embargo, en Modula-2 podemos definir un nuevo tipo ordinal que conste de esos cincovalores exactamente:

TYPE COLOR = (Rojo, Verde, Azul, Amarillo, Naranja);VAR Color1, Color2 : COLOR;

Page 84: Curso de Modula-2 (Incompleto).pdf

Tema 7. Tipos de datos s imples. 5

Informática Facultad de Ciencias (Matemáticas)

La declaración de un tipo de esta índole consiste en asociar a un identificador una enumeraciónde los posibles valores que una variable de ese tipo puede tomar.

Otros ejemplos de tipos enumerados son:

TYPE PALO = (Oros, Copas, Espadas, Bastos);

DIA = (Lunes, Martes, Miercoles, Jueve s, Viernes, Sabado, Domingo);

SEXO = (Hombre, Mujer);FIGURA = (Circulo, Triangulo, Cuadrado, Rectangulo);

Un mismo valor NO PUEDE aparecer la declaración de DOS TIPOS ENUMERADOS distintos.Es decir, dada la declaración anterior la siguiente declaración NO es válida, ya que Rojo, Verde yAzul están usados en el tipo COLOR:

TYPE COLORBASICO = (Rojo, Verde, Azul);

El orden de los valores de estos nuevos tipos declarados por el programador será aquel en queaparecen dentro de la li sta de enumeración de los elementos del tipo. El tipo enumerado estambién escalar y ordinal.

La función ORD devuelve el número ordinal de un valor perteneciente a un tipo enumerado. Lafunción VAL produce el efecto contrario:

Expresión Valor

ORD(Rojo) 0ORD(Azul) 2VAL(COLOR,1) Verde

VAL(COLOR,4) Naranja

Al tratarse de tipos ordinales, los valores de tipo enumerado tienen su predecesor (excepto elprimero del tipo) y sucesor (excepto el ultimo del tipo), por lo que es válido:

IF Color1 < Azul THEN ...FOR Color1 := Rojo TO Azul DO...CASE Color1 OF

Rojo: ...

No existen operaciones aritméticas definidas para los tipos enumerados. Por lo tanto, esINVÁLIDO:

Color1 := Color1 + 1;

Sí se pueden utili zar, en cambio, los procedimientos generales INC y DEC.

Hay que tener en cuenta que se pueden producir errores al emplear los procedimientos INC y DECsi se excede el rango del tipo de la variable:

VAR Color1 : COLOR;i : INTEGER;

...Color1 := Rojo;i := 1000;INC (Color1); ---> Color1 = Amarill oINC (i); ---> i = i + 1 = 1001DEC (Color1, 4); ---> ErrorINC (i,40000); ---> Error

...

Page 85: Curso de Modula-2 (Incompleto).pdf

6 7.2 Tipos s imples definidos por el programador

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Los valores de tipo enumerado no pueden leerse ni escribirse directamente. Es tarea delprogramador el implementar los procedimientos y funciones adecuados. Por ejemplo el siguienteprocedimiento puede ser usado para escribir un valor del tipo COLOR:

PROCEDURE WrColor(c : COLOR);BEGIN

CASE c OFRojo : WrStr (“Rojo”) |Verde : WrStr (“Verde”) |Amarillo : WrStr (“Amarillo”) |Azul : WrStr (“Azul”) |Naranja : WrStr (“Naranja”)

ENDEND WrColor;

La sintaxis BNF para la declaración de un tipo enumerado es:

Tipo_Enumerado ::= (Lista_de_Identificadores) ;

Por último comentemos que el tipo BOOLEAN es realmente un tipo enumerado definido como:

TYPE BOOLEAN = ( FALSE, TRUE);

para el cual han sido definidos otros operadores adicionales: AND, OR y NOT.

7.2.2 Tipo subrango

Siempre que podamos, debemos definir tipos cuyo rango de valores esté contenido en el rango devalores de otros tipos ordinales, ya que ayuda a clarificar el rango de valores que pueden tomardeterminadas variables, evitando o descubriendo posibles errores. Los tipos con estacaracterística se llaman tipos subrango. Por ejemplo:

TYPECOLOR = (Rojo, Verde, Azul, Amaril lo, Naranja);EDAD = [0..130]; (* Subrango de CARDINAL *)NOTA = [0..10]; (* Subrango de CARDINAL *)DIADELMES = [1..31]; (* Subrango de CARDINAL *)LETRAMINUSCULA = ['a'...'z']; (* Subrango de CHAR *)ENTEROPEQUENYO = [-10..10]; (* Subr ango de INTEGER *)COLORPRIMARIO = [Rojo..Azul]; (* Subrango de COLOR *)

VAR EdadAlumno: EDAD;NotaAlumno: NOTA;

Los valores de un tipo subrango deben ser un rango de valores CONSECUTIVOS pertenecientesa un tipo ya definido, al cual se le denomina tipo base. SÓLO tipos ORDINALES pueden sertipos base.

En la definición del tipo se puede indicar el tipo base:

Edad = [0..130]; (* Subrango de CARDINAL *)Edad = INTEGER [0..130]; (* Subrango de INTEGER *)

pero se puede también omiti r, pues el compilador puede calcularlo a partir del tipo de lasexpresiones en todos los casos, salvo si es incapaz de decidir si se trata de CARDINAL oINTEGER, en cuyo caso se toma por defecto el tipo CARDINAL.

Uno de los motivos para usar los tipos subrango o enumerado es detectar cierta clase de fallos enla que se dan valores fuera de rango. No obstante, por defecto el compilador no detecta este tipode errores, por lo cual se producen resultados indefinidos en tiempo de ejecución de losprogramas. En Top-Speed, si queremos que lo haga hay que indicárselo expresamente con una

Page 86: Curso de Modula-2 (Incompleto).pdf

Tema 7. Tipos de datos s imples. 7

Informática Facultad de Ciencias (Matemáticas)

anotación en el programa. Es lo que se llama una directiva para el compilador, que se sitúa alprincipio del programa escribiendo (*#check (range=>on) * ). El mismo efecto se consigueponiendo a on la opción correspondiente dentro del submenú Runtime cheks del menú Project.En caso de que en ejecución se presente un error de los que controla dicha directiva, aparecerá unmensaje de error indicándolo y preguntará si queremos ir al lugar del fichero fuente en el que seprodujo. Hay que tener en cuenta que cuando está activa esta directiva la velocidad de ejecucióndecrece apreciablemente, por lo que normalmente sólo se usa en las etapas iniciales deldesarrollo de un programa, de forma que cuando éste ha sido probado y suponemos que funcionase vuelve a compilar, pero sin indicar la directiva, con lo que el código objeto obtenido es máseficiente.

La sintaxis BNF para definir tipos subrango es:

Tipo_Subrango ::= [Identificador_de_Tipo] [Expresión_Constante.. Expresión_Constante] ;

Las expresiones constantes deben tener tipo ordinal.

Como tipo ordinal que es, al tipo subrango también se le pueden aplicar las funciones que vimosen el primer apartado de este tema.

7.3 Compatibili dad de Tipos en Modu la-2Modula-2 es un lenguaje fuertemente tipado. Esto significa que el compilador chequea lostipos de los valores que aparecen en las sentencias y expresiones para comprobar el uso correctode los mismos. Para ver las reglas que se siguen para ello definiremos previamente:

• Tipos Equivalentes: Se dice que dos tipos son equivalentes si tienen el mismonombre, o están derivados del mismo nombre de tipo. Ejemplo:

TYPET1 = REAL;T2 = T1;T3 = T1;

Son todos tipos equivalentes.

Se requiere que los tipos de los parámetros formales y reales sean equivalentes, si el pasode éstos es por referencia.

• Tipos Compatibles: Dos tipos T1 y T2 son compatibles, si y sólo si es cierta una delas siguientes condiciones:

1) T1 y T2 son tipos equivalentes

2) T2 es subrango de T1 o viceversa.

3) T1 y T2 son subrangos del mismo tipo base.

Modula-2 requiere compatibili dad de tipos para:

1) Los operandos de una expresión aritmética.

2) Los operandos de una expresión relacional.

3) Las etiquetas y expresión de una sentencia CASE.

4) El valor inicial, límite y variable de control de un bucle FOR.

• Compatibilidad de asignación: Dos tipos son compatibles en la asignación si soncompatibles o si ambos son INTEGER o CARDINAL, o bien subrangos de los tiposINTEGER o CARDINAL. Ejemplo:

Page 87: Curso de Modula-2 (Incompleto).pdf

8 7.4 Tipos procedimiento y función

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

TYPET1 = [0..10];T2 = [- 3..3];

Modula-2 requiere este tipo de compatibili dad para:

1) La variable y la expresión de una sentencia de asignación.

2) El tipo del índice de un ARRAY y la expresión usada como índice (Tema 8).

3) Un parámetro por valor y su correspondiente formal.

4) EL tipo del resultado que devuelve una función y el valor que sigue al RETURNde dicha función.

7.4 Tipos procedimiento y funciónEn Modula-2 es posible declarar variables de tipo subprograma (procedimientos o funciones) yasignar valores a éstas. Los valores asignables son nombres de subprogramas. Dichas variablespueden ser usadas como identificadores de subprogramas en una sentencia de llamada aprocedimiento o función y el subprograma que se llame será el último que se haya asignado a lavariable. Por ejemplo, el siguiente programa pide al usuario que eli ja una entre varias funciones,un punto x y evalúa la función en dicho punto:

MODULE FuncionesFROM IO IMPORT WrStr, WrLn, WrLngReal, RdLngReal, RdLn, RdChar;FROM MATHLIB IMPORT Sin, Sqrt;CONST

PRECISION = 5;TYPE

FUNCION = PROCEDURE ( LONGREAL) : LONGREAL;VAR

f : FUNCION;x : LONGREAL;Opcion : CHAR;

PROCEDURE Cuadrado ( X : LONGREAL) : LONGREAL;BEGIN RETURN x*xEND Cuadrado;

PROCEDURE Cubo ( X : LONGREAL) : LONGREAL;BEGIN RETURN x*x*xEND Cubo;

BEGINWrStr (“Dame x:”);x := RdLngReal(); RdLn;

WrStr (“1. Cuadrado”); WrLn;WrStr (“2. Cubo”); WrLn;WrStr (“3. Seno”); WrLn;WrStr (“4. Raiz cuadrada”); WrLn;

WrStr (“Qué función: “);Opcion = RdChar(); RdLn;

CASE Opcion OF‘1’ : f := Cuadrado |

Page 88: Curso de Modula-2 (Incompleto).pdf

Tema 7. Tipos de datos s imples. 9

Informática Facultad de Ciencias (Matemáticas)

‘2’ : f := Cubo |‘3’ : f := Sin |‘4’ : f := Sqrt

END;

WrStr (“El valor de la función en el punto es: “);WrLngReal (f(x), PRECISION, 0)

END Funciones.

La variable f es una variable de tipo función. En concreto se puede asignar a f el nombre decualquier función que tome un valor LONGREAL y devuelva un valor LONGREAL. El tipoFUNCION es el tipo de todas las funciones con rango un valor LONGREAL y dominio un valorLONGREAL. No se puede asignar a f el nombre de otra función que no tenga este tipo. Porsupuesto, podemos declarar distintos tipos funciones correspondientes a otras clases defunciones:

TYPEFUNCION2 = PROCEDURE ( INTEGER, INTEGER) : INTEGER;FUNCION3 = PROCEDURE ( CHAR) : INTEGER;

FUNCION2 es el tipo de aquellas funciones que toman dos enteros y devuelven un entero.Similarmente FUNCION3 es el tipo de las funciones que toman un carácter y devuelven un valorentero.

Podemos observar que se pueden asignar funciones importadas de otros módulos como son Sin ySqrt , siempre y cuando sean del tipo adecuado. No podremos asignar nombres de subprogramasanidados. Sólo se pueden asignar nombres de subprogramas definidos en el nivel más externo oimportados de otros módulos. Tampoco se pueden asignar nombres de operadores (+, - , ...).

Todo lo explicado para funciones vale para procedimientos. Tipos procedimientos válidos son:

TYPEPROCEDIMIENTO1 = PROCEDURE ( INTEGER, INTEGER);PROCEDIMIENTO2 = PROCEDURE ( CHAR);

La sintaxis BNF para los tipos función y procedimientos son:

Tipo_Procedimiento ::= PROCEDURE [Lista_de_Tipos_Formales ] ;

Tipo_Función ::= PROCEDURE Lista_de_Tipos_Formales : Identificador_de_Tipo ;

Lista_de_Tipos_Formales ::= ( [ Tipo_Formal { , Tipo_Formal } ] )

Tipo_Formal ::= [ VAR ] Identificador_de_Tipo

Page 89: Curso de Modula-2 (Incompleto).pdf
Page 90: Curso de Modula-2 (Incompleto).pdf

Tema 7. Tipos de datos s imples. 1

Informática Facultad de Ciencias (Matemáticas)

Relación d e Problemas (Tema 7)1. Escribe un programa que solucione el sistema de ecuaciones:

ax by cdx ey f

+ =+ =

Para ello diseña un subprograma que tome como parámetros por valor a, b, c, d, e y f ,como parámetros de salida por referencia x, y y Estado , donde Estado es del tipoenumerado:

TYPE Estado = (Determinado, Indeterminado, Incompatible);

Si el sistema está determinado x e y contendrán la solución al sistema y Estado valdráDeterminado . En otro caso Estado valdrá Indeterminado o Incompatible y se enviaráun mensaje al usuario indicando el estado del sistema.

El programa principal deberá leer los coeficientes, llamar al subprograma y escribir elresultado por pantalla.

NOTA: Si ae - bd = 0 y bf - ec = 0 el sistema es indeterminado. Si ae-bd = 0 pero bf-ec ≠0el sistema es incompatible.

2. Escribir una función que tome como parámetros dos funciones f y g ambas de rango ydominio LONGREAL, un valor x de tipo LONGREAL y devuelva f compuesta de g evaluadaen el punto x. Probar la función con casos concretos de f y g.

NOTA: ( )( ) ( ( ))f g x f g x� =

3. Escribir un subprograma que tome como parámetro una función f de rango y dominioLONGREAL y un valor x de tipo LONGREAL, y devuelva un valor aproximado de laderivada de f en dicho punto utili zando para ello la siguiente fórmula con ε igual a unamill onésima.

f xf x f x

' ( )( ) ( )

=+ −ε

εEscribir un programa que utili ce la función anterior para calcular el valor de la derivadade las funciones seno y coseno en los puntos π y π/2.

4. Escribir una función que encuentre un cero de una función utili zando el algoritmo debipartición. Este algoritmo toma como parámetros, entre otros, una función f (de dominioy rango LONGREAL que suponemos continua), y tres valores a, b y Epsilon de tipoLONGREAL, y devuelve el cero calculado. El algoritmo debe comprobar que el valor deb sea mayor que a y que el signo de f (a) es distinto que el signo de f (b) (condiciones delTeorema de Bolzano). A partir de aquí se repite el siguiente proceso: calcular el puntomedio del intervalo [a,b] y llamarlo c. Si f (c) = 0, entonces hemos encontrado un cero def en c y acabamos. En otro caso determinamos en qué mitad del intervalo [a,b] se produceel cambio de signo ([a,c] o [c,b]) y repetimos el proceso con dicha mitad. Todo esteproceso se repite hasta que se da la condición anterior (f (c) = 0) o hasta que el ancho delintervalo considerado sea menor que Epsilon . Utili zar la función anterior para encontrarun cero de la función coseno en [0, π].

5. Escribir una función Pliega que tiene cuatro parámetros: f , a, b, Inicial . El primerparámetro es una función que toma dos enteros y devuelve un entero. Los otros tresparámetros son valores enteros. El resultado de la función Pliega es de tipo entero y debeser el resultado de calcular la expresión:

Page 91: Curso de Modula-2 (Incompleto).pdf

2 Relación d e Problemas (Tema 7)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

f ( f ( ...f ( f ( f ( Inicial , a), a+1), a+2), ... b-1), b).

Es decir , calculamos primero f con parámetros Inicial y a y obtenemos un resultado.Con este resultado y a+1 volvemos a calcular f. Seguimos así hasta que llegamos a que elsegundo parámetro es b.

Escribir un programa que utili ce la función Pliega para calcular el factorial de unnúmero N leído de teclado y el sumatorio de los primeros N naturales, donde N es unnúmero leído del teclado

6. Realizar un procedimiento Filtra que toma tres parámetros: f , a y b. f es una funciónque toma un entero y devuelve un booleano. a y b son dos valores enteros. Filt ra deberáescribir por pantalla todos los valores enteros x en el intervalo [a..b] para los cuales f(x)sea cierto.

Utili zar el procedimiento Filtra en un programa que escriba los números perfectos ylos números primos menores a un valor Maximo dado por teclado.

7. Escribir una función que calcule el valor de la integral definida

f x dxa

b

( )∫ .

Esta función tomará como parámetros: una función f de dominio y rango LONGREAL,los valores a y b de tipo LONGREAL, y un parámetro Epsilon también LONGREAL.Para ello dividiremos el intervalo [a,b] en intervalos de amplitud menor o igual a Epsilony aproximaremos la integral de cada subintervalo con la fórmula del trapecio:

[ ]f x dxx x

f x f xx

x

( ) ( ) ( )≅−

+∫1 0

20 1

0

1

El valor de f x dxa

b

( )∫ será el sumatorio de las aproximaciones anteriores. Utili zar la

función anterior para calcular la integral definida de la función seno entre 0 y π/2.

Page 92: Curso de Modula-2 (Incompleto).pdf

Tema 9. Almacenamiento externo d e la información 1

Informática. Facultad de Ciencias (Matemáticas)

Departamento de Lenguajes y Ciencias dela Computación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)

http://www.lcc.uma.es/personal/pepeg/mates

Tema 9. Almacenamiento externo d e la información

9.1. Ficheros ................................................................ ................................ .............2

9.1.1 Ficheros en MS-DOS ................................................................ .................... 2

9.2. Tipos de ficheros................................................................ ................................ 3

9.2.1 Clasificación de ficheros según su contenido................................................3

9.2.1.1 Ficheros de texto................................................................ ..................... 3

9.2.1.2 Ficheros binarios................................................................ ..................... 4

9.2.2 Clasificación de ficheros según su acceso.................................................... 4

9.2.2.1 Ficheros secuenciales ................................................................ .............4

9.2.2.2 Ficheros con acceso directo................................................................ ....4

9.3 Gestión de ficheros................................................................ ............................. 4

9.3.1. Manejadores de ficheros ................................................................ ..............4

9.3.2 Apertura y cierre de ficheros ................................................................ .........5

9.3.3 Escritura de ficheros ................................................................ ..................... 6

9.3.4 Lectura de ficheros ................................................................ ....................... 7

9.3.4.1 Lectura de múltiples datos desde teclado................................................8

9.3.4.2 Diferencia entre la lectura de teclado y de fichero ...................................9

9.3.4.3 Detección del fin de fichero ................................................................ ...10

9.3.4.4 Lectura de cadenas de caracteres. RdStr..............................................10

9.3.4.5 Convenios para la escritura en ficheros de texto ...................................11

Bibliografía• Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de

Educación a Distancia.

• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

• Fundamentos de programación. L. Joyanes. McGraw-Hill .

Page 93: Curso de Modula-2 (Incompleto).pdf

2 9.1. Ficheros

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Introdu cc iónEn este tema estudiamos el tipo de dato File de TopSpeed Modula-2 y las operaciones para elmanejo de éste que se encuentran en la biblioteca FIO .

9.1. FicherosEn el tema 1 estudiamos los tipos de memoria existentes en un ordenador: memoria principal(RAM) y memoria masiva (discos, cintas magnéticas,...). Vimos que para que un programa seejecutase era necesario que éste y los datos que manejase estuviesen cargados en memoriaprincipal. También estudiamos las características de ambos tipos de memoria, que podemosresumir en:

• memoria principal: rápida, capacidad limitada y volátil .

• memoria masiva: más lenta, mayor capacidad y no volátil .

Todos los datos que se han manipulado hasta el momento en los algoritmos presentados tienenuna característica común: están almacenados en memoria principal. Al ser la memoria principalvolátil , la consecuencia inmediata es que el contenido de estos datos se pierde al apagar elordenador (e incluso cuando termina el programa que se está ejecutando). Sin embargo, losordenadores suelen utili zarse para almacenar datos que serán recuperados posteriormente. Paraconseguir esto son necesarios mecanismos que permitan:

• copiar el contenido de la información situada en memoria principal sobre la memoriasecundaria (antes de terminar la ejecución del programa)

• recuperar el contenido de información almacenada previamente en memoria secundaria.

Para trabajar con datos almacenados en memoria secundaria es necesario declarar variablesdonde temporalmente se copien éstos durante la ejecución del programa y operacionesadicionales que establecen la conexión entre dichas variables en memoria principal y los datosen memoria secundaria.

En Modula-2 esta conexión se consigue mediante el tipo de datos fichero (File) y susoperaciones asociadas. En TopSpeed Modula-2, el módulo de biblioteca FIO contiene todos losservicios para el tratamiento de ficheros, incluyendo la definición del tipo File, que no es untipo predefinido en Modula-2.

Nota: el modulo FIO es propio de TopSpeed Modula-2 y no es estándar. Otros compiladorespueden no contar con las operaciones que veremos en este tema, aunque poseerán algunassimilares.

En la memoria secundaria la información está organizada en archivos o ficheros. Un fichero sepuede definir como una colección de información o elementos lógicamente relacionados yalmacenados en memoria secundaria. En realidad un fichero es tan solo una colección de bytes,pero éstos pueden estar organizados jerárquicamente en estructuras que facilit an y aumentan laeficiencia de las operaciones sobre el mismo.

9.1.1 Ficheros en MS-DOS

Dentro de un mismo dispositi vo de almacenamiento secundario (disco duro, disquete, cintamagnética, CD-ROM, ...) pueden almacenarse varios ficheros. Cuando queremos acceder a unfichero lo hacemos mediante su nombre. El nombre del fichero es una cadena de caracteresque debe seguir ciertas reglas, las cuales dependen del sistema operativo que utili ce elordenador. En nuestro caso, el sistema operativo MS-DOS exige que el nombre del fichero esté

Page 94: Curso de Modula-2 (Incompleto).pdf

Tema 9. Almacenamiento externo d e la información 3

Informática. Facultad de Ciencias (Matemáticas)

formado por no más de ocho caracteres. El primer carácter deberá ser obligatoriamente unaletra (no podrá ser un número ni un signo). Tampoco podremos utili zar el espacio en blancocomo parte del nombre de un fichero. Adicionalmente podremos añadir no más de tres letras alfichero precedidas del carácter punto. A esto se llama extensión del fichero y se suele usar para,siguiendo cierto convenio, indicar el tipo de datos almacenado en el fichero. Por último, hemosde comentar que MS-DOS no distingue entre letras mayúsculas y minúsculas en el nombre deun fichero. Así, los nombres de fichero “ Datos” , “ DATOS” y “ datos” se refieren todos a unmismo fichero.

Algunos ejemplos de nombres de fichero son:

• “Datos” : nombre de fichero de cinco letras sin extensión

• “Programa.mod” : nombre de fichero con ocho letras y extensión de tres letras. Laextensión “mod” se suele usar para ficheros cuyo contenido es el texto de un programaescrito en el lenguaje Modula-2.

• “Programa.exe” : nombre de fichero con ocho letras y extensión de tres letras. Laextensión “exe” se suele utili zar para ficheros cuyo contenido es un programaejecutable, resultado de compilar un programa.

9.2. Tipos de ficherosSimpli ficando mucho, un fichero es tan solo una secuencia de bytes que contienen ciertainformación. Consideramos a continuación un par de criterios para clasificar ficheros: sucontenido y el modo en que se puede acceder a la información que contienen.

9.2.1 Clasificac ión d e ficheros según su contenido

Uno de los criterios que podemos seguir para clasificar ficheros es el tipo de información quealmacenan. De este modo podemos distinguir entre ficheros de texto y binarios.

9.2.1.1 Ficheros de texto

El contenido del fichero es una secuencia de caracteres pertenecientes a un determinado códigode entrada/salida, normalmente el código ASCII. Suelen estar compuestos por una serie delíneas.

Un ejemplo típico de fichero de texto es aquel que almacena el texto correspondiente a unprograma escrito en Modula-2. Las líneas del fichero corresponden a las distintas líneas delprograma que contiene.

Cuando desde un programa escrito en Modula-2 se almacena el contenido de un valor cadenade caracteres en un fichero de texto, sólo es necesario copiar los caracteres desde memoriainterna al fichero correspondiente. Algo similar sucede para operaciones de lectura.

Sin embargo, se necesita más trabajo cuando se pretenden escribir valores de otros tipos(INTEGER, CARDINAL, REAL, ...). En este caso hay que realizar una conversión de larepresentación interna en memoria del valor (una serie de bytes que representan el número enbinario como puede ser 00011001) a la correspondiente secuencia de caracteres que lorepresentan externamente (en este caso podría ser “ 25” ). En las operaciones de lectura serealiza la conversión inversa. Los subprogramas en la biblioteca FIO se encargan de esta tarea.

La principal ventaja que presenta este tipo de ficheros es que una persona puede entenderdirectamente su contenido si lo inspecciona.

Nota: la conversión también ocurre en las lecturas/escrituras en dispositi vos estándares(teclado/pantalla).

Page 95: Curso de Modula-2 (Incompleto).pdf

4 9.3 Gestión d e ficheros

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

9.2.1.2 Ficheros binarios

En lugar de realizar las conversiones anteriormente comentadas para almacenar caracteres en unfichero, las propias representaciones internas de los datos pueden copiarse en un ficherodirectamente. Un fichero creado de esta forma se denomina binario.

La principal ventaja de este tipo de ficheros es que las operaciones con ellos son más rápidas(no es necesario realizar la transformación desde la representación interna de memoria a lacadena de texto correspondiente). La principal desventaja es que su contenido no puede serentendido directamente por una persona al inspeccionarlo.

Modula-2 también provee operaciones en el modulo de biblioteca FIO para el manejo de estetipo de ficheros, aunque no las estudiaremos en este curso.

9.2.2 Clasificac ión d e ficheros según su acces o

Si atendemos al modo en que se puede acceder a la información almacenada en el ficheropodemos clasificar éstos como: ficheros secuenciales y ficheros con acceso directo.

9.2.2.1 Ficheros sec uenciales

Un fichero secuencial es aquel en el cual para acceder al elemento del contenido que ocupa laposición i-ésima hay que acceder previamente a los i-1 elementos previos.

9.2.2.2 Ficheros con acces o d irecto

Un fichero con acceso directo es aquel que permite acceder al elemento que ocupa la posición i-ésima directamente (al estilo del acceso en un ARRAY) sin pasar necesariamente por loselementos previos.

La biblioteca FIO de TopSpeed Modula-2 posee operaciones para el manejo de ficherossecuenciales y con acceso directo, aunque en este curso sólo estudiaremos las primeras.

9.3 Gestión d e ficherosLos ficheros se suelen utili zar de tres modos:

• para escribir datos en ellos

• para leer datos contenidos en ellos

• para modificar o almacenar información adicional a la que ya contenían

A la hora de utili zar un fichero debemos indicar de qué modo vamos a utili zarlo. Veremos enlos puntos siguientes como hacerlo.

La gestión básica de ficheros en TopSpeed Modula-2 se realiza a través de la biblioteca FIO.Para utili zar los servicios ofrecidos por esta biblioteca, es necesario importar dicho módulo.

9.3.1. Manejadores de ficheros

Hemos visto que un fichero se identifica mediante su nombre y que antes de utili zarlo hay queindicar de qué modo va a ser utili zado (para lectura, escritura o ambas). En Modula-2, parautili zar un fichero hay que abrirlo previamente mediante una de las siguientes operaciones:Open, OpenRead, Create o Append . Al utili zar las operaciones anteriores se especifica elnombre del fichero que se va a utili zar. Estas operaciones devuelven un valor de tipo File , quees conocido como manejador de fichero. Posteriormente cuando queramos leer o escribirinformación en el fichero NO utili zaremos el nombre de éste, sino el manejador que obtuvimos

Page 96: Curso de Modula-2 (Incompleto).pdf

Tema 9. Almacenamiento externo d e la información 5

Informática. Facultad de Ciencias (Matemáticas)

al abrirlo. Cada fichero abierto tiene un manejador de fichero diferente. Cuando hayamosterminado de trabajar con el fichero debemos cerrarlo mediante la operación Close .

Asociada a cada fichero abierto existe una cabeza de lectura/escritura. Ésta indica laposición dentro del fichero de donde se leerá (o en donde se escribirá) información la próximavez que se ejecute una operación de lectura (o escritura). En el apartado siguiente veremos que,dependiendo de la operación de apertura utili zada, la cabeza se colocará inicialmente alprincipio o al final del fichero. También veremos que las operaciones de lectura y escrituraavanzan automáticamente esta cabeza cada vez que se ejecutan.

9.3.2 Apertura y cierre de ficheros

Para la apertura de un fichero existen diversas posibili dades. Hay cuatro formas de apertura.

• Creación de un nuevo fichero: en este caso usaremos la función Create :

PROCEDURE Create(Nombre: ARRAY OF CHAR): File;

El parámetro de esta función es el nombre del fichero que se desea crear.

• Si el fichero no existe, se crea uno nuevo vacío. Después de esta operación el ficheroqueda abierto, li sto para ser usado por el programa.

• Si el fichero indicado ya existe, su contenido se borra y se abre como si se hubiesecreado uno nuevo.

El valor devuelto por dicha función es el manejador asociado a dicho fichero. Estemanejador sirve para poder referenciar al fichero que se acaba de crear. La cabeza delectura/escritura se sitúa al principio del fichero.

• Apertura de un fichero ya existente para lectura o escritura. En este caso usamos lafunción Open:

PROCEDURE Open(Nombre: ARRAY OF CHAR): File;

• Si el fichero ya existe, abre el fichero especificado para lectura o escritura, einicializa la cabeza de lectura/escritura al principio del mismo.

• Si el fichero no existe se produce un error en tiempo de ejecución.

• Apertura de un fichero ya existente sólo para lectura. En este caso se usa la funciónOpenRead:

PROCEDURE OpenRead(Nombre: ARRAY OF CHAR): File;

En este caso, sólo podemos realizar operaciones que lean datos del fichero. Si usamosoperaciones que intenten modificar el contenido de éste se produce un error en tiempode ejecución.

• Apertura de un fichero ya existente para añadir datos al final. En este caso usamos lafunción Append :

PROCEDURE Append(Nombre: ARRAY OF CHAR): File;

• Si el fichero ya existe, Append abre el fichero especificado para lectura o escritura, einicializa la cabeza de lectura/escritura al final del mismo. Por lo tanto, se utili zacuando se quiere añadir datos detrás de los ya existentes.

• Si el fichero no existe se produce un error en tiempo de ejecución.

Siempre hay que cerrar un fichero cuando se termina de trabajar con él. El procedimientoClose se utili za para ello.

PROCEDURE Close(Fich: File);

Page 97: Curso de Modula-2 (Incompleto).pdf

6 9.3 Gestión d e ficheros

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Este procedimiento toma como parámetro el manejador del fichero abierto que queremos cerrar.

Si hemos de determinar si un fichero existe o no antes de elegir la operación con la cual abrirlo,podemos utili zar la función Exists :

PROCEDURE Exists(Nombre: ARRAY OF CHAR): BOOLEAN;

Esta función toma como parámetro el nombre de un fichero y devolverá TRUE si el fichero yaexiste, o FALSE en caso contrario.

Veamos un ejemplo de uso de las operaciones anteriores. Se trata de un programa para añadirnueva información al final del fichero “Datos.txt” . Previamente comprobamos si el ficheroexiste (en cuyo caso lo abrimos con Append ) o no (en este caso se crea con Create ). Una vezañadida la información al fichero, se cierra:

MODULE Fichero;FROM FIO IMPORT File, Create, Append, Exists, Close;CONST NOMBREFICHERO = “Datos.txt”;

VARManejador : File;

BEGINIF Exists(NOMBREFICHERO) THEN

Manejado r := Append(NOMBREFICHERO)ELSE

Manejador := Create(NOMBREFICHERO)END;...

(* Operaciones de escritura *)...Close(Manejador)

END Fichero.

9.3.3 Escritura de ficheros

Las operaciones de escritura en ficheros son similares a las de escritura por pantalla, perotoman un parámetro adicional que es el manejador del fichero en el cual queremos escribir eldato. Algunas de estas operaciones son:

PROCEDURE WrChar(Fich:File, V: CHAR);

PROCEDURE WrInt(Fich:File, V: INTEGER, Long: INTEGER);

PROCEDURE WrLngInt(Fich:File, V: LONGINT, Long: INTEGER);

PROCEDURE WrCard(Fich:File, V: CARDINAL, Long: INTEGER);

PROCEDURE WrLngCard(Fich:File, V: LONGCARD, Long: INTEGER);

PROCEDURE WrReal(Fich:File, V: REAL, Pre: CARDINAL, Lon: INTEGER);

PROCEDURE WrLngReal(Fich:File, V: LONGREAL, Pre: CARDINAL,Lon: INTEGER);

PROCEDURE WrFixReal(Fich:File, V: REAL, Pre: CARDINAL, Lon: INTEGER);

PROCEDURE WrFixLngReal(Fich:File, V: LONGREAL, Pre: CARDINAL,Lon: INTEGER);

PROCEDURE WrStr(Fich: File, V: ARRAY OF CHAR);

PROCEDURE WrLn(Fich: File);

Estos procedimientos escriben los datos que toman como parámetros en el fichero indicado apartir de la posición actual de la cabeza de lectura/escritura. La posición de la cabeza seincrementa automáticamente para que apunte a la siguiente posición a los caracteres escritos.

Page 98: Curso de Modula-2 (Incompleto).pdf

Tema 9. Almacenamiento externo d e la información 7

Informática. Facultad de Ciencias (Matemáticas)

Veamos un ejemplo. Supongamos que hemos abierto un fichero con la operación Create . Estaoperación deja la cabeza al principio del fichero por lo que tenemos la siguiente situación:

Si a continuación utili zamos la operación de escritura de enteros en ficherosWrInt(Manejador,123,0) la situación del fichero pasa a ser:

‘1’ ‘2’ ‘3’

El procedimiento WrLn escribe una indicación de fin de línea en el fichero. Esta indicaciónconsiste en escribir los caracteres CHR(13) y CHR(10) en el fichero en este orden exactamente.Si ll amamos a WrLn(Manejador) el estado del fichero queda:

‘1’ ‘2’ ‘3’ CHR(13) CHR(10)

Los procedimientos WrFixReal y WrFixLngReal se usan para escribir valores reales ennotación fija (no científica).

Obsérvese que el nombre de los procedimientos coincide con el nombre de los procedimientosde salida por pantalla del módulo IO. Si nos interesa utili zar un procedimiento del módulo IO yotro de FIO con el mismo nombre en un mismo programa, podemos utili zar la importación demódulos completos y referirnos a la operación concreta precediéndola del nombre de labiblioteca y un punto:

MODULE Importar;IMPORT IO, FIO;...BEGIN

...(* Escribe por pantalla *)IO.WrStr(“A pantalla”);...(* Escrib e en un fichero *)FIO.WrStr(Manejador, “A fichero”);...

END Importar.

Nota Importante: La lectura de los datos almacenados en el fichero debe respetar una serie deconvenios, por lo tanto, dichos datos se deben escribir (tanto con un programa en Modula-2como de cualquier otra forma, por ejemplo con un editor) teniendo en cuenta que dichos datosserán posteriormente leídos. Estos convenios tienen que ver con el funcionamiento de lasfunciones de lectura/escritura de Modula-2.

9.3.4 Lectura de ficheros

El módulo FIO también contiene operaciones que permiten leer datos desde un fichero. Algunasde éstas son:

PROCEDURE RdChar(Fich:File): CHAR;

PROCEDURE RdInt(Fich:File): INTEGER;

PROCEDURE RdLngInt(Fich:File): LONGINT;

PROCEDURE RdCard(Fich:File): CARDINAL;

PROCEDURE RdLngCard(Fich:File): LONGCARD;

PROCEDURE RdReal(Fich:File): REAL;

PROCEDURE RdLngReal(Fich:File): LONGREAL;

PROCEDURE RdStr(Fich: File, VAR V: ARRAY OF CHAR);

Page 99: Curso de Modula-2 (Incompleto).pdf

8 9.3 Gestión d e ficheros

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Estos subprogramas se comportan de forma parecida a sus homólogos del módulo IO, salvo quelos caracteres se toman del fichero especificado como primer parámetro, a partir de la posiciónindicada por la posición de lectura/escritura. Tras la lectura, dicha posición se incrementa paraque apunte a la siguiente posición a los caracteres leídos.

El procedimiento RdStr se comporta de forma diferente al homólogo de IO, por lo que loestudiaremos con más detenimiento.

9.3.4.1 Lectura de múltiples datos desde teclado

Hasta ahora hemos usado siempre la instrucción RdLn tras cualquier operación de entrada desdeteclado. Vamos a explicar en este punto porqué ha sido esto necesario y cómo funciona lalectura desde teclado más detalladamente.

Sabemos que cuando un programa escrito en Modula-2 llega a una operación de entrada desdeteclado se detiene, muestra un cursor parpadeante y espera a que el usuario introduzca un dato.El programa no reanuda su ejecución hasta que el usuario pulsa la tecla especial <ENTER>.Los datos tecleados por el usuario se almacenan en una zona llamada buffer del teclado. Lapulsación de la tecla <ENTER> hace que se almacenen los caracteres CHR(13) y CHR(10) alfinal del buffer del teclado. Ahora bien, nada impide que el usuario teclee más de un datocuando aparece el cursor parpadeante. Supongamos que un programa ejecuta la instrucciónN:=RdInt() y que el usuario escribe 12, un espacio en blanco, 15 y entonces pulsa <ENTER>.El contenido del buffer del teclado queda como se indica:

‘1’ ‘2’ ‘b’ ‘1’ ‘5’ CHR(13) CHR(10)

Como RdInt lee del teclado hasta encontrar un carácter que no forme parte de un número, Ntoma el valor 12 y la cabeza de lectura/escritura queda en el espacio en blanco (la lectura desdeteclado no salta el separador final):

‘1’ ‘2’ ‘b’ ‘1’ ‘5’ CHR(13) CHR(10)

El resto de la información queda almacenada en el buffer del teclado, de modo que si elprograma ejecuta otra operación M:=RdInt() no llega a detenerse ya que hay informaciónsuficiente en el buffer. En este caso M tomaría el valor 15 y el buffer del teclado quedaría:

‘1’ ‘2’ ‘b’ ‘1’ ‘5’ CHR(13) CHR(10)

La ejecución de un programa no se detiene en una operación de lectura desde teclado hasta quese agota el contenido del buffer. En ese momento el programa se detendrá a la espera de que elusuario introduzca más datos.

Lo único que hace la operación de lectura RdLn es vaciar el buffer del teclado. Si ll amamos aRdLn tras cualquier operación de lectura desde teclado, borramos cualquier información extraque el usuario haya podido introducir.

A veces puede ser interesante no llamar a RdLn tras una operación de entrada. El siguienteprograma pide al usuario que introduzca diez números de una vez y los lee en un ARRAY:

MODULE SinRdLn;FROM IO IMPORT RdInt, RdLn, WrStr;CONST

MAXIMO = 10;VAR

Vector : ARRAY [1.. MAXIMO] OF INTEGER;i : CARDINAL;

BEGINWrStr(“Dame 10 nºs separados por espacio y pulsa ENTER: ”);FOR i := 1 TO MAXIMO DO

Vector[i] := RdInt()

Page 100: Curso de Modula-2 (Incompleto).pdf

Tema 9. Almacenamiento externo d e la información 9

Informática. Facultad de Ciencias (Matemáticas)

END;RdLn...

END SinRdLn.

9.3.4.2 Diferencia entre la lectura de teclado y de fichero

Supongamos que el buffer de teclado contiene la siguiente información (el próximo carácter aleer es el enmarcado en trazo doble).

‘b’ ‘b’ ‘1’ ‘2’ ‘3’ ‘b’ ‘A’ ...

Después de realizar la operación N:=RdInt() , N valdrá 123 y el buffer queda como sigue:

‘b’ ‘b’ ‘1’ ‘2’ ‘3’ ‘b’ ‘A’ ...

si ahora realizamos la operación C:=RdChar() , C contiene el carácter blanco ‘ b’ .

Veamos ahora lo que sucede en el caso de lectura de ficheros (la posición de lectura/escritura semuestra en trazo doble):

‘b’ ‘b’ ‘1’ ‘2’ ‘3’ ‘b’ ‘A’ ...

Después de realizar la operación N:=RdInt(Manejador) , N también vale 123 pero la posiciónde lectura/escritura queda como sigue:

‘b’ ‘b’ ‘1’ ‘2’ ‘3’ ‘b’ ‘A’ ...

con lo que si realizamos la operación C:=RdChar(Manejador) C contendrá el carácter ‘A’ .

La diferencia fundamental entre la lectura desde el teclado y la lectura desde fichero es que lasoperaciones de lectura desde teclado no saltan el separador (en este caso el blanco) que originael fin del número, mientras que las operaciones de lectura desde fichero sí lo hacen (avanzanuna posición más).

Nótese que las funciones para leer enteros, cardinales y reales saltan los separadores (‘ b’ ,CHR(9) , CHR(10) , CHR(13) , CHR(26) ) que se encuentran antes de los datos a leer. En lasbibliotecas IO y FIO se encuentra una variable de tipo SET OF CHAR que contiene los valoresque se consideran separadores. Esta variable es Separators y se puede modificar utili zandolos procedimientos INCL y EXCL.

Si el dato introducido por el usuario no representa un número válido del tipo que se intenta leerel valor devuelto por las funciones de lectura es indefinido. Se puede importar la variablebooleana OK del módulo IO (o de FIO si estamos leyendo desde ficheros) que se pone a FALSEsi el dato introducido por el usuario no fue válido. El siguiente programa pide un dato de tipoCARDINAL por teclado y no cesa hasta conseguirlo:

MODULE Leer;IMPORT IO;VAR c : CARDINAL;BEGIN LOOP IO.WrStr("Dame un valor CARDINAL: "); c := IO.RdCard(); IF IO.OK THEN EXIT END; IO.WrStr("Valor no válido. Prueba de nuevo"); IO.WrLn END; IO.WrStr("El valor leído es: "); IO.WrCard(c, 0)

Page 101: Curso de Modula-2 (Incompleto).pdf

10 9.3 Gestión d e ficheros

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

END Leer.

9.3.4.3 Detecc ión d el fin de fichero

Para controlar correctamente la lectura de datos de un fichero, necesitamos algún mecanismopara saber si existen más datos en éste o no, es decir, si la posición de lectura/escritura seencuentra al final del fichero.

Para ello se utili za la variable booleana EOF (siglas de End Of File) que se importa del móduloFIO. Su utili zación es similar a la de la variable OK ya vista. Si la variable EOF es TRUE,indica que en la última operación de lectura de fichero que se intentó, la cabeza delectura/escritura ya estaba sobre el final del fichero. Obsérvese que HAY QUE INTENTARLEER ALGO Y LUEGO COMPROBAR SI LO LEÍDO ES VÁLIDO en este ordenexactamente.

Veamos un programa que muestra el contenido de un fichero de texto por pantalla:

MODULE Fichero;IMPORT IO, FIO;CONST

MAX = 20;TYPE

Nombre = ARRAY [1..MAX] OF CHAR;VAR

C : CHAR;Fich : Nombre;Manejador : FIO.File;

BEGIN IO.WrStr("Introduce el nombre del fichero: "); IO.RdStr(Fich); Manejador := FIO.Open(Fich); (* Apertura de fichero *)

LOOP C := FIO.RdChar(Manejador); (* Lectura de datos *)

IF FIO.EOF THEN (* Fin de fichero ? *)EXIT

END; IO.WrChar(C); (* Escribir en pantalla *)

END; FIO.Close(Manejador);END Fichero.

9.3.4.4 Lectura de cadenas de caracteres. RdStr

El comportamiento del procedimiento RdStr del módulo FIO es diferente a su homólogo delmódulo IO. Su comportamiento es como se indica a continuación:

Se leen caracteres del fichero especificado hasta que:

1) Se encuentra los caracteres correspondientes a un fin de línea (CHR(13) y CHR(10) ).Estos caracteres, sin embargo, no se almacenan en la cadena leída. Se coloca en su lugarun carácter CHR(0) .

2) Se encuentra el fin de fichero. En este caso también se añade un carácter CHR(0) al finalde la cadena.

3) Se llena la cadena argumento.

Algunas consideraciones sobre esta operación son:

• Si los primeros caracteres leídos son CHR(13) y CHR(10) , la cadena contiene la cadenavacía (una cadena con el carácter CHR(0) en su primera posición).

Page 102: Curso de Modula-2 (Incompleto).pdf

Tema 9. Almacenamiento externo d e la información 11

Informática. Facultad de Ciencias (Matemáticas)

• Si la llamada a RdStr es seguida por una llamada a RdChar , ésta lee el primer carácterdel fichero que no leyó RdStr . Este carácter dependerá de la causa que motivó el fin dela operación RdStr . Para cada uno de los casos anteriores tenemos:

1) Se leerá el primer carácter de la siguiente línea. Nótese que los caracteres de fin delínea son saltados.

2) Se producirá fin de fichero.

3) Se leerá el siguiente carácter a los que se leyeron.

9.3.4.5 Convenios para la escritura en ficheros de texto

Las funciones para leer enteros, cardinales y reales desde un fichero leen hasta encontrarse uncarácter que no corresponda a un número de dicho tipo. Este carácter (que llamaremosseparador) es leído también. Como consecuencia de esto, resulta que es necesario escribir algúncarácter especial (como puede ser un espacio en blanco) siempre que escribamos un datonumérico en un fichero y queramos que éste pueda ser leído posteriormente. Si no seguimoseste convenio no podremos recuperar la información almacenada posteriormente con éxito. Enefecto, supongamos que NO lo hacemos y que escribimos dos enteros (10 y 25) en un fichero:

...Manejador := FIO.Open(Fich);FIO.WrInt(Manejador, 10, 0);FIO.WrInt(Manejador, 25, 0);...

el contenido del fichero sería:

‘1’ ‘0’ ‘2’ ‘5’ ‘b’ ...

Por lo cual, si posteriormente abrimos el fichero para lectura e intentamos leer un númeroobtendremos 1025. Sin embargo, si seguimos el convenio indicado:

...Manejador := FIO.Open(Fich);FIO.WrInt(Manejador, 10, 0);FIO.WrChar(Manejador, ‘ ‘);FIO.WrInt(Manejador, 25, 0);FIO.WrChar(Manejador, ‘ ‘);...

el contenido del fichero es ahora

‘1’ ‘0’ ‘b’ ‘2’ ‘5’ ‘b’ ‘b’ ...

y los dos enteros almacenados pueden ser leídos con éxito:

...Manejador := FIO.OpenRead(Fich);a := FIO.RdInt(Manejador);

b := FIO.RdInt(Manejador);...

Por otro lado, la función de lectura de cadenas de caracteres RdStr lee hasta fin de línea, por lotanto se debe escribir el fin de línea después de escribir en el fichero una cadena de caracteres,si queremos que sea posible leerla posteriormente con RdStr :

...Manejador := FIO.Open(Fich);FIO.WrStr(Manejador, “Hola”);FIO.WrLn(Manejador);...

Page 103: Curso de Modula-2 (Incompleto).pdf
Page 104: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 9) 1

Informática. Facultad de Ciencias (Matemáticas)

Relación d e problemas (Tema 9)1. Escribe un programa que lea del teclado el nombre de tres ficheros y escriba en el tercero

el contenido del primero seguido del contenido del segundo.

2. Escribe un programa que codifique y decodifique ficheros de texto usando el método decifrado César. Para codificar un fichero de texto (cuyo nombre y extensión se leerá deteclado) se generará otro fichero de texto con el mismo nombre y con extensión “.COD” .La codificación consistirá en reemplazar cada carácter del fichero original por el tercerosiguiente según la tabla ASCII (Por ejemplo, el carácter ‘a’ será sustituido por el carácter‘d’ ). Si el carácter a codificar es CHR(10) o CHR(13) no se cambiará al codificarlo. Laopción de decodificación deberá leer de teclado el nombre de un fichero codificado yrecuperar en otro fichero con mismo nombre y con extensión “.DEC” la informaciónoriginal.

NOTA: El desplazamiento en tres caracteres debe ser circular tanto en un sentido como enotro. Por ejemplo, el último carácter de la tabla ASCII (CHR(255) ) es codificado comoCHR(2) .

3. Diseña un programa que cree un fichero que contenga los datos relativos a los artículos deun almacén. Para cada artículo hay que guardar la siguiente información:

Código del artículo (Numérico)

Nombre del artículo (Cadena de caracteres)

Existencias actuales (Numérico)

Precio (Numérico).

Los datos de los distintos artículos se pedirán del teclado y se almacenarán previamenteen un array. Supondremos que el número máximo de artículos que se pueden introducir estreinta. Una vez leídos, los datos se ordenarán en el array (el orden será ascendente segúnel código del artículo) y se grabarán en el fichero.

4. Escribe un programa que a partir de dos ficheros generados por el programa anterior(recordar que los artículos están ordenados por código) genere un tercer fichero que sea elresultado de mezclar de formar ordenada los dos primeros. Escribe otro programa quehaga lo mismo pero con n ficheros (n será un número positi vo leído de teclado).

5. Escribe un programa que tome como entrada un fichero generado por el programa delejercicio 3 y una condición sobre el campo referente a las existencias actuales. Lacondición podrá ser:

[<,<=,>,>=, <>, =] <número>

Es decir, que las referencias actuales sean menores a un número dado, o menores oiguales, o mayores, etc.

El programa debe generar como salida un fichero llamado "salida.dat" que contengatodos aquellos artículos para los que se cumple la condición de entrada.

6. Escribe un programa que tenga como entrada el nombre de un fichero que contenga untexto y muestre en pantalla una estadística de la longitud de las distintas palabras quecontiene (número de palabras de cada longitud), así como cuántas veces aparecen loscaracteres separadores ("," , "." , ":" , ";" , " b" ).

7. Escribe un programa que a partir de un fichero de entrada que contiene números enterospositi vos expresados en cualquier base entre 2 y 10, genere un li stado por pantalla y unfichero de salida que contenga las mismas cantidades del fichero de entrada, pero

Page 105: Curso de Modula-2 (Incompleto).pdf

2 Relación d e Problemas (Tema 9)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

expresadas en base 10.

El fichero de entrada contendrá en cada línea la base y el número separados por el carácter‘ /’ .

Ejemplo:

Fichero de Entrada:

2/101

5/412

9/111

10/923

Salida por pantalla: Se deberá generar un li stado por pantalla con las siguientes líneas:

Número de entrada 2/101 Resultado 5

Número de entrada 5/412 Resultado 107

Número de entrada 9/111 Resultado 91

Número de entrada 10/923 Resultado 923

El contenido del fichero de salida será:

5 107 91 923

8. Escribe un programa que busque en un archivo de texto, que contiene números enterosseparados por un espacio, los valores máximo y mínimo y los muestre por pantalla.

9. Escribe un programa que calcule el número de líneas que han de leerse de un archivo detexto hasta que se hayan leído del fichero todas las letras minúsculas del alfabeto al menosuna vez. El programa debe mostrar también el número total de caracteres leídos hasta esemomento. Si se alcanza el final del fichero y no se consigue el objetivo, el programamostrará un mensaje por pantalla que lo indique.

10. Escribe un programa que a partir de un fichero de texto, cree otro que sólo contengaaquellas líneas del primero en las que figure una palabra introducida previamente por elusuario desde el teclado.

NOTA: Suponer que la longitud máxima de una línea del fichero es 128 caracteres, quelas palabras están separadas por espacios en blanco o saltos de línea y que los únicoscaracteres que aparecen en el texto son letras, espacios en blanco y los caracteres queforman el salto de línea.

Page 106: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 9) 3

Informática. Facultad de Ciencias (Matemáticas)

Relación complementaria (Tema 9)11. Escribe un programa que mezcle dos archivos de texto, que contengan números enteros

separados por espacios, y que estén ordenados ascendentemente. El fichero resultantedeberá estar también ordenado en orden ascendente.

12. Escribe un programa que a partir de los nombres de dos ficheros de texto que contienenvalores cardinales en el rango [1..1000] separados por espacios, genere dos nuevosficheros de texto con la unión e intersección de los dos ficheros anteriores.

13. Se desea escribir un programa que resuelva el juego Sopa de Letras. Para ello, seconsiderarán las siguiente especificaciones:

• La tabla de caracteres que forma la sopa de letras tendrá como dimensiones 15filas por 15 columnas.

• En fichero de entrada "SOPA.DAT" contendrá las distintas líneas que forman latabla.

• En fichero "PATRONES.DAT" contendrá las palabras a buscar dentro de la SOPA.

• Sólo será necesario buscar los patrones dentro de la SOPA por filas y porcolumnas en ambos sentidos (No será necesario buscar en las diagonales).

La salida del programa será un li stado por pantalla mostrando cada palabra encontradajunto con las coordenadas donde fue hallada.

14. Mejora el programa anterior para que busque también en diagonales

15. Se desea ordenar un fichero de números enteros que no cabe en la memoria central delordenador. Se opta por ordenarlo considerándolo como un array en disco. Para ello seránecesario escribir los siguientes subprogramas:

1) PROCEDURE Longitud (NombreFich : NOMBREFICH) : LONGCARD; Devuelvela cantidad de números enteros almacenada en el fichero que toma comoargumento.

2) PROCEDURE LeerFich (NombreFich : NOMBREFICH; Posicion :

LONGCARD) : INTEGER; Devuelve el valor del número que está situado en laposición indicada dentro del fichero.

3) PROCEDURE EscribirFich (NombreFich : NOMBREFICH; Posicion :

LONGCARD; Valor : INTEGER); Modifica el contenido del fichero, de modo queel valor del número que ocupa la posición indicada pasa a ser Valor . El resto delos números en el fichero permanecen iguales.

Utili zando estos subprogramas, diseña el programa que ordene el fichero y muestre elresultado por pantalla.

16. Otra alternativa al procedimiento anterior es dividir el fichero inicial en subficheros decomo máximo 100 bytes. Cada uno de estos ficheros se carga en memoria en un vector detamaño 50, se ordena en el vector y se vuelca en el correspondiente subfichero.Posteriormente se mezclan los subficheros obteniéndose el fichero original ordenado.Escribe un programa para esto.

Nota: Los problemas 14, 15 y 16 presentan un alto nivel de dificultad.

Page 107: Curso de Modula-2 (Incompleto).pdf

Tema 10. Diseño modu lar 1

Informática Facultad de Ciencias (Matemáticas)

Departamento de Lenguajes y Ciencias de laComputación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)

http://www.lcc.uma.es/personal/pepeg/mates

Tema 10. Diseño modu lar

10.1 Los módulos de Modula-2................................................................ .................2

10.2 Ventajas de la modularización de programas.................................................... 2

10.3 Módulos de biblioteca ................................................................ ....................... 3

10.3.1 Módulos de definición ................................................................ .................3

10.3.2 Módulos de implementación................................................................ ........4

10.3.3 Inicialización de un módulo ................................................................ .........6

10.3.4 Usos de los módulos de biblioteca .............................................................. 7

10.4. Compilación separada ................................................................ ..................... 8

Bibliografía• Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de Educación

a Distancia.

• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

Page 108: Curso de Modula-2 (Incompleto).pdf

2 10.1 Los módu los de Modu la-2

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Introdu cc iónEn este tema estudiamos el sistema de módulos del lenguaje Módula-2. Este mecanismo esesencial para poder escribir programas reales (con cierto tamaño). Además, hace posible lacreación de módulos de biblioteca reutili zables.

10.1 Los módu los de Modu la-2En programación, un módulo es un fragmento de un programa que se desarrolla de formaindependiente del resto del programa. Esta independencia hace posible un mecanismo decompilación por separado que limita la complejidad del programa que se está desarrollando. Alcompilarse el módulo por separado, la persona que lo desarrolla sólo debe preocuparse de él,prescindiendo en parte de cómo se utili za este módulo dentro del programa. Quien escriba elresto del programa no debe preocuparse de los detalles del módulo sino sólo de cómo utili zarlo.

Los módulos son, probablemente, la característica más innovadora del lenguaje Modula-2. Haycuatro tipos de módulos:

• módulos de programa

• módulos internos

• módulos de definición

• módulos de implementación

Los módulos de programa son unidades de programa completas que pueden importar recursos(constantes, variables, procedimientos..) de módulos de biblioteca. Son módulos de programatodos los que hemos utili zado hasta el momento.

Los módulos de definición e implementación son las dos partes que constituyen los módulosde biblioteca.

Los módulos internos o locales pueden ser definidos dentro del cuerpo de, bien módulos deprograma, bien módulos de implementación, y se usan para ayudar a controlar el ámbito y lavisibili dad de los distintos objetos.

Un programa en Modula-2 consta de un módulo de programa y cualquier número de módulosde biblioteca, de los que el módulo de programa importa entidades (constantes, tipos, variables,funciones y procedimientos). Estos módulos de biblioteca pueden a su vez importar de otrosmódulos de biblioteca.

Cada sistema Modula-2 suministra un conjunto de bibliotecas básico. El programador tiene,además, la posibili dad de crear módulos de biblioteca adicionales para usar en uno o másprogramas.

Los módulos usan li stas de impor tación para indicar los recursos externos que van a utili zar.

10.2 Ventajas de la modu larización d e programasLos módulos son una herramienta indispensable para crear programas reales cuyo tamaño seagrande. Un programador debe diseñar un programa grande como un conjunto de módulos,relacionados entre sí mediante interfaces definidas apropiadamente. Escribir y depurar elprograma es más fácil porque el programador puede trabajar con un módulo cada vez, usandolos servicios facilit ados por otros módulos pero ignorando los detalles de cómo estos módulostrabajan (principio de abstracción). Este tipo de diseño modular es particularmente

Page 109: Curso de Modula-2 (Incompleto).pdf

Tema 10. Diseño modu lar 3

Informática Facultad de Ciencias (Matemáticas)

necesario cuando el programa se está desarrollando entre un conjunto de programadores, que eslo más habitual en cualquier programa de cierta envergadura.

Los programas modulares son más fáciles de modificar . Puesto que los detalles deimplementación de un módulo se ocultan a los demás, se pueden cambiar detalles de un módulosin afectar al resto.

La modularización hace los programas mas por tables. El programador puede ocultar losdetalles dependientes de la máquina en un único módulo, de forma que cuando se transporte aotro ordenador, sólo debe preocuparse de reescribir dicho módulo.

Cada módulo se compila por separado. El programa se divide en trozos, que el compiladorpuede procesar separadamente. De esta forma, un cambio en un módulo sólo requiere volver acompilar dicho módulo, no el programa completo.

El desarrollo de bibliotecas con código reutili zable conlleva no sólo un ahorro de trabajo, sinoademás un aumento de la fiabili dad del programa, pues dichas bibliotecas están más probadasque si la parte de la biblioteca que se usa se codifica de nuevo.

10.3 Módu los de bibliotecaLos módulos de biblioteca se usan para exportar recursos a otros módulos. El programador queutili za estos módulos sólo necesita conocer cuales son los recursos disponibles pero no cómoestán implementados. Un módulo de biblioteca consta de dos partes, la par te de definición y lapar te de implementación. La parte de definición contiene sólo las definiciones de entidadesque el módulo exporta; define la interfaz del módulo de biblioteca con el resto del programa,informa al programador de los recursos existentes en la biblioteca. La parte de implementacióndescribe cómo implementar los servicios indicados en la parte de definición. Para resaltar quecada parte es por sí sola una unidad de programa, la primera es llamada DEFINITIONMODULE, y la segunda IMPLEMENTATION MODULE. Cada una está contenida en unfichero. En TopSpeed Modula-2, el nombre del fichero que contiene la parte de definición debetener la extensión .DEF, mientras que el fichero que almacena la parte de implementacióndeberá tener la extensión .MOD.

10.3.1 Módu los de definición

Un módulo de definición contiene definiciones de constantes, tipos, variables y subprogramas.Las definiciones son similares a las declaraciones, pero pueden tener menos información.

• Constantes

Son idénticas a las declaraciones de constantes normales.

• Tipos.

Podemos definir tipos de dos formas. Una posibili dad es usar una declaración de tipo normal:

TYPECOMPLEJO = RECORD

PReal, PImag : REAL;END;

En este caso se llama tipo transparente y la estructura del tipo es visible en los módulos que loimporten. Un módulo que importe el tipo COMPLEJO, sabe que el tipo está definido como unregistro con dos campos cuyos nombres son campos PReal y PImag, y puede acceder a éstos.

Otra alternativa consiste en omiti r el signo de igualdad y la especificación del tipo:

TYPE

Page 110: Curso de Modula-2 (Incompleto).pdf

4 10.3 Módu los de biblioteca

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

COMPLEJO;

A un tipo definido de esta forma se le llama tipo opaco. Un módulo que lo importe no conocesu estructura. En este caso, sólo se pueden efectuar operaciones de asignación o decomparación de igualdad y desigualdad sobre variables declaradas de dicho tipo opaco, ademásde las operaciones definidas en el módulo de definición para dicho tipo. La definición completadel tipo opaco debe aparecer en el módulo de implementación y deberá ser un tipo puntero (vertema 12).

• Var iables.

Las definiciones de variables son idénticas a las declaraciones de variables normales:

VAREsCorrecto : BOOLEAN;

• Subprogramas.

La definición de un subprograma consta de la cabecera del mismo. La declaración completadebe aparecer en el módulo de implementación.

Un módulo de definición puede incluir también li stas de importación; sólo debe importaraquellas entidades externas (normalmente tipos) que se usen en el módulo de definición. Es unerror común importar aquí entidades que sólo son necesarias en la parte de implementación.

La forma exacta de escribir un módulo de definición se describe mediantes las siguiente reglasBNF:

Módulo_definición ::= Cabecera_definición {Definición_de_elementos } END Identificador.

Cabecera_definición ::= DEFINITION MODULE Identificador;

{ Lista_importados ; }

[ Lista_exportados ; ]]Definición_de_elementos::= Declaración_de_constantes |

TYPE { Iidentificador [ = Esquema_de_tipo]]; }|Declaración_de_variables | Cabecera_subprograma;

10.3.2 Módu los de implementación

Un módulo de implementación tiene la misma sintaxis que un módulo de programa, salvo quecomienza con las palabras IMPLEMENTATION MODULE , en lugar de MODULE .

Al igual que los módulos de programa, los módulos de implementación pueden contener tantolistas de importación como declaraciones. Mediante li stas de importación un módulo deimplementación debe importar las entidades de otros módulos de biblioteca que utili ce.

Las declaraciones sirven para dos propósitos:

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

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

Cualquier entidad declarada en la parte de definición de un módulo de biblioteca es visible enla parte de implementación.

En TopSpeed Modula-2, las entidades importadas en la parte de definición son visibles en laparte de implementación automáticamente aunque esto no es un estándar del lenguaje Modula-2.

En un módulo de implementación pueden aparecer declaraciones de cinco clases de entidades:

Page 111: Curso de Modula-2 (Incompleto).pdf

Tema 10. Diseño modu lar 5

Informática Facultad de Ciencias (Matemáticas)

• Constantes.

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

• Tipos.

Los tipos definidos en la parte de definición del módulo son visibles automáticamente en laparte de implementación. Si en la parte de definición aparece la especificación del tipo, no tieneque aparecer una declaración del mismo en la parte de implementación, sin embargo, si seomitió dicha especificación (se definió como tipo opaco), debe aparecer una declaracióncompleta en la parte de implementación. Esta declaración debe ser obligatoriamente de tipoPOINTER (que será estudiado en un tema posterior). Pueden aparecer, además, declaracionesde nuevos tipos, en cuyo caso sólo son visibles dentro de la parte de implementación.

Ejemplo. Si el tipo COMPLEJO ha sido definido como opaco en el módulo de definición,habría que declarar:

TYPECOMPLEJO = POINTER TO RECORD

PReal, PImag: REAL END;

• Var iables.

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

• Subprogramas.

La parte de implementación de un módulo debe contener una declaración completa de todos lossubprogramas cuya cabecera aparece en la parte de definición. Hay que respetar estrictamentela forma en que se definió la cabecera del procedimiento en la parte de definición, es decir, hayque declarar los mismos parámetros y tipos para ellos. Además, pueden declararse otrosprocedimientos que serán locales al módulo de implementación.

• Módulos.

Dentro de un módulo de implementación pueden declararse otros módulos. A estos módulos selos llama módulos internos. No los estudiaremos en este curso.

Los módulos de biblioteca pueden tener un cuerpo, cuyas instrucciones se ejecutan al comienzode la ejecución del programa (sobre esta cuestión insisteremos más adelante).Todas lasvariables declaradas en el nivel más externo de un módulo de biblioteca retienen sus valoresdurante todo el tiempo de vida del programa, a diferencia de lo que ocurre con las variablesdeclaradas en un subprograma. Por tanto, sólo es necesario inicializar una vez las variablespertenecientes a un módulo de biblioteca (cuando el programa comienza la ejecución).

En el siguiente ejemplo, se define un módulo de biblioteca con operaciones para ladeterminación de la posición del máximo y el mínimo elemento de un array de números realesde mil elementos.

Page 112: Curso de Modula-2 (Incompleto).pdf

6 10.3 Módu los de biblioteca

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

MaxMin.Def

DEFINITION MODULE MaxMin;TYPE (* Tipo Transparente *)

ARRAYREAL = ARRAY [1..1000] OF REAL;

PROCEDURE MaxPos(A : ARRAYREAL): CARDINAL;PROCEDURE MinPos(A : ARRAYREAL): CARDINAL;

END MaxMin.

MaxMin.Mod

IMPLEMENTATION MODULE MaxMin;

PROCEDURE MaxPos(A : ARRAYREAL): CARDINAL;VAR

Indice : CARDINAL;PosMax : [1..1000];

BEGINPosMax := 1;FOR Indice := 2 TO 1000 DO

IF A[Indice] > A[PosMax] THENPosMax := Indice

ENDEND;RETURN PosMax

END MaxPos;

PROCEDURE MinPos(A : ARRAYREAL): CARDINAL;VAR

Indice : CARDINAL;PosMin : [1..1000];

BEGINPosMin := 1;FOR Indice := 2 TO 1000 DO

IF A[Indice] < A[PosMin] THENPosMin := Indice

ENDEND;RETURN PosMin

END MinPos;

END MaxMin.

10.3.3 Inicialización d e un módu lo

Los módulos de implementación pueden contener código para su inicialización. Este código esejecutado una sola vez, antes de ejecutar el código del módulo cliente (aquel que hace uso deél). En el caso de que varios módulos de biblioteca contengan código para su inicialización,cada bloque de código de inicialización es ejecutado sólo una vez en la secuencia dada por lali sta de importación.

Como ejemplo, consideremos los siguientes módulos de biblioteca y el siguiente módulo deprograma:

DEFINITION MODULE biblioteca1;END biblioteca1.

IMPLEMENTATION MODULE biblioteca1;FROM IO IMPORT WrStr, WrLn;

Page 113: Curso de Modula-2 (Incompleto).pdf

Tema 10. Diseño modu lar 7

Informática Facultad de Ciencias (Matemáticas)

BEGINWrStr(“Den tro de Biblioteca 1”);WrLn;

END biblioteca1.

DEFINITION MODULE biblioteca2;END biblioteca2.

IMPLEMENTATION MODULE biblioteca2;FROM IO IM PORT WrStr, WrLn;

BEGINWrStr(“Dentro de Biblioteca 2”);WrLn;

END biblioteca2.

DEFINITION MODULE biblioteca3;END biblioteca3.

IMPLEMENTATION MODULE biblioteca3;FROM IO IMPORT WrStr, WrLn;

BEGINWrStr(“Dentro de Biblioteca 3”);WrLn;

END biblioteca3.

MODULE principal;FROM IO IMPORT WrLn, WrStr;IMPORT Biblioteca3;IMPORT Biblioteca1;IMPORT Biblioteca2;

BEGINWrLn;WrStr(“Dentro del modulo principal”);

END principal.

La sálida por pantalla que resulta al ejecutar el módulo principal es:

Dentro de Biblioteca 3Dentro de Biblioteca 1Dentro de Biblioteca 2Dentro d el modulo principal.

10.3.4 Usos de los módu los de biblioteca

El concepto de módulo está muy ligado al concepto de abstracción. Un módulo debe definir unelemento abstracto o varios relacionados entre sí. El diseño del módulo debe permiti r su uso demodo que se sepa qué hace cada parte sin que sea necesario saber cómo está implementada.

Se pueden construir módulos de biblioteca con las siguientes finalidades:

1) Agrupar una cierta cantidad de identificadores de constantes relacionadas. Porejemplo podríamos construir un módulo de biblioteca que reuniera las principalesconstantes matemática (π, e,...). En este caso, solo aparecen definiciones en el módulode definción de la biblioteca. El módulo de implementación queda vacío.

2) Agrupar subprogramas relacionados. Por ejemplo la biblioteca MATHLIB agrupa lasfunciones matemáticas de uso más frecuente (seno, coseno, raíz cuadrada...). En estecaso, sólo aparecen definiciones de subprogramas en el módulo de definición. Lascorrespondientes implementaciones aparecen en el módulo de implementación.

3) Definir un tipo abstracto de datos. Se utili za la biblioteca para definir un nuevo tipo ylas operaciones que se pueden realizar con él. Ejemplo: biblioteca FIO. En este caso la

Page 114: Curso de Modula-2 (Incompleto).pdf

8 10.4. Compilación separada

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

interfaz del módulo equivale a la especificación del tipo abstracto de datos, y larealización del módulo establece su representación interna. En el módulo de definiciónaparece la definición de tipo y los subprogramas asociados.

4) Ocultar una única var iable de un tipo abstracto (dato encapsulado). El móduloconstituye una cápsula que protege al dato de manera que sólo se puede acceder a élusando las operaciones de la interfaz. En el módulo de definición sólo aparecendefiniciones de subprogramas. En el módulo de implementación hay una variable global(el dato encapsulado). Los subprogramas acceden al dato encapsulado mediante efectoslaterales. Este es uno de los pocos casos en los que es lícito usar efectos laterales, yaque éstos quedan aislados a los subprogramas del módulo.

El siguiente ejemplo muestra un módulo en el que se define un dato encapsulado:

DEFINITION MODULE Autor;PROCEDURE Leer;PROCEDURE Escribir;

END Autor.

IMPLEMENTATION MODULE Autor;IMPORT IO;VAR autor: ARRAY [0..20 ] OF CHAR;PROCEDURE Leer;BEGIN

IO.RdStr(autor)END Leer;

PROCEDURE Escribir;BEGIN

IO.WrStr(autor)END Escribir;

END Autor.

MODULE Principal;IMPORT Autor;BEGIN

Autor.Leer;Autor.Escribir

END Principal.

10.4. Compilación separadaModula-2 permite compilar módulos de programa y de biblioteca de forma separada. Elcompilador chequea que cada entidad importada de un módulo de biblioteca sea usada de formaconsistente con su definición en el módulo (para ello usa la información contenida en la partede definición del módulo de biblioteca).

Una de las ventajas proporcionadas por la compilación separada es que cuando cambianalgunos de los módulos de un programa, sólo es necesario recompilar los módulos afectados, yno todos los módulos del programa.

Muchos sistemas Modula-2 requieren que se compilen los módulos de definición; sin embargo,en TopSpeed sólo necesitan ser compilados los módulos de implementación y de programa. Lacompilación de cada fichero con extensión .MOD genera un fichero con el mismo nombre yextensión .OBJ. Los ficheros .DEF no producen ficheros .OBJ ya que no son compilados.

Si un programa consta de varios ficheros con extensión .MOD (un módulo de programa y variosmódulos de implementación) se puede seguir cualquier orden a la hora de compilar los ficherossiempre que se respete la siguiente norma:

Page 115: Curso de Modula-2 (Incompleto).pdf

Tema 10. Diseño modu lar 9

Informática Facultad de Ciencias (Matemáticas)

El módulo de definición de una librería debe existir antes de que pueda compilarse sucorrespondiente módulo de implementación o cualquier otro módulo que importe de lalibrería.

Una vez generados todos los ficheros .OBJ, hay que enlazarlos. El proceso de enlazado generaun fichero ejecutable con el nombre del módulo de programa y con extensión .EXE.

Si se modifica uno de los ficheros que forman el programa, no es necesario volver a compilartodos los ficheros de nuevo. Las normas son:

• Si un módulo de programa o un módulo implementación es modificado, sólo él debe serrecompilado. A continuación basta con repetir el proceso de enlazado para obtener unnuevo fichero ejecutable actualizado.

• Si un módulo de definición es modificado, su correspondiente módulo deimplementación y todos los módulos que importen la biblioteca deben serrecompilados. Es necesario también repetir el proceso de enlazado.

En TopSpeed Modula-2 todo este proceso está automatizado mediante la opción Make delmenú. Cuando esta opción es seleccionada, el sistema recompila los módulos necesarios y,además, realiza el proceso de enlazado.

El siguiente ejemplo muestra el proceso de compilación y enlazado para un programa formadopor un módulo de programa (Programa.Mod) y un módulo de biblioteca (Bib.Mod y Bib.Def):

MODULE Programa;

IMPORT Bib;...

END Programa.

IMPLEMENTATION MODULE Bib;

...

END Bib.

DEFINITION MODULE Bib;

...

END Bib.

Program.Mod Bib.Mod Bib.Def

COMPILACIÓN COMPILACIÓN

Programa.Obj Bib.Obj

ENLAZADO

Programa.Exe

Page 116: Curso de Modula-2 (Incompleto).pdf

10 10.4. Compilación separada

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Page 117: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 10) 1

Informática Facultad de Ciencias (Matemáticas)

Relación d e Problemas (Tema 10)1. Escribe una biblioteca MatConst que exporte las siguientes constantes matemáticas:

PI : relación entre el radio y la circunferencia de un círculo.

E: el valor de la función exponencial en el punto 1.0.

LN10: valor de la función logaritmo neperiano en el punto 10.

2. Diseña una biblioteca que exporte el tipo de dato COMPLEJO y operaciones para construir,sumar, restar, multipli car, dividir, leer de teclado y escribir por pantalla de valores de dichotipo. El módulo de definición será el siguiente:

DEFINITION MODULE Complejo;

TYPECOMPLEJO = RECORD

PReal : LONGREAL;PImag : LONGREAL

END;PROCEDURE RdComplejo () : COMPLEJO;PROCEDURE WrComplejo (C : COMPLEJO);PROCEDURE AsignaRectangular (Real, Imag: LONGREAL) : COMPLEJO;PROCEDURE AsignaPolar (Modulo, Argumento: LONGREAL) : COMPLEJO;PROCEDURE Suma (C1, C2 : COMPLEJO) : COMPLEJO;PROCEDURE Resta (C1, C2 : COMPLEJO) : COMPLEJO;PROCEDURE Producto (C1, C2 : COMPLEJO) : COMPLEJO;PROCEDURE Division (C1, C2 : COMPLEJO ) : COMPLEJO;PROCEDURE SonIguales (C1, C2 : COMPLEJO) : BOOLEAN;

END Complejo.

La función AsignaRectangular toma dos números reales, correspondientes a la parte reale imaginaria de un número complejo, y devuelve un número complejo con dichascomponentes. La función AsignaPolar es similar, pero construye el número a partir de sumódulo y argumento. La función SonIguales devuelve TRUE si sus dos argumentoscorresponden al mismo valor complejo.

Prueba la biblioteca construida con el siguiente programa:

MODULE Ej1002;IMPORT Complejo;FROM MatConst IMPORT PI;FROM IO IMPORT WrLn;VAR

a, b, c, Suma, Resta, Producto, Division : Complejo.COMPLEJO;

BEGINa := Complejo.AsignaRectangular(4.0, 5.0);b := Complejo.AsignaPolar(1.0, PI);c := Complejo.RdComplejo() ;Complejo.WrComplejo(a); WrLn;Complejo.WrComplejo(b); WrLn;Complejo.WrComplejo(c); WrLn;Suma := Complejo.Suma(a, c);Resta := Complejo.Resta(a, c);Producto := Complejo.Producto(a, b);Division := Complejo.Division(c, b);Complejo.WrCompl ejo(Suma); WrLn;Complejo.WrComplejo(Resta); WrLn;Complejo.WrComplejo(Producto); WrLn;

Page 118: Curso de Modula-2 (Incompleto).pdf

2 Relación d e Problemas (Tema 10)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Complejo.WrComplejo(Division)END Ej1002.

3. Se desea escribir una función que devuelva un número real aleatorio entre 0 y 1 cada vezque se llame.

Aunque no es fácil generar mediante un programa de ordenador números realmentealeatorios, existen técnicas para la generación de números pseudo-aleatorios. Una de estastécnicas consiste en utili zar los valores obtenidos al ejecutar repetidamente la sentencia:

Semill a := (a * Semill a + c) MOD m;

Donde a, c y m son valores enteros. No es fácil escoger valores apropiados para a, c y m,pero se puede demostrar que si el valor inicial de Semilla es menor que m y se cumplenlas siguientes igualdades:

ym

xc

ca

2

12

14

=

+=

+=

donde x e y son cualquier valor entero, los valores asignados a Semilla comienzan arepetirse cícli camente tras m valores y todos los valores en el rango [0..m-1] aparecenexactamente una vez en cada ciclo.

Por ejemplo, si escogemos y = 11 y x = 3, tenemos que m = 2048, c = 7 y a = 29. Al repetirla sentencia

Semill a := (29 * Semill a + 7) MOD 2048

cada uno de los valores asignados a Semilla será un número pseudo-aleatorio en el rango[0..2047]. Para obtener números aleatorios entre 0 y 1 basta con dividir los sucesivosvalores de Semilla por 2047.

Escribir un módulo de biblioteca para la generación de números pseudo aleatorios según elsiguiente módulo de definición y utili zando el método explicado:

DEFINITION MODULE NumAleat;

PROCEDURE EstablecerSemilla (NuevaSemilla : CARDINAL);PROCEDURE NumeroAleatorio () : REAL;

END NumAleat.

La función NumeroAleatorio devuelve un número real entre 0 y 1 cada vez que se llama.En el módulo de implementación se definirá una variable global Semilla que seactualizará, según la fórmula vista, con cada llamada a la función NumeroAleatorio . Lafunción EstablecerSemilla permite cambiar el valor inicial de la semill a.

NOTA: Obsérvese que tanto NumeroAleatorio como EstablecerSemilla acceden a lavariable Semilla mediante un efecto lateral. Una variable global encapsulada dentro de unmódulo de biblioteca es una de las pocas circunstancias en las cuales es lícito el acceso auna variable mediante un efecto lateral.

4. Desarrolla una biblioteca que permita trabajar con cadenas de caracteres implementadassegún el criterio habitual en Modula-2. Las cadenas se representan mediante arrays decaracteres, con terminador CHR(0) , si la longitud de la cadena es menor al tamaño delarray. La biblioteca se llamará Cadenas y debe construirse de manera que el programaadjunto funcione correctamente, por lo que debe definir las siguientes operaciones:� Una función llamada Longitud que toma como parámetro una cadena de caracteres, y

Page 119: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 10) 3

Informática Facultad de Ciencias (Matemáticas)

devuelve su longitud (número de caracteres de la cadena que contiene).� Una función llamada Buscar , que toma como parámetros dos cadenas de caracteres y

permite buscar la primera cadena dentro de la segunda. Para ello, devuelve la posiciónde la primera ocurrencia de la primera cadena en la segunda (o el valor –1 si noaparece).

� Un procedimiento Sustituir , que toma como parámetros dos cadenas de caracteres ysustituye la primera ocurrencia de la primera cadena en la segunda (si está) porasteriscos.

� Un procedimiento llamado Borrar , que toma como parámetros dos cadenas decaracteres y elimina de la primera cadena todas las ocurrencias de la segunda cadena.

� Un procedimiento llamado WrCadena, que toma como parámetro una cadena decaracteres, y escribe por pantalla los caracteres que la forman (no se puede usarIO.WrStr ).

� Un procedimiento llamado RdCadena, que lee de teclado una cadena de caracteres y laalmacena en la variable que toma como parámetro. (no se puede usar IO.RdStr ).

� Un procedimiento llamado Insertar , que toma tres parámetros, el primero una cadenade caracteres, el segundo un valor de tipo CARDINAL, y el tercero una cadena decaracteres, y realiza la inserción de la primera cadena en la segunda a partir de laposición indicada por el segundo parámetro. En caso de que el segundo parámetrohaga referencia a una posición no válida, el procedimiento no hace nada.

NOTA: Los argumentos que representan cadenas de caracteres se pasan como arraysabiertos. La primera letra dentro de una cadena tiene como posición asociada el valor cero.

MODULE Ej1004;FROM Cadenas IMPORT RdCadena, WrCadena, Longitud, Buscar, Sustituir, Insertar, Borrar;FROM IO IMPORT RdLn, RdChar, WrLn, WrInt;VAR

C1 : ARRAY [1..20] OF CHAR;C2 : ARRAY [1..10] OF CHAR;Fin : CHAR;Pos : INTEGER;

BEGINREPEAT

WrCadena("Introd uzca una cadena de caracteres: "); WrLn;RdCadena(C1);WrCadena("Se ha leido la cadena");WrCadena(C1); WrLn;WrCadena("La longitud de la cadena leida es: ");WrCard(Longitud(C1), 0); WrLn;WrCadena("Introduzca una cadena a buscar:");RdCadena(C2);Pos := Buscar(C2,C1);IF Pos = -1 THEN

WrCadena("El patron NO aparece en la cadena");ELSE

WrCadena("Encontrado en la posición:");WrInt(Pos,0)

END;WrLn;Sustituir(C2,C1);WrCadena("Tras Sustituir, la cadena inicial queda:");WrCadena(C1); WrLn;Borrar(C1,"ABC");WrCadena("Despues de borrar ABC, la cadena queda:");WrCadena(C1); WrLn;

Page 120: Curso de Modula-2 (Incompleto).pdf

4 Relación d e Problemas (Tema 10)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Insertar("DDD", 3, C1);WrCadena("Despues de insertar DDD, la cadena queda:");WrCadena(C1); WrLn;

WrCadena("Desea repetir el proceso (S/N)?: ");Fin := RdChar(); RdLn;

UNTIL CAP(Fin) = 'N'END Ej1004.

5. Diseña una biblioteca Punto que exporte el tipo de datos PUNTO, que representa un puntodel plano bidimensional. La biblioteca debe exportar, además, operaciones para� asignar valor a un punto,� escribir un punto en pantalla� leer un punto de teclado� comparar dos puntos� desplazar un punto según la dirección determinada por el origen de coordenadas y otro

punto especificado como parámetro� girar un cierto ángulo expresado en radianes el vector determinado por el origen y otro

punto (especificado como parámetro) en el sentido contrario a las agujas del reloj

NOTA: Representar el punto bidimensional mediante un tipo registro con campos lascomponentes x e y del punto.

6. Sabemos que un conjunto es una colección desordenada de elementos en la que no existenelementos duplicados. En programación, los elementos de un conjunto tienen todos elmismo tipo al que se le llama tipo base del conjunto. En TopSpeed Modula-2, el tipo basede un conjunto puede ser CARDINAL, SHORTCARD, CHAR, un tipo enumerado, o unsubrango de cualquiera de estos tipos. Esta restricción limita bastante el uso de los tiposconjuntos. Se desea desarrollar un programa que trabaje con conjuntos de puntos del planobidimensional, para lo cual es necesario disponer conjuntos con dicho tipo base.

Diseña el tipo de datos CONJUNTOPUNTOS (conjunto de puntos del plano bidimensional),construyendo para ello una biblioteca denominada ConjPunt que ofrezca, además del tipoCONJUNTOPUNTOS, las siguientes operaciones:

Vacio: devuelve un conjunto vacío de este tipo.

Pertenece(p,c) : devuelve TRUE si el punto p es un elemento del conjunto c, o FALSE enotro caso.

Incluye(p,c) : incluye el punto p en el conjunto c. El subprograma debe comprobarpreviamente si el elemento ya estaba, en cuyo caso no hace nada.

Excluye(p,c) : excluye el punto p del conjunto c. Si el punto no está en el conjunto seescribirá en pantalla un mensaje indicándolo y no se modificará el conjunto c.

WrConjunto(c) : muestra por pantalla todos los elementos del conjunto c.

Union(c1,c2) : devuelve un nuevo conjunto que es la unión de los conjuntos c1 y c2 . Losconjuntos c1 y c2 no se modifican.

Interseccion(c1,c2) : devuelve un nuevo conjunto que es la intersección de losconjuntos c1 y c2 . Los conjuntos c1 y c2 no se modifican.

Diferencia(c1,c2) : devuelve un nuevo conjunto que es la diferencia c1-c2 . Losconjuntos c1 y c2 no se modifican.

Incluido(c1,c2) : devuelve TRUE si el conjunto c1 está incluido en el conjunto c2 .

SonIguales(c1,c2) : devuelve TRUE si el conjunto c1 coincide con el conjunto c2 .

Page 121: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 10) 5

Informática Facultad de Ciencias (Matemáticas)

Téngase en cuenta que el orden de los elementos no es relevante para determinar laigualdad de los dos conjuntos.

NOTA: Para simpli ficar, consideraremos que el cardinal máximo de cualquier variable deltipo CONJUNTOPUNTOS será 20 elementos. El tipo PUNTO debe importarse de la bibliotecadesarrollada en el problema anterior.

Escribe un programa de prueba para la biblioteca desarrollada.

Page 122: Curso de Modula-2 (Incompleto).pdf

6 Relación d e Problemas (Tema 10)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Relación d e Problemas complementarios (Tema 10)7. Escribe una biblioteca, similar a la del ejercicio 2, en la que se defina el tipo RACIONAL y

operaciones para asignar, operar, comparar, leer del teclado y escribir por pantalla valoresde dicho tipo. Prueba la biblioteca con un programa que la use. La función de comparacióndevolverá un valor en el rango [-1..1] (-1 si el primer argumento es menor al segundo, 0 sison iguales y +1 si el primero es mayor al segundo).

8. Escribe una biblioteca que exporte las funciones trigonométricas Seno y Coseno . Paraevaluarlas suma las siguientes series hasta que los términos obtenidos sean menores a unamilésima.

�+−+−=!7!5!3

)(Seno753 xxx

xx

�+−+−=!6!4!2

1)Coseno(642 xxx

x

Dado que estas series convergen cuando x → 0, deberán sumarse para valores de x en elrango 0 ≤ x ≤ π/2. Si los argumentos no se encuentran en este rango, se deberán utili zar lassiguientes igualdades:

ππππππ

ππππππ

ππππππ

22/3)2(Coseno)(Coseno

2/3)(Coseno)(Coseno

2/)(Coseno)(Coseno

22/3)2(Seno)(Seno

2/3)(Seno)(Seno

2/)(Seno)(Seno

≤≤−≡≤≤−−≡

≤≤−−≡≤≤−−≡

≤≤−−≡≤≤−≡

xsixx

xsixx

xsixx

xsixx

xsixx

xsixx

9. Escribe una biblioteca estadística en la cual se definan las siguientes operaciones, quetoman como argumento un array abierto de valores reales:

Maximo: devuelve la medida de valor máximo del array que toma como argumento.

Minimo : devuelve la medida de valor mínimo del array que toma como argumento.

Media : devuelve la media de los valores del array que toma como argumento.

DesviacionTipica : devuelve la desviación típica de los valores del array que toma comoargumento.

Varianza : devuelve la varianza de los valores del array que toma como argumento.

Mediana : devuelve la mediana de los valores del array que toma como argumento.

Moda: devuelve la moda de los valores del array que toma como argumento. Si ésta no esúnica escribirá un mensaje de aviso en pantalla y devolverá la menor de las modas.

Para este ejercicio calcularemos la mediana como:

- el valor que ocupa la posición (N+1) /2 en el array una vez ordenado si el número dedatos (N) es impar,

- la media aritmética de los valores que ocupan las posiciones N/2 y (N+1)/2 en el arrayuna vez ordenado si el número de datos es par .

Page 123: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 1

Departamento de Lenguajes yCiencias de la Computación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)

http://www.lcc.uma.es/personal/pepeg/mates

Tema 11. Diseño d e algoritmos recursivos11.1. Recursión................................................................ ................................ .........2

11.1.1 Verificación de los subprogramas recursivos...............................................3

11.2 Recursividad frente a iteración................................................................ ..........4

11.3 Eficiencia de los algoritmos recursivos ............................................................. 5

11.3.1 Sobrecarga debida al funcionamiento interno .............................................5

11.3.2 Sobrecarga debida a la solución recursiva..................................................6

11.3.3 Iteración o recursión................................................................ .................... 7

11.4 Ejemplos clásicos de recursividad ................................................................ ....8

11.4.1 Las torres de Hanoi................................................................ ..................... 8

11.4.2 Algoritmos de búsqueda recursivos .......................................................... 11

11.4.2.1 Búsqueda lineal recursiva................................................................ ....11

11.4.2.2 Búsqueda binaria recursiva ................................................................ .12

Bibliografía• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

• Pascal y estructuras de datos. Nell Dale y Susan C. Lill y. McGraw-Hill .

• Fundamentos de programación. L. Joyanes. McGraw-Hill .

Page 124: Curso de Modula-2 (Incompleto).pdf

2 11.1. Recursión

Informática Facultad de Ciencias (Matemáticas)

11.1. RecursiónUna definición es recursiva cuando el concepto que se introduce está definido en base a símismo. Un gran número de problemas se plantean de forma recursiva. Esto significa que susolución se apoya en la solución del mismo problema pero para un caso más fácil .

En matemáticas es frecuente definir conceptos en términos de sí mismos. Por ejemplo lasiguiente definición de factorial de un número n positi vo es recursiva:

î

≠−×

==

0,)!1(

0,1!

nsinn

nsin

La definición es recursiva porque estamos definiendo el factorial de n como el producto de npor el factorial de n-1, si n es distinto de cero. El concepto que definimos (factorial) aparece enla propia definición. Si queremos calcular, por ejemplo, el factorial de 4 con la definiciónanterior procederíamos del siguiente modo:

2411234!01234!1234!234!34!4 =××××=××××=×××=××=×=El siguiente ejemplo es una definición recursiva del sumatorio de los primeros n númerosnaturales:

î

≠+

== ∑∑ −

== 0,

0,01

00 nsiin

nsii n

i

n

i

Un último ejemplo es la definición de una potencia con exponente entero positi vo:

bsi e

b b si ee

e==

× ≠î

1 0

01

,

,( )

Vemos que la recursividad es una técnica que permite dar definiciones simples y elegantes. EnModula-2 es posible definir subprogramas recursivos, es decir, subprogramas en cuyo cuerpoaparezcan llamadas a sí mismos.

La definición anterior de la función factorial nos lleva a la siguiente función Modula-2:

PROCEDURE Factorial (n : CARDINAL) : CARDINAL;BEGIN

IF n = 0 THENRETURN 1

ELSERETURN n * Factorial(n-1)

ENDEND Factorial;

Obsérvese que hay una llamada a la propia función que se está definiendo (Factorial ) en laparte ELSE. Esto no presenta ningún problema ya que las reglas de ámbito de Modula-2 lopermiten.

Por otro lado, la función presenta más de una instrucción RETURN. Esta práctica es común a lahora de escribir funciones recursivas. En el caso de funciones no recursivas, es mejor estilo deprogramación utili zar una única sentencia RETURN al final del subprograma.

Veamos ahora qué es lo que ocurre si un programa ejecuta la sentenciaIO.WrCard(Factorial(3), 0) que llama a la función recursiva anterior:

Page 125: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 3

Facultad de Ciencias (Matemáticas) Informática

1) El subprograma WrCard necesita conocer el valor de su argumento Factorial(3) parapoder imprimirlo por lo cual se entra en la función Factorial . Como el argumento estádeclarado por valor se crea una nueva variable n y se asigna a ésta el valor 3.Llamemos a esta variable n (1.

2) Como n(1 es distinto de cero el valor que devuelve la llamada a Factorial(3) es lacorrespondiente al ELSE, o sea, n(1 * Factorial(n (1-1 ) . Para poder calcular esteproducto es necesario calcular Factorial(n (1-1) que provoca una nueva llamada a lafunción Factorial , en este caso con argumento 2, ya que n(1 vale 3.

3) Se vuelve a entrar en la función Factorial , por lo que se crea una nueva variable quellamaremos n(2 y cuyo valor es 2. Como el valor de n(2 es distinto de cero esta llamadadevuelve n(2 * Factorial(n (2-1 ) . De nuevo para calcular este producto se debeconocer el valor de la segunda parte lo que provoca una tercera llamada a Factorial conargumento 1, ya que n(2 vale 2.

4) Se crea n(3 con valor 1, y se devuelve n(3 * Factorial(n (3-1 ) . Se produce una ultimallamada a factorial con argumento 0.

5) Al entrar en la función Factorial se crea una nueva variable n(4 con valor 0. Como n(4

vale 0 la función Factorial devuelve el valor indicado en la parte IF, o sea, 1.

6) El producto del punto 4) puede ser calculado, por lo que la tercera llamada a factorialdevuelve el valor n(3 * Factorial(n (3-1) = 1 * 1 = 1.

7) El producto del punto 3) puede ser calculado, por lo que la segunda llamada a factorialdevuelve el valor n(2 * Factorial(n (2-1) = 2 * 1 = 2.

8) El producto del punto 2) puede ser calculado, por lo que la primera llamada a factorialdevuelve el valor n(1 * Factorial(n (1-1) = 3 * 2 = 6.

9) El valor de Factorial(3) ha sido calculado y puede ser impreso por pantalla.

11.1.1 Verificac ión d e los subp rogramas recursivos

Hemos visto que la ejecución de un subprograma recursivo hace, en general, que éste seallamado varias veces. Para asegurar que este proceso termina es necesario que el subprogramarecursivo definido cumpla las siguientes condiciones:

1) Hay al menos una posible llamada al subprograma que produce un resultado sinprovocar una nueva llamada recursiva. A esto se le llama caso base de la recursión.En el caso de la función Factorial el caso base es n=0.

La siguiente definición de la función Factorial no es correcta ya que no posee casobase:

PROCEDURE Factorial (n : CARDINAL) : CARDINAL; BEGIN RETURN n * Factorial(n-1) END Factorial;

2) Todas las llamadas recursivas se refieren a un caso que es más cercano al caso base. Enel caso de la función Factorial , cada llamada disminuye en uno el valor delargumento, por lo que éste se va acercando a cero, que es el caso base.

A partir de la expresión nnn ×−= )!1(! , y la sustitución 1+= mn se obtiene que

)1(!)!1( +×=+ mmm , de donde despejando se deduce )1(/)!1(! ++= mmm . Conesta expresión podemos construir el siguiente subprograma recursivo:

PROCEDURE Factorial (m : CARDINAL) : CARDINAL;

Page 126: Curso de Modula-2 (Incompleto).pdf

4 11.2 Recursividad frente a iteración

Informática Facultad de Ciencias (Matemáticas)

BEGIN IF m = 0 THEN RETURN 1 ELSE RETURN Factorial(m+1) DIV (m+1) END END Factorial;

Este subprograma presenta un caso base, sin embargo no es correcto ya que nocumple la condición 2). Cada llamada recursiva incrementa en uno el valor delargumento por lo que éste se va alejando del caso base y la recursión nunca termina.

3) El caso base debe acabar alcanzándose.

El siguiente subprograma cumple las condiciones 1) y 2), pero no es correcto. Si lollamamos con un argumento cuyo valor sea impar, el caso base nunca se alcanza.

PROCEDURE Factorial (n : CARDINAL) : CARDINAL;BEGIN

IF n = 0 THENRETURN 1

ELSERETURN n * (n-1) * Factorial(n-2)

ENDEND Factorial;

Para algunos algoritmos recursivos el caso base puede ser múltiple. Un ejemplo es la sucesiónde Fibonacci, que se define del siguiente modo: el primer número de Fibonacci es 0, el segundoes 1 y cualquier otro número de Fibonacci se obtiene sumando los dos números de Fibonaccique le preceden:

î

−+−

=

=

=

casootroennFibonaccinFibonacci

nsi

nsi

nFibonacci

),2()1(

2,1

1,0

)(

Los casos bases en este ejemplo son n = 1 y n = 2. Una función en Modula-2 que calcule eln-ésimo número de Fibonacci según esta definición es:

PROCEDURE Fibonacci (n : CARDINAL) : CARDINAL;BEGIN

IF n = 0 THENWrStr (“Error: Fibonacci(0) no está definido”);HALT

ELSIF n = 1 THENRETURN 0

ELSIF n = 2 THENRETURN 1

ELSERETURN Fibonacci(n-1) + Fibonacci(n-2)

ENDEND Factorial;

11.2 Recursividad frente a iteraciónCualquiera de los problemas resueltos de modo recursivo puede ser resuelto de modo iterativo.En algunos casos, como en el de la función Factorial , la solución iterativa es bastante simple:

PROCEDURE Factorial (n : CARDINAL) : CARDINAL;VAR i, Resultado : CARDINAL;

Page 127: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 5

Facultad de Ciencias (Matemáticas) Informática

BEGINResultado := 1;FOR i := 1 TO n DO

Resultado := Resultado * iEND;RETURN Resultado

END Factorial;

Podemos observar que, en la versión iterativa, la recursión ha sido sustituida por una iteración(un bucle FOR, en este caso). También ha sido necesario introducir, en la versión iterativa, dosvariables locales (i y Resultado ). En general, en los algoritmos recursivos se suele utili zar unasentencia de selección (IF), mientras que en los iterativos equivalentes se usa una sentencia deiteración (FOR, WHILE, REPEAT o LOOP) y es necesario introducir variables locales quealmacenen los resultados intermedios del cómputo.

En otros casos la solución iterativa al problema es más complicada. En un apartado posteriorveremos una solución recursiva al problema de las Torres de Hanoi. No es nada fácil encontraruna solución iterativa a este problema.

Un poco más complicada, aunque también fácil , es la solución iterativa para la recurrencia deFibonacci. En este caso, necesitamos almacenar en dos variables (FibNMenos1 y FibNMenos2 )los valores de las dos iteraciones previas:

PROCEDURE Fibonacci (n : CARDINAL) : CARDINAL;VAR FibN, FibNMenos1, FibNMenos2, i : CARDINAL;BEGIN

IF n = 0 THENWrStr (“Error: Fibonacci(0) no está definido”);HALT

ELSIF n = 1 THEN FibN := 0 ELSE FibNMenos1 := 0; FibN := 1; FOR i := 2 TO n-1 DO FibNMenos2 := FibNMenos1; FibNMenos1 := FibN; FibN := FibNMenos2 + FibNMenos1; END END; RETURN FibN END Fibonacci;

11.3 Eficiencia de los algoritmos recursivosLos algoritmos recursivos suelen ser menos eficientes (en tiempo) que los iterativoscorrespondientes. Esto es así por dos motivos principalmente:

• La sobrecarga debida al funcionamiento interno de la recursividad.

• La posible sobrecarga debida a la solución recursiva.

11.3.1 Sobrecarga debida al funcionamiento interno

En la primera sección de este tema hicimos un seguimiento en detalle de la evaluación de unallamada a la función recursiva Factorial . Podemos observar que, en general, una llamada auna función recursiva produce varias llamadas más a la propia función. Cada una de estasllamadas requiere cierto tiempo para:

• Hacer la llamada.

Page 128: Curso de Modula-2 (Incompleto).pdf

6 11.3 Eficiencia de los algoritmos recursivos

Informática Facultad de Ciencias (Matemáticas)

• Crear las variables locales y copiar los parámetros por valor.

• Ejecutar las instrucciones en parte ejecutiva de la función.

• Destruir las variables locales y parámetros por valor.

• Sali r de la función.

Si se realizan unas cuantas llamadas recursivas a una función, puede ocurrir que el tiemponecesario para hacer las llamadas y crear y destruir variables prevalezca sobre el tiemponecesario para realizar el cómputo propiamente dicho.

Este tipo de sobrecarga aparece en todos los algoritmos recursivos. Si utili zamos unafunción iterativa equivalente esta sobrecarga no aparece, ya que la función iterativa no da lugara varias llamadas a sí misma.

11.3.2 Sobrecarga debida a la solución recursiva

Este tipo de sobrecarga no se debe al modo en que funciona la recursividad en sí misma, sino aque la solución recursiva al problema es mala. Esta sobrecarga aparece en la función recursivaque calcula los números de Fibonacci. Si analizamos el algoritmo podemos observar que losmismos valores son calculados varias veces. En la siguiente figura podemos observar lasllamadas que se producen al intentar evaluar la expresión Fibonacci(5) :

Fibonacci (5)

Fibonacci (2)Fibonacci (3)

Fibonacci (1)Fibonacci (2)

Fibonacci (1)Fibonacci (2)

Fibonacci (4) Fibonacci (3)

Figura 1. Llamadas realizadas al evaluar Fibonacci(5) .

Podemos observar que han sido necesarias un total de 9 llamadas a la función para calcular estevalor y que el cálculo de Fibonacci(2) , por ejemplo, ha sido repetido 3 veces. Se harealizado un montón de trabajo repetido.

Este tipo de sobrecarga no aparece en todos los algoritmos recursivos (por ejemplo, no apareceen el caso de la función Factorial recursiva). Al evaluar Factorial(3) , no se repite ningúncómputo:

Factorial (3)

Factorial (0)

Factorial (1)

Factorial (2)

Figura 2. Llamadas realizadas al evaluar Factorial(3) .

Page 129: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 7

Facultad de Ciencias (Matemáticas) Informática

Es posible mejorar el algoritmo recursivo para el calculo de los números de Fibonacci de modoque se evite este tipo de sobrecarga. En concreto, necesitamos añadir un par de parámetrosextras en la función que almacenen el valor de los dos números de Fibonnaci anteriores. En laprimera llamada estos argumentos tomarán valores 0 y 1 (los dos primeros números de larecurrencia):

PROCEDURE Fibonacci (n : CARDINAL) : CARDINAL;PROCEDURE FibAux (n, FibN, FibNMas1 : CARDINAL) : CARDINAL;BEGIN

IF n = 1 THENRETURN FibN

ELSERETURN FibAux(n-1, FibNMas1, FibN+FibNMas1)

ENDEND FibAux;

BEGINIF n = 0 THEN

WrStr(“Error: Fibonacci(0) no está definido”);HALT

ELSERETURN FibAux(n, 0, 1)

ENDEND Fibonacci;

Si calculamos Fibonacci(5) con este algoritmo no repetimos cálculo:

Fibonacci(5)

FibAux(5,0,1)

FibAux(4,1,1)

FibAux(3,1,2)

FibAux(2,2,3)

FibAux(1,3,5)

Figura 3. Llamadas realizadas al evaluar Fibonacci(5) .

Sin embargo, la nueva solución no es tan directa como la original, lo cual era la ventajafundamental de la solución recursiva.

11.3.3 Iteración o recursión

El hecho de que la recursividad presente cierta sobrecarga (en tiempo de ejecución delalgoritmo) frente a la iteración no significa que no se deba utili zar, sino que hay que utili zarlacuando realmente sea apropiada.

Cuando el problema a resolver es relativamente simple, suele ser igualmente fácil escribir laversión iterativa y la recursiva a éste. En este caso es preferible utili zar la solución iterativa yaque es más eficiente. Sin embargo, las soluciones a ciertos problemas más complicados puedenser mucho más fáciles si utili zamos para ello la recursividad (ver el ejemplo de las Torres deHanoi). En este caso, la claridad y simplicidad del algoritmo recursivo debe prevalecer frente

Page 130: Curso de Modula-2 (Incompleto).pdf

8 11.4 Ejemplos c lásicos de recursividad

Informática Facultad de Ciencias (Matemáticas)

al tiempo extra que consume la recursión. Este enfrentamiento entre simplicidad y eficienciaaparece a menudo en la programación de ordenadores.

Otro uso común de la recursividad es como herramienta para desarrollar prototipos deprogramas. Podemos comenzar con una solución recursiva simple, que desarrollemosrápidamente, y posteriormente, si necesitamos un programa más eficiente, mejorarlo utili zandouna solución iterativa.

El verdadero valor de la recursividad es como herramienta para resolver problemas para los queno hay soluciones iterativas simples.

11.4 Ejemplos c lásicos de recursividad

11.4.1 Las torres de Hanoi

El primero de los ejemplos que estudiaremos es fácilmente resuelto mediante un algoritmorecursivo. Sin embargo, una solución iterativa al problema es mucho más complicada. Elenunciado del problema es el siguiente:

Sean tres estacas verticales y n discos de distintos radios que pueden insertarse en lasestacas formando torres. Inicialmente los n discos están situados todos en la primeraestaca por orden decreciente de radios (ver figura 3). Se trata de pasar los n discos de laprimera estaca a la última siguiendo las siguientes reglas:

1) En cada paso se mueve un único disco.

2) En ningún paso se puede colocar un disco sobre otro disco de radio menor.

3) Puede usarse la estaca central como estaca auxili ar.

Figura 4. Situación inicial del juego.

En el caso de una torre de altura uno, la solución es trivial:

Posición inicial� � � � �

La solución en el caso de una torre de dos discos consta de solo tres pasos:

Page 131: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 9

Facultad de Ciencias (Matemáticas) Informática

Posición inicial � � � �

� � � �� � � �

Si suponemos resuelto el problema para una torre de altura n-1 discos (es decir sabemos movern-1 discos de una estaca a otra usando la que queda como auxili ar), el problema de pasar ndiscos desde la estaca izquierda a la derecha queda resuelto del siguiente modo:

1) Pasar n-1 discos de la estaca izquierda a la estaca central, utili zando la derecha comoauxili ar.

2) Mover el disco mayor de la estaca izquierda a la estaca derecha.

3) Mover n-1 discos de la estaca central a la derecha usando la izquierda como auxili ar.

� � � � � � � � � � � � � � � � � � � ! " # $ % & ' ( & ) * ) ' + , - . ) *

/ 0 1 0 2 3 4 1 5 6 7 0 8 6 2 0 3 9 2 9 5 : 0 / 0 1 0 2 ; < = 3 4 1 5 6 1 0 3 9 2 9 5 : 0

Obsérvese que para solucionar el problema para una torre de altura n hemos supuesto resueltoel problema para una torre de altura n-1; la solución es recursiva.

El programa en Modula-2 que usa la estrategia anterior para mostrar por pantalla los pasosnecesarios para solucionar una torre cuya altura se ha leído desde el teclado es:

MODULE Hanoi;FROM IO IMPORT WrStr, WrLn, RdCard, RdLn;CONST IZQ = "Izquierda "; DER = "Derecha "; CEN = "Central ";VAR

Page 132: Curso de Modula-2 (Incompleto).pdf

10 11.4 Ejemplos c lásicos de recursividad

Informática Facultad de Ciencias (Matemáticas)

Altura : CARDINAL;

PROCEDURE WrMovimientos (N : CARDINAL; Izq, Der, Cen : ARRAY OF CHAR); BEGIN IF N = 1 THEN WrStr ("Mover d e "); WrStr(Izq); WrStr("a "); WrStr(Der);

WrLn ELSE WrMovimientos(N-1, Izq, Cen, Der); WrStr ("Mover de "); WrStr(Izq); WrStr("a "); WrStr(Der);

WrLn; WrMovimientos(N-1, Cen, Der, Izq)

END END WrMovimientos;

BEGIN WrStr ("Dame la altura: "); Altura := RdCard(); RdLn;

WrMovimientos(Altura, IZQ, DER, CEN)END Hanoi.

La clave del programa anterior es el subprograma recursivo

PROCEDURE WrMovimientos (N : CARDINAL; Izq, Der, Cen : ARRAY OF CHAR);

que muestra por pantalla los movimientos necesarios para mover N discos desde la estaca cuyonombre es Izq a la estaca cuyo nombre es Der , usando para ello la estaca Cen como estacaauxili ar.

Este subprograma tiene como caso base aquél en el cual la altura de la torre a resolver es 1. Pararesolver este caso (mover una torre de altura 1 que esta situada en la estaca izquierda a la estacaderecha) basta con realizar un único movimiento: mover un disco desde la estaca izquierda a laderecha.

En otro caso, si la altura de la torre es mayor a 1:

1) Escribimos primero los pasos necesarios para mover N-1 discos desde la estacaizquierda a la central usando la derecha como auxili ar. Esto se consigue con la llamadarecursiva

WrMovimientos(N-1, Izq, Cen, Der);

Obsérvese que Izq aparece como primer parámetro en esta llamada, por lo cual laestaca desde la que se mueven los N-1 discos es desde la izquierda. Cen es el segundoargumento, por lo que la estaca hacia la que se mueven los discos es la central. Porúltimo Der es el tercer argumento e indica que se use la estaca derecha como auxili ar.

2) Movemos el disco que queda en la estaca izquierda a la derecha

WrStr ("Mover de "); WrStr(Izq); WrStr("a "); WrStr(Der);

3) Escribimos los pasos necesarios para mover N-1 discos desde la torre central a laderecha usando la izquierda como auxili ar.

WrMovimientos(N-1, Cen, Der, Izq);

Podemos comprobar que la solución cumple las tres condiciones de corrección:

1) Existe un caso base (la torre de altura 1).

Page 133: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 11

Facultad de Ciencias (Matemáticas) Informática

2) Cada llamada recursiva se aproxima más al caso base ya que se decrementa en 1 el valorde N.

3) El caso base será alcanzado. Dado que en cada llamada recursiva decrementamos elvalor de N exactamente uno, en algún momento N será 1.

La llamada que activa el subprograma desde el programa principal hace que se muestren lospasos necesarios para mover tantos discos como indique la variable Altura desde la estacaizquierda a la derecha, utili zando la central como auxili ar. Si ejecutamos el algoritmo para unaaltura inicial de 3 discos obtenemos la siguiente salida por pantalla:

Dame la altura: 3

Mover de Izquierda a Derecha

Mover de Izquierda a Central

Mover de Derecha a Central

Mover de Izquierda a Derecha

Mover de Central a Izquierda

Mover de Central a Derecha

Mover de Izquierda a Derecha

El lector puede comprobar que la solución obtenida es correcta.

11.4.2 Algoritmos de búsqueda recursivos

En el tema 7 estudiamos varios algoritmos para buscar un elemento en un vector. Veremosahora como podemos expresar estos algoritmos de forma recursiva.

11.4.2.1 Búsqueda lineal recursiva

Recordemos que la búsqueda lineal consiste en ir inspeccionando cada elemento del vector deizquierda a derecha hasta que, o bien se encuentra el elemento buscado, o bien se ha recorridotodo el vector. En este último caso el elemento buscado no está en el vector.

Realizaremos la recursión sobre la longitud del vector. Así, podemos expresar esta idea como:

1) Si buscamos un elemento en un vector de tamaño cero podemos concluir que elelemento no está en éste

2) Si el elemento buscado coincide con el primer elemento del vector entonces lo hemosencontrado.

3) En otro caso deberemos buscar (llamada recursiva) a partir de la siguiente posición delvector.

El siguiente subprograma implementa esta búsqueda recursiva:

PROCEDURE BuscarLineal ( A : ARRAY OF ELEMENTO; Elemento : ELEMENTO ) : INTEGER;

PROCEDURE BuscarDesde( A : ARRAY OF ELEMENTO; Elemento : ELEMENTO;

Primero, Maximo : CARDINAL ) : INTEGER;CONST

NOENCONTRADO = -1;BEGIN

IF Primero > Maximo THENRETURN NOENCONTRADO

ELSIF A[Primero] = Elemento THENRETURN Primero

ELSERETURN BuscarDesde(A, Elemento, Primero+1, Maximo)

END

Page 134: Curso de Modula-2 (Incompleto).pdf

12 11.4 Ejemplos c lásicos de recursividad

Informática Facultad de Ciencias (Matemáticas)

END BuscarDesde;BEGIN

RETURN BuscarDesde(A, Elemento, 0, HIGH(A))END BuscarLineal;

La función devuelve la posición en la que se encontró el elemento o el valor -1 si no seencontró. El algoritmo recursivo se implementa en BuscarDesde . Esta función buscarecursivamente el elemento Elemento en el vector A . En todo momento, el segmento del vectorque queda por inspeccionar es el determinado por las variables Primero y Maximo. Con cadallamada recursiva el tamaño del segmento a inspeccionar se reduce en una unidad. El caso 1) seproduce cuando (Primero > Maximo). El caso 2) es el correspondiente a la parte ELSIFmientras que el 3) aparece tras la cláusula ELSE. La función BuscarLineal hace que comiencela búsqueda, estableciendo como segmento inicial la totalidad del vector.

Obsérvese que al ser BuscarDesde una función recursiva, será probablemente llamada variasveces. Al comienzo de cada llamada se reservará espacio para cada uno de los parámetros porvalor de esta función. Si el tamaño de la variable A es relativamente grande, reservar espaciopara ella en cada llamada puede ser costoso (en tiempo y consumo de memoria). Parasolucionar este problema podemos, aunque su valor no sea modificado, declarar este parámetropor referencia (VAR A: ARRAY OF ELEMENTO), ya que no se crean nuevas copias con cadallamada para este tipo de parámetros.

11.4.2.2 Búsqueda binaria recursiva

La búsqueda binaria puede ser también fácilmente implementada de modo recursivo. Si elvector está ordenado en orden ascendente, el algoritmo es el siguiente:

1) Si buscamos un elemento en un vector de tamaño cero podemos concluir que elelemento no está en éste

2) Si el elemento que ocupa la posición central del vector coincide con el buscado, lohemos encontrado en la posición central.

3) Si el elemento buscado es menor que el que ocupa la posición central del vector, buscaren la mitad izquierda del segmento.

4) En otro caso, buscar en la mitad derecha del segmento.

El siguiente subprograma implementa esta búsqueda recursiva:

PROCEDURE BuscarBinaria ( A : ARRAY OF ELEMENTO; Elemento : ELEMENTO ) : INTEGER;

PROCEDURE BuscarEn ( A : ARRAY OF ELEMENTO; Elemento : ELEMENTO;

Primero, Ultimo : CARDINAL ) : INTEGER;CONST

NOENCONTRADO = -1;VAR

Central : CARDINAL;BEGIN

IF Primero > Ultimo THENRETURN NOENCONTRADO

ELSECentral := (Primero + Ultimo) DIV 2;IF A[Central] = Elemento THEN

RETURN CentralELSIF A[Central] > Elemento THEN

RETURN BuscarEn(A, Elemento, Primero, Central-1)ELSE

RETURN BuscarEn(A, Elemento, Central+1, Ultimo)END

END

Page 135: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 13

Facultad de Ciencias (Matemáticas) Informática

END BuscarEn;BEGIN

RETURN BuscarEn(A, Elemento, 0, HIGH(A))END BuscarLineal;

En este caso, el tamaño del segmento donde realizar la búsqueda queda reducido a la mitad encada llamada recursiva. Las mismas consideraciones de eficiencia estudiadas para la búsquedalineal recursiva son aplicables a este algoritmo.

Page 136: Curso de Modula-2 (Incompleto).pdf
Page 137: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 1

Facultad de Ciencias (Matemáticas) Informática

Relación d e problemas (Tema 11)

1. El máximo común divisor de dos números enteros se puede definir con ayuda de lassiguientes propiedades elementales:

mcd a b mcd a b

mcd a a a

mcd a a

mcd a b mcd b a

mcd a b mcd a b b a>b

( , ) ' ( , ),

' ( , ) ,

' ( , ) ,

' ( , ) ' ( , ),

' ( , ) ' ( , ),

===== −

0

si

Escribe un programa recursivo que calcule el máximo común divisor de dos númerosenteros usando las propiedades citadas.

Sigue las llamadas realizadas por el algoritmo que diseñes para calcular el máximo comúndivisor de 6 y 32.

2. Observe que la última propiedad del ejercicio anterior permite reducir el cálculo delmáximo común divisor de dos números al mismo problema pero con dos números máspequeños, utili zando para ello la operación diferencia. Tal operación puede sustituirse porel resto de la división entera, ya que si k es un divisor de a y b (siendo a>b), entonces ktambién es un divisor del resto de la división de a entre b:

mcd a b mcd a b b a>b' ( , ) ' ( , ),= MOD si

Dicho resto puede ser cero, y en ese caso el máximo común divisor es el valor de b(puesto que a sería un múltiplo de b). Esta propiedad permite acelerar el método delejercicio anterior.

Escribe un programa recursivo que calcule el máximo común divisor de dos númerosenteros usando las propiedades citadas, junto con las del ejercicio anterior.

Sigue las llamadas realizadas por el algoritmo que diseñes para calcular el máximo comúndivisor de 6 y 32.

3. Escribe un programa recursivo que calcule números combinatorios teniendo en cuenta lassiguientes propiedades:

m

nn m=n

m

nm n n=m

m

n

m

n

m

n

= =

= = −

=

−−

+

1 0

1 1

1

1

1

,

,

si o si

si o si

Sigue las llamadas que realiza el algoritmo para calcular 5 sobre 2.

4. Escribe un programa recursivo que calcule la suma de los primeros N números paresnaturales.

5. La función de Ackermann se describe del siguiente modo:

Page 138: Curso de Modula-2 (Incompleto).pdf

2 Tema 11. Diseño d e algoritmos recursivos

Informática Facultad de Ciencias (Matemáticas)

A m n n m

A m n A m n

A m n A m A m n m n>

( , ) ,

( , ) ( , ),

( , ) ( , ( , )),

= + == − == − − >

1 0

11 0

1 1 0 0

si

si

si y

Esta función recursiva es muy conocida porque aun pareciendo muy simple da lugar acálculos muy complicados. Por ejemplo la llamada A(2, 2) produce 27 llamadas recursivaspara devolver el valor 7.

Escribe un subprograma recursivo que calcule la función de Ackermann para valores de my n dados. Utili za éste para escribir un programa que produzca la siguiente tabla:

m \ n 0 1 2 3 4 5 6 7

0 1 2 3 4 5 6 7 8

1 2 3 4 5 6 7 8 9

2 3 5 7 9 11 13 15 17

... ... ... ... ... ... ... ... ...

Puede que notes que el ordenador tarda un poco en calcular los últimos valores de la tabla.Esto no es extraño ya que el cálculo de A(2, 6), por ejemplo, da lugar a 172.233 llamadasrecursivas.

NOTA: Para la versión 1 de TopSpeed se produce un error al intentar evaluar A(3, n) si n> 7, A(4, n) si n > 0 o A(m,n) si m > 4.

6. Escribe un programa recursivo que lea un número entero positi vo desde teclado y loescriba por pantalla en orden inverso (si se lee 124 se escribirá 421).

7. Escribe un programa recursivo que calcule la suma de las cifras de un número enteropositi vo leído de teclado.

8. Escribir un programa recursivo que lea un número entero positi vo expresado en base 10desde teclado y lo pase a otra base entre 2 y 10 también leída de teclado. No se conoce apriori el número de cifras del número en la base destino, por lo cual no se podrá utili zarun array para ir almacenando las cifras calculadas.

9. Supongamos que tenemos un ordenador que sólo trabaja con números naturales y para elcual sólo existen dos funciones aritméticas:

PROCEDURE Suc(n : CARDINAL) : CARDINAL;BEGIN

RETURN n+1END Suc;

PROCEDURE Pred(n : CARDINAL) : CARDINAL;BEGIN

IF n = 0 THENWrStr(“ERROR, número negativo”);HALT

ELSERETURN n-1

ENDEND Pred;

Escribe los siguientes subprogramas de un modo recursivo:

PROCEDURE Suma (a, b : CARDINAL) : CARDINAL;PROCEDURE Resta (a, b : CARDINAL) : CARDINAL;PROCEDURE Producto (a, b : CARDINAL) : CARDINAL;

Page 139: Curso de Modula-2 (Incompleto).pdf

Tema 11. Diseño d e algoritmos recursivos 3

Facultad de Ciencias (Matemáticas) Informática

PROCEDURE Cociente (a, b : CARDINAL) : CARDINAL;

Teniendo en cuenta las siguientes propiedades:

Suma a a

Suma a b Suc Suma a Pred b b

( , )

( , ) ( ( , ( )),

0

0

== ≠si

Resta a a

Resta a

Resta a b a b

Resta(a,b) Resta Pred(a) Pred(b) a b

( , )

( , )

( , ) ,

( , ),

0

0

0

=== =

= ≠

ERROR, numero negativo

si

si

Producto a

Producto a b Suma Producto a Pred b a

( , )

( , ) ( ( , ( )), )

0 0==

Cociente a

Cociente a b Suc Cociente Resta a b b a b

Cociente a b a b

( , )

( , ) ( ( ( , ), )),

( , ) ,

0

0

== ≥= <

ERROR, division por cero

si

si

Recuerda que no puedes usar +, - , * , DIV o MOD en estos cuatro subprogramas.

Intenta deducir tú las propiedades de Resto(a,b) (valor del resto obtenido al dividir a porb) y escribe el correspondiente subprograma recursivo.

10. Escribir un programa recursivo que lea una cadena de caracteres acabada en punto desdeel teclado y la imprima al revés por pantalla. No se conoce el tamaño máximo de lacadena a priori, por lo cual el programa no podrá almacenar la cadena en un array talcomo se va leyendo. Utili za lectura múltiple de datos (sin RdLn).

Nota: Hablamos de programa recursivo cuando utili za subprogramas recursivos.

Page 140: Curso de Modula-2 (Incompleto).pdf

4 Tema 11. Diseño d e algoritmos recursivos

Informática Facultad de Ciencias (Matemáticas)

Relación complementar ia (Tema 11)

11. Escribe un programa recursivo que calcule potencias enteras de números reales, usandopara ello las siguientes propiedades:

a

a a a si n

aa

si n

n n

nn

0

1

1

0

10

== ⋅ >

=

<

12. Escribe un procedimiento recursivo que escriba N saltos de línea por pantalla, siendo N unargumento de este subprograma.

13. Escribe un programa recursivo que calcule el capital Cn obtenido, situando el capital C0 ainterés compuesto durante n años al interés anual r (expresado en porcentaje). Larecurrencia que permite calcular Cn es:

C C r

C C r

C C rn n

1 0

2 1

1

1 100

1 100

1 100

= ⋅ += ⋅ +

= ⋅ +−

( / )

( / )

...

( / )

14. Obtén una fórmula no recursiva para Cn .Escribe un programa que calcule Cn a partir de C0

y r utili zando la fórmula obtenida.

15. Escribir un programa recursivo que lea un número entero positi vo expresado en base bdesde teclado (con b ≤ 9) y lo pase a base 10. (Utili za el tipo LONGCARD)

16. Escribe una función recursiva que devuelva el elemento de mayor valor en un array deenteros.

17. Escribe una función recursiva que devuelva la suma de los valores almacenados en unarray de enteros.

18. Escribe una función recursiva que devuelva el n-ésimo elemento de menor valor en unarray de enteros. Por ejemplo, si el array contiene los valores 12 7 3 9 1 5 21 y n =1devuelve 1, si n=2 devuelve 3, si n=5 devuelve 9 y si n=28 se produce un error.

Page 141: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 1

Facultad de Ciencias (Matemáticas) Informática

Departamento de Lenguajes y Ciencias de laComputación

UNIVERSIDAD DE MÁLAGA

Apuntes para la asignatura

InformáticaFacultad de Ciencias (Matemáticas)

http://www.lcc.uma.es/personal/pepeg/mates

Tema12.

Estructuras de datos dinámicas

12.1 Gestión dinámica de la memoria ................................................................ ......2

12.2 El tipo POINTER................................................................ ............................... 3

12.3 Procedimientos NEW y DISPOSE ................................................................ ....4

12.4 Operaciones con Punteros ................................................................ ...............5

12.5 Listas enlazadas ................................................................ ............................... 8

12.5.1 Listas ordenadas................................................................ ....................... 21

Bibliografía• Programación 1. José A. Cerrada y Manuel Collado. Universidad Nacional de

Educación a Distancia.

• Programming with TopSpeed Modula-2. Barry Cornelius. Addison-Wesley.

• Fundamentos de programación. Algoritmos y Estructuras de datos. L. Joyanes Aguilar.McGraw Hill .

• Pascal y estructuras de datos. Nell Dale y Susan C. Lill y. McGraw-Hill

Page 142: Curso de Modula-2 (Incompleto).pdf

2 12.1 Gestión d inámica de la memoria

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Introdu cc iónLas estructuras de datos dinámicas permiten trabajar con variables cuyo tamaño no es conocidoen tiempo de compilación. Estas estructuras pueden crecer o decrecer durante la ejecución delprograma, según sea necesario. En Modula-2, estas estructuras son implementadas utili zando eltipo puntero (POINTER).

En este tema, introducimos el tipo puntero y sus operaciones asociadas. Una de las estructurasdinámicas más simples que se pueden implementar con punteros es la li sta enlazada.Implementaremos un módulo de biblioteca para el manejo de li stas enlazadas.

12.1 Gestión d inámica de la memoriaHasta ahora, todos los tipos de datos estudiados, ya sean simples o estructurados, tienen unapropiedad común: son estáticos. Esto significa que las variables de estos tipos mantienen lamisma estructura y tamaño durante toda la ejecución del programa. El tamaño de estas variablesse debe anticipar cuando se escribe el programa y queda fijado durante la compilación (tiempode compilación). Es imposible ampliar el tamaño de la estructura durante la ejecución delprograma (tiempo de ejecución).

Así, por ejemplo:

• Si declaramos un Array de cinco elementos de tipo INTEGER, el contenido de cada unade las casill as podrá cambiar, pero el tamaño máximo de este será siempre fijo (cincoelementos enteros).

• Si declaramos una variable REAL puede cambiar su contenido, pero no el tamañoasignado por el compilador para ella (el necesario para un único valor de tipo REAL).

Sin embargo, hay muchas situaciones en las que no sólo debe cambiar el contenido o valor deuna variable, sino también su tamaño. La estructura debe ir creciendo y decreciendo mientras seejecuta el programa. En esos casos la cantidad de memoria necesaria para almacenar ciertainformación no se puede determinar en tiempo de compilación, sino que hay que esperar a queel programa se esté ejecutando (tiempo de ejecución).

La técnica usada para manejar estas situaciones es la asignación dinámica de memoria.Con esta técnica tendremos variables dinámicas, que se caracterizan porque pueden crearseo destruirse en tiempo de ejecución. Veremos que estas estructuras dinámicas sonextremadamente flexibles, aunque es muy fácil cometer errores cuando son programadas.

El siguiente ejemplo muestra la necesidad de esta técnica: supongamos que se desea escribir unprograma que lea una cantidad de números reales variable desde teclado, calcule la media detodos ellos y, por último, muestre por pantalla aquellos números leídos cuyos valores seanmayores a la media. La cantidad total de números se leerá al principio del programa.

Si nos dicen que el número máximo de valores que se puede leer es MAX, podemos definir unarray de reales con este tamaño. Sin embargo, esta aproximación tiene un problema. Si MAX esgrande, estaremos desperdiciando bastante memoria si el total introducido luego es bastantemenor.

Otro problema más difícil de resolver es que no se sepa de antemano el número máximo denúmeros a leer. En este caso la solución del Array no es válida, ya que, sea cual sea el valor quedemos a MAX, siempre podemos quedarnos cortos. Una gran cantidad de problemas reales paralos que se utili zan los ordenadores tiene esta característica: no se conoce la cantidad máxima dedatos a tratar.

Page 143: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 3

Facultad de Ciencias (Matemáticas) Informática

Para resolver el problema anterior, necesitamos que el lenguaje de programación permita:

1) Ir creando nuevas variables cada vez que las necesitemos (cada vez que vayamos a leerun número en nuestro ejemplo).

2) Acceder a las variables creadas.

3) Destruir variables cuando ya no sean necesarias.

Conseguiremos las dos primeras características mediante instrucciones de asignación yliberación dinámica de memoria. La tercera se consigue mediante las variables de tipopuntero.

Mediante la asignación dinámica de memoria conseguiremos estructuras de datos cuyo tamañoserá variable. Es importante observar que el tamaño de estos datos solo estará acotado por eltamaño máximo de la memoria del ordenador en la cual se esté ejecutando el programa, pero nopor un valor máximo determinado a priori.

12.2 El tipo POINTERUna variable de tipo puntero no contiene un dato, como los tipos estudiados hasta ahora,sino que contiene la dirección (o posición) que ocupa en la memoria del ordenador otravariable. Se dice que la variable puntero apunta a esta última variable. A la variable puntero sela llama también variable referencia. A la variable apuntada se la llama variablereferenciada o anónima.

Cuando se declara una variable puntero es necesario indicar el tipo de la variable apuntada. Elsiguiente ejemplo declara una variable, cuyo nombre es Ptr , como una variable de tipo punteroa un valor entero:

VAR Ptr : POINTER TO INTEGER;

Esto significa que el valor de la variable Ptr es una posición en la memoria del ordenador en lacual hay situada un dato de tipo INTEGER:

14000Ptr

57

...13996139981400014002...

En el ejemplo, la variable Ptr contiene como valor la posición de memoria 14000. En estadirección de memoria está situado un valor de tipo INTEGER (57).

Normalmente, las direcciones de memoria concretas almacenadas en las variables puntero noson importantes, por lo que la situación anterior la representamos como:

Ptr 57

Es decir, Ptr apunta a una posición de memoria en la cual se almacena una variable de tipoINTEGER cuyo valor es 57. En este ejemplo la variable referencia es Ptr , mientras que lareferenciada es la casill a en la que se encuentra el valor 57. Esta última se llama tambiénanónima porque no tiene nombre.

Page 144: Curso de Modula-2 (Incompleto).pdf

4 12.3 Procedimientos NEW y DISPOSE

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

El único modo de acceder a la variable anónima es mediante el puntero que la referencia. Siqueremos asignar el valor 100 a la variable anónima, la instrucción correspondiente en Modula-2 es:

Ptr^ := 100;

Esta instrucción se lee: asignar a la variable apuntada por Ptr el valor 100. Para indicar que loque queremos modificar es la variable anónima hay que escribir un signo ̂ tras el nombre de lavariable referencia. (Obsérvese que Ptr^ se asemeja con partir de la variable Ptr en el dibujo yseguir la flecha). Tras esta instrucción la situación es:

Ptr 100

Si queremos acceder a la variable anónima para leer su valor también hemos de utili zar elnombre de la variable referencia y un signo ^. Así, para incrementar en dos el valor de lavariable anónima hemos de escribir:

Ptr^ := 2 + Ptr^;

con lo obtenemos:

Ptr 102

Una variable puntero puede almacenar también un valor especial: NIL . Este valor indica que elpuntero no apunta a nada (no contiene una dirección de memoria válida). Representaremosgráficamente con una línea diagonal un puntero que contiene el valor NIL :

Ptr

Normalmente el valor NIL se utili za para inicializar las variables de tipo puntero. Estainicialización no es automática por lo que debe ser realizada explícitamente por el programador(las variables punteros no son una excepción a la regla en Modula-2, por lo que su valorpredeterminado es indeterminado).

12.3 Procedimientos NEW y DISPOSECuando declaramos una variable de tipo puntero como por ejemplo

VAR Ptr : POINTER TO INTEGER;

la variable referencia Ptr se crea estáticamente, en tiempo de compilación, pero la variablereferenciada o anónima debe crearse posteriormente, en tiempo de ejecución. La forma de crearuna variable anónima es mediante el procedimiento de asignación dinámica de memoria NEW.Este procedimiento toma como argumento una variable de tipo puntero, crea una nueva variabledel tipo al cual apunta el argumento y hace que el puntero argumento apunte a la variabledinámica creada. El valor previo que tuviese la variable puntero se pierde. Tras ejecutar lainstrucción

NEW(Ptr);

la situación es la siguiente:

Page 145: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 5

Facultad de Ciencias (Matemáticas) Informática

Ptr ¿...?

Obsérvese que se ha creado una nueva variable anónima y que Ptr apunta a ella, pero que lavariable anónima no toma ningún valor por defecto. El programador debe darle un valorexplícitamente:

Ptr^ := 15;

Ptr 15

Con este procedimiento podemos crear tantas variables (dinámicamente) como necesitemosdurante la ejecución del programa, y podemos referenciarlas mediante punteros, con lo quesolucionamos el problema de partida.

Al crear una variable dinámica la cantidad de memoria libre en el ordenador disminuye. Lasvariables dinámicas, una vez creadas, siguen ocupando espacio de memoria hasta que sedestruyan explícitamente. Cuando se destruye una variable dinámica el espacio que ocupabavuelve a quedar disponible. Para destruir una variable dinámica se utili za el procedimientoDISPOSE. Este procedimiento toma como argumento un puntero a una variable dinámica, liberala memoria que la variable dinámica ocupa y pone el puntero a valor NIL para indicar que ya noapunta a nada. Tras ejecutar

DISPOSE(Ptr);

la situación es la siguiente:

Ptr 15

Una vez destruida, la variable dinámica no existe, por lo que es ilegal intentar acceder a ella. Lamemoria libre del sistema aumenta al destruir una variable dinámica.

En realidad, NEW y DISPOSE son solo dos modos más sencill os de escribir llamadas a dossubprogramas más complicados ALLOCATE y DEALLOCATE que se encuentran en la libreríaStorage . Por esto, cuando un programa va a utili zar NEW y DISPOSE, debe importarALLOCATE y DEALLOCATE:

FROM Storage IMPORT ALLOCATE, DEALLOCATE;

Nótese que, curiosamente, no es válido importar NEW y DISPOSE directamente.

12.4 Operaciones con PunterosLas operaciones que se pueden realizar con variables de tipo puntero son básicamente tres:

1) Derreferenciación.

2) Asignación

3) Comparación

La derreferenciación es la operación mediante la cual accedemos a la variable anónimaapuntada por el puntero, añadiendo para ello el operador ^ tras el nombre de la variable puntero.

A modo de ejemplo, supongamos las siguientes declaraciones de tipos y variables:

TYPE

Page 146: Curso de Modula-2 (Incompleto).pdf

6 12.4 Operaciones con Punteros

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

COMPLEJO = RECORDReal, Imag : REAL

END;PCOMPLEJO = POINTER TO COMPLEJO;

VARPtr1, Ptr2 : PCOMPLEJO;

Para comenzar a trabajar con estas variables, crearemos una variable dinámica y lareferenciaremos mediante la variable Ptr1 .

NEW(Ptr1);

Ptr1 ¿...? ¿...?

Real Imag

La nueva variable dinámica es un registro que cuenta con dos campos (Real e Imag ) ambos detipo REAL. Sin embargo, los valores de estos campos están indefinidos. Para asignar valores aestos campos es necesario derreferenciar la variable puntero:

Ptr1^.Real : = 5.0;Ptr1^.Imag := 1.2;

Ptr1 5.0 1.2

Real Imag

El mismo resultado puede ser obtenido usando la sentencia WITH:

WITH Ptr1^ DOReal := 5.0;Imag := 1.2

END;

La asignación es la operación que permite asignar a una variable puntero otra variable delmismo tipo. El efecto conseguido al asignar dos variables puntero es que ambas apuntan a lamisma variable dinámica. Si en la situación actual ejecutamos la sentencia

Ptr2 := Ptr1;

las variables quedan:

Ptr1 5.0 1.2

Real Imag

Ptr2

Es decir, podemos acceder a la variable anónima por dos caminos: Ptr1^ o Ptr2^ . En este casodecimos que la variable anónima está múltiplemente referenciada. Como no hay dos copias dela variable anónima, si se modifica su contenido mediante un camino, al acceder mediante elotro veremos el cambio. Por ejemplo, el siguiente código produce como salida por pantalla 8.0:

Ptr1^.Real := 8.0;WrReal(Ptr2^.Real, 1, 0);

ya que el estado de la memoria es:

Page 147: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 7

Facultad de Ciencias (Matemáticas) Informática

Ptr1 8.0 1.2

Real Imag

Ptr2

Un fallo muy común a la hora de trabajar con referencias múltiples es que se libere la variabledinámica mediante una de las referencias pero no se ponga a NIL la otra:

DISPOSE(Ptr1);WrReal(Ptr2^.Real, 1, 0); (* ERROR !!! *)

produciría un error ya que la variable anónima ha sido destruida, por lo que no se debe accedera ella a través de Ptr2:

Ptr1 8.0 1.2

Real Imag

Ptr2

Por otro lado, a una variable anónima siempre se le puede asignar el valor NIL, sea cual sea eltipo de la variable anónima. Éste es el segundo tipo de asignación disponible para variablespunteros

Ptr2 := NIL;

Es un error intentar derreferenciar un puntero cuyo valor sea NIL . En este caso, el programafinaliza inmediatamente con el consiguiente error. Este es uno de los errores más comunes quese comenten al programar con punteros. Es MUY IMPORTANTE asegurarnos de que unpuntero no vale NIL antes de derreferenciarlo.

Por último, las variables de tipo puntero pueden compararse entre sí si tienen el mismo tipo ocon NIL (siempre). El resultado de la expresión Ptr1 = Ptr2 es TRUE si las dos variablesapuntan a la misma variable anónima (referencias múltiples). Sin embargo, si las dos variablespunteros apuntan a dos variables anónimas distintas el resultado será FALSE, aunque elcontenido de las dos variables anónimas sea idéntico. Así, el siguiente ejemplo

NEW(Ptr1);NEW(Ptr2);WITH Ptr1^ DO

Real := 15.0; Imag := 20.0END;WITH Ptr2^ DO Real := 15.0; Imag := 20.0END;IF Ptr1 = Ptr2 THEN

WrStr(“Iguales”)ELSE

WrStr(“Distintas”)END

produce por pantalla la salida “Distintas” . Si lo que se desea es comprobar que loscontenidos de las dos variables son iguales, se debe usar la derreferenciación Ptr1^ = Ptr2^ ,que será TRUE si el contenido de la variable anónima apuntada por Ptr1 es igual al de lavariable anónima apuntada por Ptr2 , aunque dichas variables no sean las mismas.

Page 148: Curso de Modula-2 (Incompleto).pdf

8 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

12.5 Listas enlazadasLo que realmente hace de los punteros una herramienta potente es que pueden apuntar avariables que a su vez contienen punteros (típicamente registros en los cuales al menos uno delos campos es un puntero). Gracias a esta característica, podemos crear estructuras de datosdinámicas (el tamaño crece y decrece).

Una de estas estructuras es la lista enlazada. Se trata de una estructura que almacena unacantidad variable de datos, pero con la restricción de que todos tienen el mismo tipo (tipo base).La li sta se representa mediante un puntero que apunta a un registro. Este registro contiene doscampos: el primero almacena el primer elemento de la li sta(un dato del tipo base) y el segundoun puntero a otro registro (que corresponde al siguiente dato). De este modo, cada dato contienela dirección del siguiente elemento. Cada uno de los registros que forman parte de la li sta sellaman nodos. El campo puntero del último nodo de la li sta enlazada contiene el valor NIL . Elsiguiente ejemplo muestra una li sta de tres datos:

1 2

L

4

Cuando la li sta está vacía (no contiene ningún dato), el valor del puntero inicial debe ser NIL :

L

El acceso a los elementos de una li sta no es directo (como ocurría en los arrays). Para acceder aun elemento partimos del puntero inicial y hemos de ir pasando por todos los nodos anteriores aél. Además, solo es posible pasar de un nodo a su siguiente, pero no al previo.

Las declaraciones de tipo para la estructura li sta (con tipo base INTEGER) son:

TYPE ELEMENTO = INTEGER; PNODO = POINTER TO NODO; NODO = RECORD

Elem : ELEMENTO; Sig : PNODO

END; LISTA = PNODO;

Obsérvese que el tipo NODO aparece en la definición de PNODO antes de estar declarado. EnModula-2, solo se puede utili zar un tipo aún no definido en la definición de otro, cuando se estádefiniendo un tipo puntero. Por supuesto, el tipo no definido debe definirse posteriormente(como ocurre en el ejemplo).

La estructura li sta es una estructura recursiva, ya que es un puntero a un registro de doscomponentes, donde la segunda es a su vez una li sta.

Junto a la definición del tipo para las li stas, es necesario definir una serie de operaciones parasu manejo. Podemos hacer esto mediante un módulo de biblioteca. El módulo de definicióncorrespondiente puede ser el siguiente:

DEFINITION MODULE Lista;TYPE ELEMENTO = INTEGER; PNODO = POINTER TO NODO; NODO = RECORD

Elem : ELEMENTO; Sig : PNODO

END; LISTA = PNODO;

Page 149: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 9

Facultad de Ciencias (Matemáticas) Informática

PROCEDURE Crear () : LISTA;PROCEDURE InsertarInicio ( VAR L : LISTA; Elem : ELEMENTO);PROCEDURE InsertarFinal ( VAR L : LISTA; Elem : ELEMENTO);PROCEDURE InsertarEnPosicion ( VAR L : LISTA; Elem : ELEMENTO;

Pos : CARDINAL);PROCEDURE Eliminar ( VAR L : LISTA; Elem : ELEMENTO);PROCEDURE EliminarEnPosicion ( VAR L : LISTA; Pos : CARDINAL);PROCEDURE ElementoEnPosicion (L : LISTA; Pos : CARDINAL) : ELEMENTO;PROCEDURE Longitud (L : LISTA) : CARDINAL;PROCEDURE WrLista (L : LISTA);PROCEDURE Destruir ( VAR L : LISTA);

END Lista.

El significado de cada una de las operaciones es:

• Crear : devuelve una li sta vacía (sin ningún elemento). Se usa para inicializar variablesdel tipo LISTA.

• InsertarInicio : inserta un nuevo elemento en la primera posición de una li sta.

• InsertarFinal : inserta un nuevo elemento en la última posición de una li sta.

• InsertarEnPosición : inserta un nuevo elemento dentro de la li sta en la posiciónindicada por el tercer parámetro. Los nodos de la li sta comienzan a numerarse por uno.

• Eliminar : elimina la primera aparición del elemento Elem de la li sta. Si el elementoestá repetido varias veces dentro de la li sta solo se elimina la primera (más a laizquierda) ocurrencia.

• EliminarEnPosicion : elimina de una li sta el elemento que ocupa la posición dada porel segundo argumento.

• ElementoEnPosicion : devuelve el valor del elemento que ocupa la posición dada porel segundo argumento, pero no lo elimina de la li sta.

• Longitud : devuelve el número de elementos en una li sta.

• WrLista : escribe el contenido de una li sta por pantalla.

• Destruir : elimina todos los elementos de una li sta, liberando la memoria queocupaban.

Obsérvese que en las operaciones donde la li sta se ve modificada es necesario pasar elcorrespondiente argumento por referencia (VAR).

La implementación de cada operación aparecerá en el correspondiente módulo deimplementación. Es necesario importar ALLOCATE y DEALLOCATE ya que usaremos NEW yDISPOSE. También definimos un par de constantes que representan la li sta vacía y el valor delpuntero final de una li sta (ambos son NIL ):

IMPLEMENTATION MODULE Lista;

FROM Storage IMPORT ALLOCATE, DEALLOCATE;FROM IO IMPORT WrStr, WrInt, WrChar;

CONST LISTAVACIA = NIL; FINLISTA = NIL;

...END Lista.

Page 150: Curso de Modula-2 (Incompleto).pdf

10 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

La operación Crear es inmediata. Basta con devolver NIL ya que por convenio las li stas vacíasse representan con este valor.

PROCEDURE Crear () : LISTA;BEGIN RETURN LISTAVACIAEND Crear;

Supongamos que queremos insertar el elemento 3 al principio de la li sta

1 2

L

Para ello hemos de seguir los siguientes pasos:

1) Creamos un nuevo nodo (lo referenciaremos mediante la variable puntero PtrNuevo ):

1 2

L

? ?PtrNuevo

NEW(PtrNuevo);

2) Copiamos el valor a insertar en el campo Elem

1 2

L

3 ?PtrNuevo

PtrNuevo .̂Elem := 3;

3) Enlazamos el nuevo nodo con el principio de la li sta

1 2

L

3PtrNuevo

PtrNuevo .̂Sig := L;

4) Por último, la li sta comienza ahora por el nuevo nodo:

1 2

L

3PtrNuevo

L := PtrNuevo;

Podemos unir todo lo anterior en el siguiente subprograma:

PROCEDURE InsertarInicio ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrNuevo : PNODO;BEGIN

NEW(PtrNuevo); PtrNuevo^.Elem := Elem; PtrNuevo^.Sig := L; L := PtrNuevoEND InsertarInicio;

Page 151: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 11

Facultad de Ciencias (Matemáticas) Informática

La variable PtrNuevo será destruida al sali r del subprograma, ya que es una variable local aéste.

Para que el subprograma anterior pueda ser considerado correcto es necesario comprobar quetambién funciona en el caso de que la li sta inicial sea vacía:

L

? ?PtrNuevo

NEW(PtrNuevo);

L

3PtrNuevo

PtrNuevo .̂Elem := 3;PtrNuevo^.Sig := L;

L

3PtrNuevo

L := PtrNuevo

El orden en que se realizan las operaciones debe ser exactamente el indicado en elsubprograma, ya que si invirtiésemos el orden de las dos últimas instrucciones, perderíamos lareferencia al antiguo primer nodo de la li sta. A la hora de trabajar con li stas enlazadas es muyimportante no dejar nunca ningún nodo inaccesible. Para evitar esto se usarán variablespunteros auxili ares siempre que sea necesario.

También es importante observar que el parámetro L pasa por referencia ya que su valor se vemodificado dentro del subprograma.

Para insertar un elemento nuevo al final de una li sta creamos un nuevo nodo, copiamos el valordel elemento y ponemos el puntero del campo Sig a FINLISTA (ya que este nodo ocupará laúltima posición de la li sta). A continuación consideramos dos casos:

• Si la li sta está vacía enlazamos L con este nodo.

• En otro caso hay que recorrer la li sta hasta encontrar el último nodo. Esto se suele hacerutili zando una variable de tipo puntero (Ptr en nuestro caso) que se desplaza hastaalcanzar un nodo cuyo campo Sig sea FINLISTA . Una vez localizado el último nodo loenlazamos con el nuevo.

PROCEDURE InsertarFinal ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrNuevo, Ptr : PNODO;BEGIN NEW(PtrNuevo); PtrNuevo^.Elem := Elem; PtrNuevo^.Sig := FINLISTA; IF L = LISTAVACIA THEN L := PtrNuevo ELSE Ptr := L; WHILE Ptr^.Sig <> FINLISTA DO Ptr := Ptr^.Sig END;

Page 152: Curso de Modula-2 (Incompleto).pdf

12 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Ptr^.Sig := PtrNuevo ENDEND InsertarFinal;

El siguiente ejemplo muestras los pasos seguidos para insertar un elemento de valor 4 en unalista con dos elementos (1 y 2):

1 2

L

Ptr

1 2

L

Ptr

1 2

L

4

PtrNuevoPtr

Este algoritmo también se puede describir más elegantemente de modo recursivo. Para insertarun elemento en una li sta vacía basta con crear un nodo y enlazarlo como en InsertarInicio .En otro caso hacemos una llamada recursiva, pero con el segmento de li sta que comienza por elsegundo elemento:

PROCEDURE InsertarFinal ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrNuevo : PNODO;BEGIN IF L = LISTAVACIA THEN

NEW(PtrNuevo); PtrNuevo^.Elem := Elem; PtrNuevo^.Sig := FINLISTA; L := PtrNuevo ELSE InsertarFinal(L^.Sig, Elem) ENDEND InsertarFinal;

Por ejemplo, si queremos insertar un 4 en la li sta mostrada se producen dos llamadas recursivas.El valor de L en la primera llamada recursiva es L(1 y en la segunda L(2. En la última llamada,como L(2 es LISTAVACIA , se crea el nuevo nodo y se enlaza.

1) Llamada inicial: InsertarFinal (L, 4)

1 2

L

2) Primera Llamada recursiva: InsertarFinal (L (1 , 4)

1 2

L(1L

3) Segunda Llamada recursiva: InsertarFinal (L (2 , 4)

Page 153: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 13

Facultad de Ciencias (Matemáticas) Informática

1 2

L

4

PtrNuevo

L(2

Las operaciones relativas a li stas enlazadas suelen ser fáciles de implementar de modorecursivo ya que la estructura es recursiva. En las operaciones recursivas suele ser necesarioconsiderar siempre dos casos: la li sta está vacía (caso base) o no. La llamada recursiva sueleaproximarse al caso base tomando la li sta que se obtiene saltando el nodo inicial (L^.Sig ).

Para insertar un nuevo elemento en una posición dada de una li sta se contemplan tres casos:

• Si la posición es cero, se produce un error ya que la primera posición válida es uno queindica insertar al comienzo de la li sta.

• Si la posición es uno llamamos al subprograma InsertarInicio .

• En otro caso utili zamos Ptr para localizar el nodo previo a donde se ha de insertar. Paraello se parte del comienzo de la li sta y se avanza Pos-2 veces (cuidando no alcanzar elfinal de la li sta). Si al intentar localizar el nodo previo se alcanzó el final de la li sta esque la posición indicada para insertar no es válida (es mayor al número de elementos enla li sta). En otro caso, creamos un nuevo nodo y lo enlazamos tras el nodo localizado.

PROCEDURE InsertarEnPosicion ( VAR L : LISTA; Elem : ELEMENTO; Pos : CARDINAL);

VAR PtrNuevo, Ptr : PNODO; Avanzados : CARDINAL;BEGIN IF Pos = 0 THEN WrStr("Error: InsertarEnPosicio n fuera de rango"); HALT ELSIF Pos = 1 THEN InsertarInicio(L, Elem) ELSE (* Pos >= 2 *) Avanzados := 0; Ptr := L; WHILE (Ptr<>FINLISTA) AND (Avanzados < Pos-2) DO Ptr := Ptr^.Sig; INC(Avanzados) END;

IF Ptr = FINLISTA THEN WrStr("Error: InsertarEnPosicion fuera de rango"); HALT ELSE NEW(PtrNuevo); PtrNuevo^.Elem := Elem; PtrNuevo^.Sig := Ptr^.Sig; Ptr^.Sig := PtrNuevo END ENDEND InsertarEnPosicion;

Veamos el algoritmo en funcionamiento si queremos insertar un elemento de valor 7 en laposición cuarta de la siguiente li sta:

1 2

L

5 9

1) Avanzar dos nodos (4-2 = 2):

Page 154: Curso de Modula-2 (Incompleto).pdf

14 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

1 2

L

5 9

Ptr

1 2

L

5 9

Ptr

1 2

L

5 9

Ptr

2) Crear y enlazar el nuevo nodo:

1 2

L

5 9

7

PtrNuevo

Ptr

Obsérvese el orden seguido al enlazar el nuevo nodo: primero se enlaza el nuevo nodo con elsiguiente nodo al que apunta Ptr y por último se enlaza el nodo apuntado por Ptr con el nuevo.Este orden es importante, ya que si lo hiciésemos en orden inverso perderíamos la referencia alúltimo nodo.

El algoritmo InsertarEnPosicion escrito de modo recursivo es:

PROCEDURE InsertarEnPosicion ( VAR L : LISTA; Elem : ELEMENTO; Pos : CARDINAL);

PROCEDURE InsertarAux ( VAR L : LISTA; Elem : ELEMENTO; Pos : CARDINAL);

VAR PtrNuevo : PNODO; BEGIN

IF Pos = 1 THENNEW(PtrNuevo); (* Se puede usar InsertarInicio(L,Elem) *)

PtrNuevo^.Elem := Elem; PtrNuevo^.Sig := L; L := PtrNuevo

ELSIF L = LISTAVACIA THENWrStr("Error: InsertarEnPosicion fuera de rango");

HALTELSE

InsertarAux(L^.Sig, Elem, Pos-1)END

END InsertarAux;BEGIN IF Pos = 0 THEN WrStr("Error: InsertarEnPosicion fuera de rango"); HALT ELSE InsertarAux (L, Elem, Pos) ENDEND InsertarEnPosicion;

Page 155: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 15

Facultad de Ciencias (Matemáticas) Informática

Describimos ahora un algoritmo para eliminar la primera ocurrencia de un elemento dado deuna li sta enlazada:

PROCEDURE Eliminar ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrBorrar, PtrPrev : PNODO;BEGIN PtrBorrar := L; PtrPrev := NIL; WHILE (PtrBorrar<>FINLISTA) AND (PtrBorrar^.Elem<>Elem) DO PtrPrev := PtrBorrar; PtrBorrar := PtrBorrar^.Sig END; IF PtrBorrar = FINLISTA THEN WrStr("Error: Eliminar, elemento no encontrado"); HALT ELSE IF PtrPrev = NIL THEN

L := L^.Sig ELSE

PtrPrev^.Sig := PtrBorrar^.Sig; END;

DISPOSE(PtrBorrar) ENDEND Eliminar;

Para ello localizaremos con PtrBorrar el primer nodo cuyo elemento coincida con el valor quese quiere eliminar. Como Modula-2 utili za evaluación en cortocircuito de expresionesbooleanas, si PtrBorrar alcanza en algún momento el final de la li sta (porque el elementobuscado no se encuentre en ella) la segunda parte de la expresión AND no llega a evaluarse, ygracias a esto, en ese caso no se llega a derreferenciar PtrBorrar (lo cual sería un error ya queel valor de esta variable en ese punto sería NIL ).

Se utili za la técnica del puntero retrasado. PtrPrev siempre apuntará al nodo previo aPtrBorrar o será NIL si PtrBorrar está situado sobre el primer nodo de la li sta. Es necesariocomprobar en todo momento que no hemos alcanzado el final de la li sta. Tras el bucle, si hemoslocalizado el nodo a eliminar (PtrBorrar <> FINLISTA ) contemplamos dos casos:

1) El nodo a eliminar es el primero de la li sta. En este caso PtrPrev valdrá NIL . Paraeliminar el nodo avanzamos L y como PtrBorrar apunta al primer nodo llamamos aDISPOSE(PtrBorrar) para liberar la memoria que ocupaba.

2) El nodo a eliminar no es el primero de la li sta. Enlazamos el nodo previo al eliminadocon el siguiente al eliminado. De nuevo PtrBorrar apunta al nodo a eliminar ydevolvemos su memoria.

Veamos como funciona el algoritmo si queremos eliminar la primera ocurrencia del valor 4 dela siguiente li sta:

1 2

L

4 4

1) Localizar el nodo a borrar

1 2

L

4 4

PtrBorrarPtrPrev

Page 156: Curso de Modula-2 (Incompleto).pdf

16 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

1 2

L

4 4

PtrPrev PtrBorrar

1 2

L

4 4

PtrPrev PtrBorrar

2) Desenlazarlo de la li sta

1 2

L

4 4

PtrPrev PtrBorrar

3) Liberar memoria

1 2

L

4 4

PtrPrev PtrBorrar

El alumno debería verificar que el algoritmo descrito también funciona si el nodo que seelimina es el primero de la li sta o el último.

De modo recursivo tenemos:

PROCEDURE Eliminar ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrBorrar : PNODO;BEGIN IF L = LISTAVACIA THEN WrStr("Error: Eliminar, elemento no encontrado"); HALT ELSIF L^.Elem = Elem THEN PtrBorrar := L; L := L^.Sig; DISPOSE(PtrBorrar); ELSE Eliminar (L^.Sig, Elem) ENDEND Eliminar;

El siguiente procedimiento elimina el nodo que ocupa la posición indicada de una li sta. Elalgoritmo es muy similar al anterior salvo que en vez de avanzar PtrBorrar hasta encontrar elelemento se avanza Pos-1 veces:

PROCEDURE EliminarEnPosicion ( VAR L : LISTA; Pos : CARDINAL);VAR PtrBorrar, PtrPrev : PNODO; Avanzados : CARDINAL;BEGIN IF Pos = 0 THEN WrStr("Error: EliminarEnPosicion fuera de rango"); HALT

Page 157: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 17

Facultad de Ciencias (Matemáticas) Informática

ELSEPtrBorrar : = L; PtrPrev := NIL; Avanzados := 0; WHILE (Avanzados<Pos-1) AND (PtrBorrar<>FINLISTA) DO PtrPrev := PtrBorrar; PtrBorrar := PtrBorrar^.Sig; INC(Avanzados) END;

IF PtrBorrar = FINLISTA THEN WrStr(" Error: EliminarEnPosicion fuera de rango"); HALT ELSE

IF PtrPrev = NIL THEN L := L^.Sig ELSE PtrPrev^.Sig := PtrBorrar^.Sig; END;

DISPOSE(PtrBorrar) END ENDEND EliminarEnPosicion;

El algoritmo recursivo es:

PROCEDURE EliminarEnPosicion ( VAR L : LISTA; Pos : CARDINAL); PROCEDURE EliminarAux( VAR L : LISTA; Pos : CARDINAL); VAR PtrBorrar : PNODO; BEGIN IF L = LISTAVACIA THEN WrStr("Error: EliminarEnPosicion fuera de rango"); HALT ELSIF Pos = 1 THEN PtrBorrar := L; L := L^.Sig; DISPOSE(PtrBorrar); ELSE EliminarAux(L^.Sig, Pos-1) END END EliminarAux;BEGIN IF Pos = 0 THEN WrStr("Error: EliminarEnPosicion fuera de rango"); HALT ELSE EliminarAux(L, Pos) ENDEND EliminarEnPosicion;

Para devolver el valor del elemento que se encuentra en una posición dada dentro de la li sta,localizamos el nodo correspondiente avanzando Ptr Pos-1 posiciones en la li sta y devolvemosel valor almacenado en el nodo apuntado por Ptr . Es importante comprobar si hemos alcanzadoel final de la li sta:

PROCEDURE ElementoEnPosicion (L:LISTA; Pos: CARDINAL) : ELEMENTO;VAR Ptr : PNODO; Avanzados : CARDINAL; Resultado : ELEMENTO;BEGIN IF Pos = 0 THEN WrStr("Error: ElementoEnPosicion fuera de rango"); HALT ELSE

Page 158: Curso de Modula-2 (Incompleto).pdf

18 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Ptr := L; Avanzados := 0; WHILE (Ptr <> FINLISTA) AND (Avanzados < Pos-1) DO Ptr := Ptr^.Sig; INC (Avanzados) END;

IF Ptr = FINLISTA THEN WrStr("Error: ElementoEnPosicion fuera de rango"); HALT ELSE Resultado := Ptr^.Elem END;

RETURN Resultado ENDEND ElementoEnPosicion;

Recursivamente:

PROCEDURE ElementoEnPosicion (L:LISTA; Pos: CARDINAL) : ELEMENTO; PROCEDURE ElementoAux( VAR L:LISTA; Pos: CARDINAL) : ELEMENTO; BEGIN IF L = LISTAVACIA THEN WrStr("Error: ElementoEnPosicion fuera de rango"); HALT ELSIF Pos = 1 THEN RETURN L^.Elem ELSE RETURN ElementoAux(L^.Sig, Pos-1) END END ElementoAux;BEGIN IF Pos = 0 THEN WrStr("Error: ElementoEnPosicion fuera de rango"); HALT ELSE RETURN ElementoAux(L, Pos) ENDEND ElementoEnPosicion;

Para calcular la longitud de una li sta recorremos todos sus nodos con la variable Ptr hastaencontrar el fin de la li sta. Utili zamos un contador que inicializamos a cero y queincrementamos cada vez que avanzamos un nodo:

PROCEDURE Longitud (L : LISTA) : CARDINAL;VAR Ptr : PNODO; LaLongitud : CARDINAL;BEGIN LaLongitud := 0; Ptr := L; WHILE Ptr <> FINLISTA DO Ptr := Ptr^.Sig; INC(LaLongitud) END; RETURN LaLongitudEND Longitud;

De modo recursivo, basta observar que la longitud de la li sta vacía es cero y en otro casodevolvemos uno más la longitud de la li sta que empieza en el nodo siguiente:

PROCEDURE Longitud (L : LISTA) : CARDINAL;BEGIN IF L = LISTAVACIA THEN

Page 159: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 19

Facultad de Ciencias (Matemáticas) Informática

RETURN 0 ELSE RETURN 1 + Longitud(L^.Sig) ENDEND Longitud;

Escribiremos una li sta entre corchetes y separando los elementos por comas. Es necesariocomprobar para cada elemento si el último de la li sta, ya que en dicho caso no se escribe lacoma correspondiente:

PROCEDURE WrLista (L : LISTA);VAR Ptr : PNODO;BEGIN WrChar('['); Ptr := L; WHILE Ptr <> FINLISTA DO WrInt(Ptr^.Elem, 0); IF Ptr^.Sig <> FINLISTA THEN WrChar(',') END; Ptr := Ptr^.Sig END; WrChar(']')END WrLista;

La solución recursiva también es fácil , aunque necesitamos un subprograma auxili ar:

PROCEDURE WrLista (L : LISTA); PROCEDURE WrAux(L : LISTA); BEGIN IF L <> LISTAVACIA THEN WrInt(L^.Elem, 0); IF L^.Sig <> FINLISTA THEN WrChar(',') END; WrAux(L^.Sig) END END WrAux;BEGIN WrChar('['); WrAux(L); WrChar(']')END WrLista;

Por último necesitamos una operación que deje la li sta vacía liberando toda la memoriaocupada por los nodos. En este caso necesitamos recorrer la li sta utili zando la técnica delpuntero retrasado. Los elementos apuntados por el puntero retrasado son los que se destruyen:

PROCEDURE Destruir ( VAR L : LISTA);VAR PtrPrev, Ptr : PNODO;BEGIN Ptr := L; PtrPrev := NIL; WHILE Ptr <> FINLISTA DO PtrPrev := Ptr; Ptr := Ptr^.Sig; DISPOSE(PtrPrev) END; L := LISTAVACIAEND Destruir;

Gráficamente, si destruimos la li sta

Page 160: Curso de Modula-2 (Incompleto).pdf

20 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

1 2

L

4

los pasos seguidos son

1 2

Ptr

4

PtrPrev

2

Ptr

4

PtrPrev

Ptr

4

PtrPrev

L

Nótese que L queda a NIL finalmente (lo cual es adecuado, ya que la li sta está vacía).

El algoritmo recursivo correspondiente es más breve:

PROCEDURE Destruir ( VAR L : LISTA);BEGIN IF L <> LISTAVACIA THEN Destruir(L^.Sig); DISPOSE(L) ENDEND Destruir;

Los pasos seguidos por el algoritmo recursivo son los siguientes:

1 2

L

4

1 2L

4L(1

1 2L

4L(2

1 2L

4L(3

1 2L

4L(2

1 2L L(1

Page 161: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 21

Facultad de Ciencias (Matemáticas) Informática

1L

L

En cada momento, el número en el superíndice de L indica el anidamiento de la llamadarecursiva que se está ejecutando.

Un programa que usa la biblioteca definida para leer una cantidad de números no conocida apriori y mostrarlos es:

MODULE Demo;FROM Lista IMPORT Crear, InsertarFinal, WrLista, Destruir,

LISTA, ELEMENTO;FROM IO IMPORT RdInt, RdCard, RdLn, WrStr;

VARLista : LISTA;Numero : ELEMENTO;Total, i : CARDINAL;

BEGINWrStr(“Dame el total de números a introducir: “);Total := RdCard(); RdLn;

Lista := Crear();

FOR i := 1 TO Total DOWrStr(“Dame un número: “);Numero := RdInt(); RdLn;InsertarFinal(Lista, Numero)

END;

WrStr(“Los números introducidos fueron: “);WrLista(Lista);

Destruir(Lista)

END Demo.

Es importante liberar la memoria que ocupa la li sta (en este caso mediante la operaciónDestruir ) cuando ésta ya no es necesaria.

12.5.1 Listas ordenadas

Una lista ordenada (en orden ascendente, aunque se pueden definir de modo similar en ordendescendente) es una li sta en la cual el valor de un nodo es siempre menor o igual al nodo que lesigue.

Las operaciones de búsqueda de elementos dentro de la li sta pueden ser implementadas de unmodo más eficiente que si se usan li stas no ordenadas. A la hora de localizar un elemento nohay que recorrer toda la li sta para asegurarnos que no existe. Basta con llegar a un nodo cuyovalor sea mayor al buscado. Esta mejora puede ser bastante considerable, especialmente si lali sta tratada tiene una longitud grande.

Por otro lado, una li sta ordenada también se usa si se desea obtener un li stado ordenado de losdatos almacenados.

Page 162: Curso de Modula-2 (Incompleto).pdf

22 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

En el caso de las li stas ordenadas, a la hora de insertar un elemento, no se especifica la posiciónque éste debe ocupar. Solo existe una operación InsertarOrdenada que toma un nuevo dato ylo coloca en su posición adecuada dentro de la li sta, de modo que la li sta resultante sigueestando ordenada. Se mantiene la operación para eliminar por posición dentro de la li sta y la deeliminación de la primera ocurrencia de un dato dado.

El siguiente módulo de definición corresponde a una biblioteca de li stas ordenadas. De lasoperaciones que aparecen en el módulo, solo InsertarOrdenado y Eliminar son distintas alas presentadas en el apartado anterior.

DEFINITION MODULE ListaOrd;TYPE ELEMENTO = INTEGER; PNODO = POINTER TO NODO; NODO = RECORD Elem : ELEMENTO;

Sig : PNODO END; LISTA = PNODO;

PROCEDURE Crear () : LISTA;PROCEDURE InsertarOrdenada ( VAR L : LISTA; Elem : ELEMENTO);PROCEDURE Eliminar ( VAR L : LISTA; Elem : ELEMENTO);PROCEDURE EliminarEnPosicion ( VAR L : LISTA; Pos : CARDINAL);PROCEDURE ElementoEnPosicion (L : LISTA; Pos : CARDINAL) : ELEMENTO;PROCEDURE Longitud (L : LISTA) : CARDINAL;PROCEDURE WrLista (L : LISTA);PROCEDURE Destruir ( VAR L : LISTA);

END ListaOrd.

Para insertar un nuevo dato hemos de buscar su posición adecuada dentro de la li sta. Para ellobuscamos con PtrSig el primer nodo cuyo contenido sea mayor o igual al que estamosinsertando. Habrá que insertar el nuevo nodo justo delante del nodo al cual apunte PtrSig .Para ello utili zamos la técnica del puntero retrasado, de modo que cuando PtrSig encuentra elnodo siguiente, PtrPrev apunta al nodo anterior y solo hay que enlazar el nuevo nodo entreestos. Previamente es necesario comprobar si PtrSig no llegó a avanzar ni un solo nodo (en esecaso PtrPrev = NIL ) ya que en ese caso el nuevo nodo iría colocado al principio de la li sta:

PROCEDURE InsertarOrdenada ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrNuevo, PtrSig, PtrPrev : PNODO;BEGIN

NEW(PtrNuevo); PtrNuevo^.Elem := Elem;

PtrSig := L; PtrPrev := NIL; WHILE (PtrSig<>FINLISTA) AND (PtrSig^.Elem<Elem) DO PtrPrev := Ptr Sig; PtrSig := PtrSig^.Sig

END;

PtrNuevo^.Sig := PtrSig; IF PtrPrev = NIL THEN

L := PtrNuevo ELSE

PtrPrev^.Sig := PtrNuevo; ENDEND InsertarOrdenada;

El alumno debería comprobar que el algoritmo también funciona si el nuevo nodo va a pararjusto al final de la li sta (o sea, es mayor que cualquiera de los nodos en la li sta).

Page 163: Curso de Modula-2 (Incompleto).pdf

Tema 12. Estructuras de datos dinámicas 23

Facultad de Ciencias (Matemáticas) Informática

La función que elimina un dato es muy similar a la de las li stas enlazadas no ordenadas, pero eneste caso basta con alcanzar un nodo con valor mayor al buscado para concluir que el nodo noestá en la li sta:

PROCEDURE Eliminar ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrBorrar, PtrPrev : PNODO;BEGIN PtrBorrar := L; PtrPrev := NIL; WHILE (PtrBorrar<>FINLISTA) AND (PtrBorrar^.Elem<Elem) DO PtrPrev : = PtrBorrar; PtrBorrar := PtrBorrar^.Sig END;

IF (PtrBorrar=FINLISTA) OR (PtrBorrar^.Elem<>Elem) THEN WrStr("Error: Eliminar elemento no encontrado"); HALT ELSE

IF PtrPrev = NIL THENL := L^.Sig

ELSEPtrPrev^.Sig := PtrBor rar^.Sig;

END;DISPOSE(PtrBorrar)

ENDEND Eliminar;

De modo recursivo:

PROCEDURE InsertarOrdenada ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrNuevo : PNODO;BEGIN IF (L = LISTAVACIA) OR (Elem <= L^.Elem) THEN (* Crear el nodo nuevo *) NEW(PtrNuevo); PtrNuevo^.Elem := Elem;

(* Enlazarlo *) PtrNuevo^.Sig := L; L := PtrNuevo ELSE InsertarOrdenada(L^.Sig, Elem) ENDEND InsertarOrdenada;

(* Elimina el primer elemento en la lista que coincide con Elem *)

PROCEDURE Eliminar ( VAR L : LISTA; Elem : ELEMENTO);VAR PtrBorrar : PNODO;BEGIN IF (L = LISTAVACIA) OR (L^.Elem > Elem) THEN WrStr("Error: Eliminar, elemento no encontrado"); HALT ELSIF L^.Elem = Elem THEN (* Enlazar con el siguiente y liberar memoria *) PtrBorrar := L; L := L^.Sig; DISPOSE(PtrBorrar); ELSE Eliminar (L^.Sig, Elem) ENDEND Eliminar;

Page 164: Curso de Modula-2 (Incompleto).pdf

24 12.5 Listas enlazadas

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

Page 165: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 12) 25

Facultad de Ciencias (Matemáticas) Informática

Relación d e Problemas (Tema 12)1. Responder verdadero o falso teniendo en cuenta las siguientes declaraciones:

TYPEPUNTERO = POINTER TO NODO;NODO = RECORD

Info : INTEGER;Siguiente : PUNTERO

END;VAR

Ptr : PUNTERO;UnNodo : NODO;

a) El espacio que ocupa la variable Ptr se asigna dinámicamente en tiempo deejecución

b) El espacio que ocupa Ptr^ se asigna dinámicamente en tiempo de ejecución.

c) Ptr^ está inicialmente indefinido.

d) Después de la sentencia NEW(Ptr) , Ptr^.Siguiente vale NIL.

e) Ptr ocupa la misma cantidad de espacio en memoria que un registro del tipo NODO.

f) La declaración de UnNodo es sintácticamente incorrecta porque los registros tipoNODO sólo pueden ser asignados dinámicamente.

2. Dadas las declaraciones

TYPECADENA = ARRAY[1..20 ] OF CHAR;ELEMENTO = RECORD

Nombre : CADENA;ID : INTEGER

END;PUNTERO = POINTER TO NODO;NODO = RECORD

Datos : ELEMENTO;Anterior,Siguiente : PUNTERO

END;VAR

Lista, Ptr : PUNTERO;

identificar el tipo de cada una de las siguientes expresiones como un puntero, un registro,un carácter, una cadena de caracteres o un entero.

a) Lista^.Siguiente

b) Lista^.Siguiente^

c)Lista^.Datos.Nombre

d) Ptr^.Anterior^.Datos.ID

e) Ptr^.Anterior

f) Ptr^.Datos.Nombre[1 ]

3. Dadas dos li stas enlazadas ordenadas escribir un procedimiento o función que genere unanueva li sta mezcla ordenada de ambas. Las dos li stas originales deben quedar intactas (losnodos que constituyen la li sta mezcla deben crearse). Escribir una versión iterativa y otrarecursiva del subprograma.

Page 166: Curso de Modula-2 (Incompleto).pdf

26 Relación d e Problemas (Tema 12)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

4. Diseña una biblioteca (módulo de definición e implementación) donde se defina un nuevotipo CONJUNTO. Las variables de este tipo representarán conjuntos de números reales. Paraello cada conjunto debe representarse como una li sta enlazada. Incorpora al módulo lasoperaciones normales predefinidas sobre conjuntos (Crear , Incluir , Excluir ,Pertenece , EsVacio , Cardinal , Union , Interseccion y Diferencia ).

NOTA: En la li sta que represente un conjunto no deben aparecer elementos repetidos.

5. Dadas dos li stas enlazadas que almacenan números enteros escribir un programa quegenere todas las combinaciones posibles de parejas de números, uno de cada li sta, cuyasuma es menor o igual que un número N introducido por teclado.

6. Un polinomio puede ser representado por una li sta enlazada en la que cada nodo contieneun coeficiente (de tipo REAL), el valor del exponente (un valor CARDINAL) y un punterohacia el siguiente elemento. Escribir un módulo de biblioteca en el que se defina el tipocorrespondiente y subprogramas que permitan:

a) Crear polinomios.

b) Añadir términos al polinomio.

c) Leer polinomios de teclado.

d) Escribir polinomios en pantalla.

e) Sumar dos polinomios.

f) Restar dos polinomios.

g) Calcular el producto de dos polinomios.

h) Calcular la derivada de un polinomio dado.

i) Evaluar el polinomio para un valor de la variable independiente también de tipoREAL

NOTA: Las li stas enlazadas que representan los polinomios estarán ordenadas en formaascendente por el grado de los nodos. Por ejemplo, el polinomio x4 + 7.5x + 2 estaríarepresentado por la li sta:

2.0

0

7.5

1

1.0

4

P

Las operaciones de suma, resta, producto y derivada deben generar li stas nuevas (losnodos que las forman deben crearse)

7. Las li stas doblemente enlazadas son li stas en las cuales cada nodo consta de un campopara almacenar un dato y dos campos de enlace o punteros que apuntan respectivamente alnodo anterior y posterior al actual. Estas li stas pueden recorrerse en dos sentidos: haciadelante y hacia atrás. Las li stas se representan mediante un registro de dos punteros(Inicio y Fin ) que apunten hacia el primer y el último nodo respectivamente.

Page 167: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 12) 27

Facultad de Ciencias (Matemáticas) Informática

8 15 4

L

FinInicio

Escribir un módulo de biblioteca para implementar esta estructura y operaciones para sumanejo.

8. Una pila es un tipo especial de li sta en la cual la inserción y eliminación de elementos serealiza sólo por un extremo que se denomina cima o tope. Los elementos sólo puedeneliminarse en orden inverso al que se insertan. El último elemento que se insertó en la pilaes el primero que se puede sacar. A este tipo de estructuras se las llama LIFO (siglas de laexpresión inglesa Last-In, First-Out).

Las operaciones asociadas a una pila son

1) Crear : devuelve una pila vacía.

2) Insertar : añade un elemento a la pila

3) Sacar : extrae el último elemento insertado en la pila. Es un error extraer de unapila vacía.

4) Cima: devuelve el valor del último elemento insertado pero no lo extrae. Es unerror obtener la cima de una pila vacía.

5) EsVacia : devuelve TRUE si la pila está vacía (no contiene ningún elemento).

Un ejemplo de uso de una pila de enteros es el siguiente:

1

2

1 1

P := Crear(); Insertar(P,1); Insertar(P,2); Extraer(P);

Cima

Cima

Cima

Escribir un módulo de biblioteca donde se defina el tipo pila de valores enteros y lasoperaciones asociadas.

NOTA: Una pila se representará mediante una li sta enlazada. La operación de inserciónen la pila consiste en insertar al inicio de la li sta, mientras que la de extracción eneliminar el primer elemento de la li sta.

9. Escribe un subprograma que tome como argumento una li sta simplemente enlazada yescriba su contenido por pantalla en orden inverso.

10. Escribe un subprograma Filtro que tome como argumento una li sta de valores enteros yuna función que toma un entero y devuelve un valor booleano. Esta función debe devolveruna nueva li sta consistente en los argumentos de la li sta original para los que la función seevalúa a TRUE. Los nodos de la li sta resultante deben crearse. Escribe un programa que,utili zando esta función, lea una serie de valores enteros, los almacene en una li sta, calculeuna nueva li sta donde queden solo los pares y por último escriba esta li sta por pantalla.

11. Dadas las definiciones de datos vistas en el tema para una li sta enlazada de valoresenteros, escribe procedimientos o funciones para:

1) Duplicar una li sta enlazada (crear otra li sta enlazada con los mismos elementos

Page 168: Curso de Modula-2 (Incompleto).pdf

28 Relación d e Problemas (Tema 12)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

que el argumento).

2) Borrar el nodo que contiene el máximo valor de una li sta enlazada.

3) Intercambiar el valor n-ésimo con el m-ésimo de la li sta.

4) Dada la siguiente cabecera:

PROCEDURE Busca (L:LISTA; e:ELEMENTO): PNODO;

devuelva el puntero al primer nodo de L cuyo valor es e o NIL si no existe ningúnnodo con dicho valor.

5) Dada la siguiente cabecera:

PROCEDURE InsBusca( VAR L:LISTA; e:ELEMENTO):PNODO;

añada e a la li sta L, si no está en ella, y siempre devuelva un puntero al nodo quecontiene a e

12. Una lista enlazada circular es una li sta enlazada donde el puntero del último nodo no esNIL, sino que apunta al primer nodo:

L L

1

L

1 2

Listas circulares de cero, uno y dos elementos.

Escribe un módulo de biblioteca donde definas el tipo para li stas circulares y operacionespara insertar al principio, insertar al final y escribir una li sta por pantalla, entre otras.

Page 169: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 12) 29

Facultad de Ciencias (Matemáticas) Informática

Relación Complementaria (Tema 12)13. Una cola es un tipo especial de li sta en la cual las eliminaciones de datos se realizan al

principio de la li sta (frente) y las inserciones se realizan en el otro extremo (final) (escomo la cola del autobús). Las colas se utili zan para almacenar datos que deben serprocesados en el orden de llegada. El primer elemento que entra es el primero que sale. Aeste tipo de estructuras se las llama FIFO (First-In, First-Out).

Las operaciones asociadas a una cola son

1) Crear : devuelve una cola vacía.

2) Insertar : añade un elemento al final de la cola

3) Sacar : extrae el primer elemento en la cola. Es un error extraer de una cola vacía.

4) Primero : devuelve el valor del primer elemento en la cola pero no lo extrae. Es unerror obtener el primer elemento de una cola vacía.

5) EsVacia : devuelve TRUE si la cola está vacía (no contiene ningún elemento).

Un ejemplo de uso de una cola de enteros es el siguiente:

C := Crear(); Insertar(C,1); Insertar(C,2); Extraer(C);

1 2 1 2

PrimeroPrimeroPrimero

Escribir un módulo de biblioteca donde se defina el tipo cola de valores enteros y lasoperaciones asociadas.

14. Escribe un subprograma que tome como argumento dos li stas simplemente enlazadas yconstruya una nueva li sta que contiene tanto los nodos de la primera como los de lasegunda. Los nodos de la li sta resultante deben crearse.

15. Escribe un subprograma Map que tome como argumento una li sta de valores enteros y unafunción que toma un entero y devuelve otro entero. Esta función debe devolver una nuevalista cuyos valores son los obtenidos al aplicar la función argumento a cada uno de losvalores en la li sta original. Escribe un programa que usando esta función lea una serie devalores en una li sta, calcule una nueva li sta con sus cuadrados y la escriba por pantalla.

16. Diseña un procedimiento Purga que elimine los elementos duplicados de una li staenlazada que tome como parámetro.

17. Escribe procedimientos recursivos e iterativos que a partir de una li sta enlazada de enteros

1) Calcule el mayor elemento de la li sta.

2) Calcule la suma de los elementos de la li sta.

3) Calcule la longitud de la li sta.

18. Una implementación más eficiente de una cola se obtiene usando una li sta enlazadacircular. Si el puntero exterior del anill o apunta siempre al último elemento de la cola,podemos siempre acceder al primero en un solo paso. Implementa una cola mediante unalista enlazada circular utili zando esta idea.

19. Un modo de almacenar un diccionario de palabras es mediante una tabla hash. Esta

Page 170: Curso de Modula-2 (Incompleto).pdf

30 Relación d e Problemas (Tema 12)

José E. Gallardo Ruiz Dpto. Lengu ajes y Ciencias de la Computación - UMACarmen M. García Lóp ez

estructura consiste en un array cuyo índice es [’a’..’z’] y donde cada posición delarray es un puntero a una li sta enlazada. Cada nodo de las li stas enlazadas poseerá elnombre de una palabra y su definición (cadenas de caracteres)

‘a’

‘b’

.

.

‘z’

ala extremidad de un ave atar ...

zapato ...

A la hora de almacenar una palabra se crea un nuevo nodo con el nombre y la definición yse enlaza en la li sta correspondiente a la primera letra de la palabra. La estructura esbastante eficiente, ya que para localizar una palabra basta con mirar en la li stacorrespondiente a su primera letra.

Escribe un módulo de biblioteca donde se defina el tipo TABLAHASH y operaciones para

• Insertar una palabra y su correspondiente definición en una tabla.

• Dada una palabra, buscar su definición en una tabla.

• Dada una palabra, eliminarla de una tabla.

• Mostrar todas las palabras y las definiciones asociadas en una tabla.

20. Una matriz dispersa es una matriz donde muchos de sus elementos tienen valor cero. Enpredicción meteorológica, por ejemplo, es necesario manejar matrices de este tipo congrandes dimensiones. Si utili zamos un array bidimensional estamos desperdiciando unagran cantidad de memoria. Una solución a este problema es utili zar li stas enlazadas. Unamatriz se representa por un registro de tres campos. El primero es el número total de filasde la matriz, el segundo el de columnas y el tercero una li sta enlazada vertical con tantoselementos como filas tenga la matriz. Cada nodo de la li sta vertical es un puntero a unalista enlazada con los nodos no nulos de la fila. Estos nodos tienen dos campos ademásdel puntero: la columna a la cual corresponde el dato y el dato. Las li stas horizontalesestán ordenadas de menor a mayor según el contenido del primer campo (la columna a lacual corresponde el dato). Por ejemplo la siguiente matriz

0 6 0 3 0

1 0 0 0 0

0 0 0 0 0

0 8 0 0 10

es representada como:

Page 171: Curso de Modula-2 (Incompleto).pdf

Relación d e Problemas (Tema 12) 31

Facultad de Ciencias (Matemáticas) Informática

4

5

Filas

Cols

2 6 4 3

1 1

2 8 5 10

Escribe un módulo de biblioteca donde se defina el tipo MATRIZ y las siguientesoperaciones:

• Crear : toma como argumentos el número total de filas y columnas de una matriz ydevuelve una matriz vacía.

• Asignar : toma como argumentos una matriz, una fila, una columna y un valor.Asigna este valor a la correspondiente posición de la matriz. Para ello hay quebuscar si existe un nodo en la matriz correspondiente a la posición. Si es así, seasigna el nuevo valor. En otro caso se crea un nuevo nodo con los valoresadecuados y se enlaza en su posición correspondiente.

• Elemento : toma una matriz, una fila y una columna y devuelve el valor delelemento que ocupa dicha posición en la matriz. Si no existe el correspondientenodo en la matriz, se devolverá cero.

• WrMatriz : escribe una matriz que toma como argumento por pantalla.

• RdMatriz : permite crear una matriz y leer sus componentes desde teclado.

Como aplicación de la biblioteca, escribe un programa que lea dos matrices del teclado,calcule su producto y lo escriba por pantalla.