Sie sind auf Seite 1von 88

UNIVERSIDAD POLITÉCNICA DE MADRID

ESCUELA TÉCNICA SUPERIOR DE INGENIEROS INDUSTRIALES


SECCIÓN DE PUBLICACIONES

INTRODUCCIÓN
AL LENGUAJE
PASCAL

Manuel Collado
Ramón Galán
ÍNDICE

CAPÍTULO 1: INTRODUCCIÓN Pág.


1.1.- Concepto de programa...........................................................1
1.2.- Diagrama de flujo..................................................................3
1.3.- Programación estructurada.....................................................5

CAPÍTULO 2: INTRODUCCIÓN AL LENGUAJE PASCAL Pág.


2.1.- Uso de comentarios.............................................................11
2.2.- Valores enteros y reales.......................................................11
2.3.- Constantes enteras y reales..................................................12
2.4.- Operadores enteros.............................................................12
2.5.- Operadores reales................................................................13
2.6.- Expresiones aritméticas........................................................13
2.7.- Sentencias de escritura........................................................14
2.8.- Escritura de literales............................................................15
2.9.- Formato de un programa......................................................15
EJERCICIOS...............................................................................16

CAPÍTULO 3: VARIABLES Y FUNCIONES Pág.


3.1.- Identificadores....................................................................19
3.2.- Declaración de constantes.....................................................20
3.3.- Declaración de variables.......................................................21
3.4.- Funciones predefinidas.........................................................22
3.5.- Sentencia de asignación.......................................................23
3.6.- Sentencias de lectura...........................................................23
EJERCICIOS...............................................................................25

CAPÍTULO 4: VALORES BOOLEANOS Y ESTRUCTURAS DE CONTROL Pág.


4.1.- Constantes booleanas..........................................................27
4.2.- Variables booleanas.............................................................27
4.3.- Operadores booleanos..........................................................27
4.4.- Operadores de comparación..................................................28
4.5.- Funciones booleanas predefinidas..........................................28
4.6.- Asignación booleana............................................................29
4.7.- Sentencia IF.......................................................................29
4.8.- Sentencia WHILE..................................................................30
4.9.- Sentencia REPEAT................................................................30
4.10.- Estructuras combinadas......................................................31
EJERCICIOS...............................................................................32

-I-
CAPÍTULO 5: ESTRUCTURAS DE CONTROL SECUNDARIAS Pág.
5.1.- Sentencia FOR.....................................................................35
5.2.- Sentencia CASE....................................................................36
5.3.- Sentencia GOTO....................................................................37
EJERCICIOS...............................................................................39

CAPÍTULO 6: SUBPROGRAMAS Pág.


6.1.- Funciones...........................................................................41
6.2.- Procedimientos....................................................................42
6.3.- Llamada por valor y por nombre............................................43
6.4.- Símbolos locales y globales...................................................44
6.5.- Recursividad.......................................................................45
EJERCICIOS...............................................................................46

CAPÍTULO 7: MANEJO DE CARACTERES Pág.


7.1.- Valores de tipo carácter........................................................49
7.2.- Lectura y escritura de caracteres............................................49
7.3.- Funciones de caracteres.......................................................50
7.4.- Operaciones con caracteres...................................................51
EJERCICIOS...............................................................................53

CAPÍTULO 8: DEFINICIÓN DE NUEVOS TIPOS Pág.


8.1.- Enumeración.......................................................................55
8.2.- Operaciones con valores enumerados.....................................56
8.3.- Subrango...........................................................................57
EJERCICIOS...............................................................................59

CAPÍTULO 9: CONJUNTOS Pág.


9.1.- Concepto de conjunto...........................................................61
9.2.- Expresiones con conjuntos....................................................62
9.3.- Manejo de conjuntos............................................................63
EJERCICIOS...............................................................................64

CAPÍTULO 10: VECTORES Y MATRICES Pág.


10.1.- Declaración de vectores......................................................65
10.2.- Selección de componentes..................................................65
10.3.- Uso de matrices.................................................................66
10.4.- Manejo de vectores............................................................66
10.5.- Vectores de caracteres........................................................67
EJERCICIOS...............................................................................69

- II -
CAPÍTULO 11: REGISTROS Pág.
11.1.- Declaración de registros......................................................71
11.2.- Selección de componentes..................................................72
11.3.- Sentencia WITH..................................................................72
11.4.- Operaciones con registros...................................................73
11.5.- Registros variantes.............................................................75
EJERCICIOS...............................................................................77

CAPÍTULO 12: FICHEROS SECUENCIALES Pág.


12.1.- Declaración de fichero. Variable asociada...............................79
12.2.- Operaciones básicas con ficheros..........................................80
12.3.- Ficheros de caracteres........................................................81
12.4.- Ficheros predefinidos..........................................................82
12.5.- Ficheros externos...............................................................82
12.6.- Escritura con formato explícito.............................................83
EJERCICIOS...............................................................................84

- III -
INTRODUCCIÓN
1
El objeto del presente texto es introducir al lector de manera progresiva en el
conocimiento y manejo del lenguaje de programación PASCAL. En la redacción
se ha buscado la máxima sencillez posible, de manera que su lectura pueda ser
abordada incluso por quienes no han tenido ningún contacto anterior con los
computadores y su programación.

A lo largo de los sucesivos capítulos se van introduciendo uno tras otro diver-
sos conceptos, de manera gradual, de forma que cada uno de ellos represente
una pequeña aportación respecto a los anteriores. Esto permite ir asimilandolo
con comodidad, y al mismo tiempo se ha cuidado de que desde el principio se
puedan presentar programas completos como ejemplo, con lo que en todo mo-
mento se estará en condiciones de realizar ejercicios de prácticas en máquina.

1.1. Concepto de programa.

La idea de programa surge tras la aparición de máquinas automáticas, capaces


de realizar por sí solas operaciones más o menos complicadas sin necesidad de
intervención de un operador humano. El funcionamiento automático exige que
la máquina “sepa” en todo momento lo que ha de realizar.

Un programa es el conjunto de órdenes o instrucciones que gobiernan el fun-


cionamiento de la máquina, y que habrá de ser preparado antes de hacerla
funcionar. El programa a seguir por una máquina puede materializarse de muy
diversas formas; por el momento nos bastará con que las órdenes a cumplir se
puedan poner por escrito, de manera que un programa adoptará la forma de
un texto.

En la actualidad los programas destinados a ser ejecutados por un computador


se redactan en algún lenguaje especial. Los lenguajes adecuados para ello se
denominan lenguajes de programación, y entre ellos se encuentra el PASCAL,
que irá siendo explicado a lo largo de este texto.

En este apartado introduciremos la idea de programa empleando el lenguaje


natural, escribiendo órdenes de manera convencional. Más concretamente, la
clase de programas que nos interesa está formada por aquellos que adoptan la
forma de una lista ordenada de instrucciones, que han de realizarse secuen-
cialmente, una tras otra, en el orden que se indica.

Consideremos, para empezar, el siguiente programa de cálculo, extraordinaria-


mente sencillo, formado por tres instrucciones:

-1-
PROGRAMA 1.
1) Leer un número
2) Calcular su cuadrado
3) Imprimir el resultado

En este programa se supone que cada una de las instrucciones puede ser reali-
zada directamente por la máquina, por lo que no es necesario explicarlas me-
jor. Además es evidente que el orden de ejecución es fundamental ya que no
puede calcularse el cuadrado del número antes de leerlo, ni imprimir el resulta-
do antes de haberlo calculado.

Sólo en casos muy sencillos, como éste, un programa se compone de una se-
cuencia pura de instrucciones. Normalmente el orden de ejecución deberá ser
determinado por la propia máquina mientras opera, para lo cual el programa
deberá indicar cómo han de tomarse las decisiones, en caso de que las opera-
ciones a realizar dependan de resultados intermedios.

Sobre el ejemplo anterior, si el cálculo a realizar se cambia por el de la raíz


cuadrada, habrá que introducir instrucciones complementarias, ya que el resul-
tado sólo está definido si el dato de partida no tiene valor negativo. El progra-
ma modificado, incluyendo operaciones condicionales, podría ser:

PROGRAMA 2
1) Leer un número.
2) Si es negativo, imprimir “dato negativo” y parar
3) Calcular la raíz cuadrada
4) Imprimir el resultado

El orden de ejecución de las instrucciones no es fijo, sino que depende del va-
lor leído en cada caso. Unas veces se ejecutará la secuencia 1), 3) y 4), que
será lo normal; o bien se ejecutará 1) y 2), si no puede operarse con el dato
leído. En cualquier caso conviene resaltar que la acción a realizar está perfec-
tamente determinada por el programa, de manera que la máquina puede ope-
rar correctamente por sí sola.

Aunque el lenguaje natural puede ser suficiente para escribir con claridad pro-
gramas sencillos, como los expuestos, resultará inadecuado en cuanto las ope-
raciones sean algo más complicadas. Para evitar ambigüedades conviene em-
plear una notación más precisa, de tipo matemático.

En el resto de este capítulo emplearemos letras mayúsculas para hacer refe-


rencia a las variables numéricas, y usaremos el símbolo compuesto “:=” para
expresar que se asigna un valor a una variable. El PROGRAMA 2 se escribirá
como:

PROGRAMA 3
1) Leer N
2) si N<0, imprimir “dato negativo” y parar
3) R := √N
4) Imprimir R

-2-
1.2. Diagrama de flujo.

En el caso de programas que incluyen operaciones condicionales, la escritura


de las instrucciones en forma de una lista única no da una idea clara del orden
de ejecución, por tanto no refleja correctamente la estructura del programa.

Dicha estructura suele ser representada esquemáticamente mediante el llama-


do diagrama de flujo (“flow-chart”) compuesto por elementos de los tres tipos
siguientes:

Comienzo/fin Operación Decisión

El elemento más común es el rectángulo, que sirve para representar cualquier


operación. El comienzo y el final del programa se indican con el símbolo de for-
ma rectangular y lados semicirculares, y el rombo se emplea para representar
la toma de decisiones en que es elige una acción entre dos o más.

El flujo de ejecución se representa mediante líneas que enlazan los diferentes


elementos, y que pueden llevar flechas para indicar su sentido. Normalmente
el diagrama se trazará de manera que las operaciones se realicen de arriba a
abajo, o bien de izquierda a derecha.

El diagrama se completa escribiendo la operación correspondiente dentro del


símbolo de cada elemento. El diagrama correspondiente al PROGRAMA 3 sería
el siguiente:

-3-
Este diagrama refleja mucho mejor la estructura del programa e inmediata-
mente se ve que hay dos terminaciones posibles. No se han usado flechas ya
que el orden es el normal, de arriba a abajo y de izquierda a derecha.

La ventaja del diagrama de flujo respecto a una lista única de instrucciones re-
sulta más evidente al considerar programas más complicados, tales como el
ejemplo siguiente:

-4-
Sobre el diagrama pueden apreciarse las partes del programa que se repiten, y
las condiciones para que esto ocurra. El análisis completo se deja como ejerci-
cio. Como orientación, se indica que el programa calcula A := N 2 a base de su-
mar los números impares sucesivos hasta N + N – 1, como queda de manifies-
to en la figura que se acompaña. En este ejemplo se ha supuesto que las ope-
raciones simples permitidas son la puesta a cero, el incremento y la compara-
ción de variables.

1.3. Programación estructurada.

El análisis del ejercicio anterior, sin ser complicado, presenta algunas dificulta-
des. Entre otras, el comprender el funcionamiento de la parte central es com-
plicado, ya que la operación de incrementar la variable A se repite por dos ra-
zones diferentes. La “programación estructurada” tiene a construir programas
que sean fácilmente comprensibles, entre otras cosas. Se basa en la técnica de
diseño mediante “refinamiento progresivo”, en que las operaciones se conside-
ran inicialmente en forma global, para ir descomponiéndolas poco a poco en
otras más sencillas, hasta llegar a aquellas que pueden ser realizadas directa-
mente por la máquina.

Esta técnica de descomposición se traduce, a nivel de diagrama de flujo, en


que los bloques iniciales se detallan mediante estructuras que sólo tienen un
punto de entrada o comienzo y un sólo final. Las estructuras más sencillas que
cumplen esta condición son la secuencia, la selección y la iteración. Sus dia-
gramas de flujo son los siguientes:

A Si
A No
A No

Si

B B C B

Secuencia Selección Iteración

Estas construcciones básicas se designan en el texto del programa mediante


palabras especiales. Las que indicamos a continuación se toman del inglés, sin
traducción.

La secuencia es simplemente la ejecución sucesiva de dos o más operaciones.


La escribiremos en la forma BEGIN A,B END.

La selección consiste en realizar una u otra operación, dependiendo de una


condición dada. La escribiremos como IF A THEN B ELSE C.

La iteración es la repetición de una operación mientras se cumpla una condi-


ción dada. Se escribirá WHILE A DO B.

-5-
Aunque esta forma de iteración permite construir cualquier tipo de repeticiones
en un programa, suelen considerarse también como básicas otras variantes.
Entre ellas la que usa la condición para marcar el final, y no el principio, de las
repeticiones. Se representa en la forma:

A
REPEAT A UNTIL B

No
B
Si

Puesto que la representación escrita de estas estructuras, empleando las pala-


bras especiales, es bastante clara, el diagrama de flujo pierde parte de su im-
portancia. El texto del programa resulta especialmente claro y refleja muy bien
su estructura si las operaciones parciales se escriben adecuadamente encolum-
nadas. Por ejemplo, la estructura selección puede encolumnarse en la forma

IF A THEN
....B....
ELSE
....C....

permitiendo que B y C se escriban empleando cada una varias líneas, si es ne-


cesario.

Para ilustrar la técnica de diseño por refinamiento progresivo, mostraremos


cómo puede construirse el programa de cálculo del cuadrado de un número,
detallado al nivel del PROGRAMA 5, partiendo de la construcción inicial del
PROGRAMA 1. Las sucesivas operaciones parciales se numerarán de forma que
facilite el seguimiento de la descomposición.

PROGRAMA 6
10) Leer N
20) A := N2
30) Imprimir A

-6-
El primer paso es descomponer la operación 20) de acuerdo con la fórmula

N
N 2= ∑ ( K + K−1)
K=1

lo cual podemos conseguir de la siguiente forma:


21) A := 0
22) K := 0
23) REPEAT
20) A := N2
23.10) K := K + 1
23.20) A := A+K+K-1
UNTIL K = N

Todas las operaciones utilizadas son simples, excepto la 23.20), que descom-
pondremos en la forma:

23.21) A := A + K
23.20) A := A + K + K - 1
23.22) A := A + K - 1

y cada una de estas dos sumas parciales puede plantearse a su vez en forma
de operación iterativa:

23.21.10) I := 0
23.21.20) REPEAT

23.21) A := A + K 23.21.20.10) I := I + 1
23.21.20.20) A := A + 1
UNTIL I = K

23.22.10) J := 1
23.22.20) WHILE J < K DO
23.22) A := A + K - 1 23.22.20.10) J := J + 1
23.22.20.20) A := A + 1

Como resultado de estos sucesivos refinamientos o descomposiciones llegamos


finalmente a un programa que sólo contiene operaciones simples capaces de
ser realizadas directamente por la máquina que haya de ejecutarlo. Lo escribi-
remos prescindiendo de la numeración, y usando las palabras BEGIN, END
cuando sea necesario agrupar varias en un bloque único.

-7-
PROGRAMA 7
BEGIN
Leer N
A := 0
K := 0
REPEAT
K := K + 1
I := 0
REPEAT
I := I + 1
A := A + 1
UNTIL I = K
J := 1
WHILE J < K DO
BEGIN
J := J + 1
A := A + 1
END
UNTIL K = N
Imprimir A
END

El diagrama de flujo, marcado como PROGRAMA 8, puede compararse con el


PROGRAMA 5. El nivel de detalle es el mismo, pero la estructura es ahora algo
más clara.

(ver página siguiente)

-8-
PROGRAMA 8
COMIENZO

Leer N

A := 0

K := 0

K := K + 1

I := 0

I := I + 1

A := A + 1

No
I=K

Si

J := 1

No
J<K

Si

J := J + 1

A := A + 1

No
K=N

Si

Imprimir A

FIN

-9-
- 10 -
INTRODUCCIÓN AL LENGUAJE PASCAL
2
El texto de un programa en lenguaje PASCAL se compone de una serie de
elementos básicos (“palabras”) perfectamente diferenciados, que se agrupan
en frases o “sentencias”. A diferencia de otros lenguajes más conocidos, tales
como el FORTRAN o el BASIC, la descomposición del texto en líneas no tiene
ningún significado. El programa completo podría siempre escribirse como una
única línea suficientemente larga. Este formato libre se da también en
lenguajes como el ALGOL o el PL/I.

Los espacios en blanco entre los elementos del programa sirven para mejorar
su legibilidad, y pueden usarse con bastante libertad. Sin embargo hay una
diferencia con respecto al FORTRAN y BASIC en el sentido de que no son
totalmente superfluos, sino que en determinados casos es absolutamente
necesario utilizarlos para separar palabras que de otra manera aparecerían
confundidas como una sola; además no pueden emplearse entre las letras de
una palabra.

La fragmentación en líneas, por su parte, puede hacerse en cualquier parte en


que puedan intercalarse espacios en blanco. Un programa de varias líneas
resulta equivalente a otro de una sola línea obtenida colocándolas una tras otra
con un blanco entre ellas.

2.1. Uso de comentarios.

La mayoría de los lenguajes de programación dan facilidad para incluir


comentarios en el texto de un programa. Es muy recomendable utilizar
bastante esta posibilidad, que facilita enormemente la comprensión por parte
de otras personas, o incluso por el mismo autor si tiene que revisar el
programa al cabo de algún tiempo. El PASCAL permite emplear comentarios en
cualquier punto en que pudieran intercalarse espacios en blanco. El texto del
comentario ha de escribirse entre paréntesis y asteriscos, en la forma:
(* comentario *)

o bien, si el juego de caracteres las incluye, entre llaves “{”, “}”

2.2. Valores enteros y reales.

El lenguaje PASCAL permite operar con datos de diferentes tipos. Algunos de


estos tipos están predefinidos en el lenguaje, y otros pueden ser definidos por
el programador a su conveniencia. Entre los primeros se encuentran los valores
llamados enteros y reales.

- 11 -
Los valores enteros coinciden con el concepto matemáticos de los mismos,
salvo en lo que respecta a la limitación de rango de valores, debida a la
capacidad de almacenamiento predefinida de un computador determinado.
Dicho rango depende por tanto del equipo utilizado y es simétrico en torno a
cero. Dentro de dicho rango la representación de estos valores es exacta.

Los valores reales permiten operar con cantidades no necesariamente enteras,


que incluyan una parte fraccionaria. Tanto su rango como la precisión es
limitada, igual que en el caso de los enteros. La limitación de precisión hace
que estos valores sean en realidad sólo una aproximación de los deseados, y
este hecho es fundamental a la hora de comprender por qué este tipo de
valores no puede ser utilizado en los programas en la misma forma que los
demás datos simples.

2.3. Constantes enteras y reales.

Una constante entera se representa en la forma habitual como una serie de


cifras decimales, precedidas opcionalmente del signo más o menos. Son
constantes enteras válidas:

1 -2 003 +362 -0 12345 0 etc...

Las constantes reales se caracterizan por llevar punto decimal. Han de tener
alguna cifra decimal en la parte entera y en la fraccionaria, obligatoriamente.
Pueden ir seguidas de una potencia decimal que indique su rango, escrita como
exponente entero de 10 precedido de la letra E, inmediatamente a
continuación de la mantisa. En este caso si la mantisa no tiene parte
fraccionaria pueden omitirse, al tiempo que el punto decimal. Son constantes
reales:

2.4 0.0 436.0 0.02 3.4E5 -0.6E5 3E20 etc...

y en cambio no son constantes válidas:

23. -.003 1.23E-4. E15 -0.78E0.5

Además no pueden dejarse espacios en blando entre las cifras de una


constante.

2.4. Operadores enteros.

Las operaciones aritméticas básicas se indican de la siguiente manera:

- suma: a + b
- resta: a - b
- producto: a * b
- cociente: a DIV b
- resto: a MOD b

- 12 -
Siendo “a” y “b” dos valores enteros. Los tres primeros operadores se
representan con un solo símbolo. Los dos últimos, en cambio, mediante una
palabra de tres letras que debe escribirse exactamente como se indica, siendo
necesario, casi siempre, dejar un blanco delante y detrás.

Si los operandos y el resultado están dentro del rango de valores aceptable, el


resultado será exacto. Los operadores DIV y MOD están relacionados de manera
que se cumple siempre:

a = (a DIV b) x b + (a MOD b)

que corresponde a la regla aritmética habitual:

dividendo = divisor x cociente + resto

2.5. Operadores reales.

Las operaciones básicas se indican de la forma:


- suma: a + b
- resta: a – b
- producto: a * b
- cociente: a / b

siendo al menos uno de los dos valores a o b de tipo real. Los símbolos de los
tres primeros operadores coinciden con el de los enteros. El cuarto es
diferente, y suministra un resultado de tipo real incluso en el caso de que se
aplique a dos valores enteros.

Tal como se indicó al principio, los resultados de tipo real son solo
aproximaciones de los verdaderos, debido a la precisión limitada de la
representación interna de los números

2.6. Expresiones aritméticas.

Combinando varios operandos y operadores pueden escribirse expresiones


aritméticas de complejidad ilimitada. Pueden utilizarse paréntesis para indicar
el orden en que han de realizarse las operaciones parciales. En ausencia de
paréntesis el orden de operación es:
- 1º operadores multiplicativos: * / DIV MOD

- 2º operadores aditivos: + -
y dentro del mismo nivel las operaciones se ejecutan de izquierda a derecha.
Si una expresión va precedida del signo más o menos, se entiende que
corresponde precisamente al primer operando. Ejemplos sencillos de
expresiones podrían ser:

Área de un triángulo de base 5 y altura 2.7 (resultado real):


(5 + 2.7) / 2

- 13 -
Número de unidades contenidas en 50 cajas de 20 docenas (resultado
entero):
50 * 50 * 12
Importe de 400 unidades de producto, de precio unitario 23,5 con
una bonificación del 15% (resultado real).
400 * 23.5 * (1 – 0.15)

Es fácil comprender que toda expresión que contenga al menos un operando


real dará un resultado real. Sólo se obtendrá resultado entero si todos los
operandos son valores enteros y no se usa la división real /.

2.7. Sentencias de escritura.

Los valores de las expresiones aritméticas que se escriban pueden ser


impresos mediante las sentencias WRITE y WRITELN. Tanto una como otra
permiten imprimir cualquier número de valores, tanto enteros como reales. Los
resultados se imprimen uno tras otro en la misma línea, a continuación de los
anteriores, salvo que se use la sentencia WRITELN, en cuyo caso los siguientes
resultados que se mandan imprimir aparecerán en la línea siguiente. El
formato de estas sentencias es:

WRITE (expresión, expresión, etc …);

y lo mismo para la sentencia WRITELN. Esta última puede además escribirse


sin incluir ningún valor a imprimir, simplemente escribiendo

WRITELN;

y provocará que se deje en blando el resto de la línea de impresión.

Como los resultados se imprimen uno tras otro en la misma línea una
sentencia de escritura de varios valores es lo mismo que varias sentencias de
escritura seguidas, de un valor cada una. Si se usan varias sentencias seguidas
se escribirán separadas por punto y coma. La sentencia

WRITE ( e1, e2, … en);

es equivalente a

WRITE(e1); WRITE(e2); … WRITE(en);

y del mismo modo, la sentencia

WRITELN ( e1, e2, … en);

equivaldrá a

WRITE(e1); WRITE(e2); … WRITE(en); WRITELN;

- 14 -
Cada valor impreso con una sentencia de escritura ocupará un cierto espacio
en la línea de impresión que dependerá de la máquina que se utilice. En todo
caso será siempre suficiente para representar cada valor con toda la precisión
del computador. Todos los valores enteros ocuparán el mismo espacio, así
como todos los valores reales, con lo que se facilita el encolumnar los
resultados. El espacio reservado para un valor entero puede ser, sin embargo,
diferente del de un valor real.

2.8. Escritura de literales.

Una sentencia de escritura puede incluir textos que ayuden a identificar los
resultados que se impriman. Se escriben entre apóstrofos (‘), y aparecerán
como una expresión más. En la línea de impresión ocuparán exactamente el
número de caracteres que posean, cosas que ha de tenerse en cuenta para
encolumnar los valores. Para incluir un apóstrofo en un texto literal se le
escribe duplicado. Un ejemplo de escritura con texto sería:

WRITELN(‘AREA = ‘, (5 * 2.7) / 2);

2.9. Formato de un programa.

En un programa en PASCAL se distinguen dos partes diferentes; una primera


de declaraciones y otra segunda de órdenes a ejecutar.

La primera de ellas especificará al menos el nombre del programa, que será


una palabra de cualquier número de letras e irá precedido de la palabra clave
PROGRAM.

La parte ejecutable contendrá al menos una sentencia de escritura, o varias,


ya que carece de sentido un programa que no produzca resultados, e irá
precedida de la palabra clave BEGIN y terminará con la END. Al final del
programa se añadirá un punto.

A continuación se presenta un sencillísimo programa, pero que contiene todos


los elementos necesarios para ser compilado y ejecutado.

PROGRAM EJEMPLOSENCILLO;
(* este programacalcula e imprime el área de un triángulo de
base 5 y altura 2.7 *)
BEGIN
WRITE( AREA = ‘, (5 * 2.7) / 2);
END.

- 15 -
EJERCICIOS

1. Indicar cuáles, de entre las siguientes, son constantes enteras válidas y por
qué.
a) -123 e) 1 3 4
b) 14.25 f) 13E-01
c) 12 3 g) 1234
d) +240 h) 78.00000000

2. Indicar cuáles de entre las siguientes son constantes reales válidas y por
qué.
a) 12 e) -123
b) 13 E-12 f) 987E+18
c) 0.00 g) .243
d) 9876543 h) (* 12.34 *)

3. ¿De qué tipo son los resultados de las siguientes expresiones?


a) 123*-12
b) -123
c) 423 ** 3
d) 123 DIV 12.0
e) 24 MOD 2

4. ¿Cuál será el resultado de evaluar la expresión siguiente?

32.0 / 320 – 12 * 14.5 * 32 +(256 DIV( 3 DIV (2)))

5. ¿Cuál será el resultado impreso al ejecutar el siguiente programa?

PROGRAM PRIMERO ;
BEGIN
WRITELN (170 DIV 6 DIV 4 MOD 2)
END.

6. En el siguiente programa hay tres errores de codificación. Localícelos y


explíquelos.

PROGRAM SEGUNDO ;
(* 45/33.-12*)
BEGIN
WRITE( ‘DIA=45’,2(23-11.09));
WRITELN;
WRITE( ‘SOLUC=’, WRITE,45/33.-12*)
END.

- 16 -
7. Indíquese cómo y cuantas líneas imprime el programa siguiente:

PROGRAM TERCERO;
BEGIN
(* PRIMERA LINEA *)
WRITE( ‘LINEA 1’, 13 MOD 11);
(* SEGUNDA LINEA *)
WRITE( ‘LINEA 2’, 11 MOD 2);
(* TERCERA LINEA *)
WRITELN;WRITE(‘LINEA 3’, 1234 MOD 32);WRITELN;
WRITELN(‘LINEA 4’, 33 MOD 11)
END.

8. Escribir un programa para calcular el precio de un lapicero, sabiendo que un


lote de 19 cajas, de doce lapiceros por caja, cuesta un millón de pesetas.
Indicar el resultado en miles de pesetas.

9. Escribir un programa para calcular el volumen de una esfera de radio 10.

10. Escribir un programa para determinar el número de billetes de 5.000,


1.000, 500 y 100 pts. En que se descomponen 12.700 pesetas.

- 17 -
- 18 -
3
VARIABLES Y FUNCIONES

En el capítulo anterior se ha visto la manera de realizar cálculos e imprimir los


valores resultantes. Sin embargo la manera en que se ha hecho es muy
limitada, y no se ha visto la forma de guardar valores para continuar operando
con ellos más adelante, ni la forma de leer datos del exterior.

Estas últimas operaciones exigen el empleo de variables, que tienen el


significado algebraico habitual, y en PASCAL se representan mediante un
nombre que las identifica, y que por ello se denomina en general
“identificador”. El uso de identificadores se extiende a otros elementos de los
programas. El propio nombre del programa pertenece a esta clase de objetos,
así como los nombres de funciones matemáticas y de otros tipos.

3.1. Identificadores.

Los identificadores o nombres empleados en PASCAL pueden tener cualquier


número de caracteres. Deben comenzar por una letra del alfabeto y construirse
empleando a continuación letras o cifras. En un nombre no pueden utilizarse
caracteres especiales además de los mencionados.

Aunque un nombre puede ser tan largo como se desee, los compiladores sólo
atienden, en general, a un cierto número de caracteres de los mismos, por lo
que el efecto es como si su longitud fuese limitada a un cierto número de ellos.
La mayoría de las versiones del lenguaje exigen que todos los identificadores
se distingan entre sí por lo 8 primeros caracteres.

Otra limitación en el empleo de nombres es que no pueden coincidir con las


palabras clave propias del lenguaje. Además existen cierto número de
identificadores ya predefinidos para dar nombre a una serie de elementos de
uso frecuente, aunque, a diferencia de las palabras clave, pueden ser
redeclarados con otro significado distinto si el programador no hace uso del
elemento predefinido. La figura 3.1 contiene una lista de las palabras clave , y
la 3.2 la de los identificadores predefinidos.

Dado que un identificador, aparte de la obligación de comenzar por una letra,


puede contener cualquier combinación de letras y cifras, cuando se escriba
precedido o seguido de una palabra clave o constante numérica deberá estar
separado de ella por un espacio en blanco o por el cambio de línea.

- 19 -
AND ARRAY BEGIN CASE CONST DIV
DO DOWNTO ELSE END FILE FOR
FUNCTION GOTO IF IN LABEL MOD
NIL NOT OF OR PACKED PROCEDURE
PROGRAM RECORD REPEAT SET THEN TO
TYPE UNTIL VAR WHILE WITH
Figura 3.1.- Lista de palabras clave (reservadas)

ABS ARCTAN BOOLEAN CHAR CHR COS


EOF EOLN EXP FALSE GET INPUT
INTEGER LN MAXINT NEW ODD ORD
OUTPUT PACK PAGE PRED PUT READ
READLN REAL RESET REWRITE ROUND SIN
SQR SQRT SUCC TEXT TRUE TRUNC
UNPACK WRITE WRITELN
Figura 3.2.- Lista de identificadores predefinidos.

Como ilustración de las aplicaciones anteriores se presentan algunos ejemplos


de identificadores. Serían válidos:

LETRA HOY MES10 J5C23 BETA

No serían válidos, por alguna de las razones mencionadas:ç

LABEL I.B.M. 33P6 VAR NOT

Finalmente se enuncian algunos identificadores válidos, pero que han de ser


usados con precaución:
IDENTIFICADORUNO REAL AREAMAXIMA

por último, conviene mencionar que en el capítulo anterior se ha hecho uso ya


de un identificador. En efecto, el nombre del programa es un elemento de esta
clase, y debe seguir las reglas que se han indicado para construirlo.

3.2. Declaración de constantes.

Además de su uso como nombres de variables, el lenguaje PASCAL permite


usar nombres propios para las constantes significativas en un programa. Todas
las constantes a las que se desee dar un nombre particular han de ser
declaradas conjuntamente al comienzo del programa.

Cada declaración de constante es de la forma:

identificador = valor;

y las sucesivas declaraciones se separan una de otra mediante punto y coma.


La primera de ellas irá precedida de la palabra clave CONST. Un ejemplo de
declaración de constantes sería:

- 20 -
CONST UNMEDIO = 0,5;
UNDIA = 1;
UNASEMANA = 7;
UNMES = 31;
UNANNO = 376;
PI = 3.141592;
E = 2.7182818;

Es fácil darse cuenta de que cada constante lleva asociado el tipo de valor que
le corresponde y que viene impuesto por el de la constante numérica explícita
que figura en su declaración. Es importante no perder de vista este hecho para
comprender cómo se harán los cálculos de las expresiones aritméticas en que
intervengan.

Existe una constante entera predefinida, MAXINT, cuyo valor es el máximo


absoluto con el que se opera correctamente.

3.3. Declaración de variables.

La declaración de variables se realiza después de la de constantes. Todas las


variables se declaran simultáneamente. Por cada variable a utilizar se
especificará su nombre y tipo. Hasta el momento sólo se han mencionado dos
tipos de valores, enteros y reales, que se especifican mediante los
identificadores predefinidos INTEGER y REAL, respectivamente. Cada
declaración de variable tendrá la forma básica:

variable : tipo;

y las sucesivas declaraciones se separarán una de otra por punto y coma. En


una sola declaración pueden agruparse varias variables del mismo tipo de la
forma:

variable, variable, … : tipo;

y en cualquier caso la primera declaración irá precedida de la palabra clave


VAR.

El lenguaje PASCAL no permite especificar valores iniciales para las variables.


Por consiguiente no deberá realizarse ninguna consideración acerca del
contenido de las variables al comienzo del programa. En particular no se
garantiza que tengan valor cero. Además no hay variables predefinidas.

Un posible ejemplo de declaración de variables sería:

VAR AREA: REAL;


DIAS, MESES: INTEGER;
DIAMETRO, BASE, ALTURA: REAL;
SEMANAS: INTEGER;

- 21 -
3.4. Funciones predefinidas.

Por el momento consideraremos que una función es un valor o resultado que


se obtiene por cálculo a partir de otros valores de partida o argumentos. En
PASCAL, al igual que en otros muchos lenguajes de programación, ese valor a
obtener por cálculo se especifica escribiendo el nombre que identifica a la
función, seguido de los valores de los argumentos, separados por comas (si
son varios), entre paréntesis. Las funciones se estudiarán con más detalle en
el capítulo 6.

Una función puede aparecer en una expresión aritmética como un término


más. Además los valores de los argumentos pueden darse también en forma
de expresiones cualesquiera.

Cada función lleva asociado el tipo de valor que suministre, así como el del o
los argumentos con los que opere. En PASCAL existen predefinidas funciones
matemáticas de uso frecuente. La figura 3.3 contiene una lista de aquellas en
las que sólo intervienen valores enteros y reales.

Como puede observarse, el tipo de cada función está implícito en su nombre,


salvo la excepción de ABS y SQR en que depende del argumento. Otra
excepción es la de las funciones trigonométricas y similares, que aceptan
argumentos enteros o reales, indistintamente.

Función Valor calculado


Funciones enteras de argumento entero:
ABS(X) Valor absoluto de X
SQR(X) X elevado al cuadrado
Funciones reales de argumento real:
ABS(X) Valor absoluto de X
SQR(X) X elevado al cuadrado
Funciones reales de argumento real o entero:
SIN(X) Seno de X
COS(X) Coseno de X
ARCTAN(X) Arco tangente de X
LN(X) Logaritmo neperiano de X
EXP(X) ex
SQRT(X) Raiz cuadrada
Funciones enteras de argumento real:
TRUNC(X) Parte entera
ROUND(X) Valor entero más próximo

Figura 3.3.- Funciones predefinidas enteras y reales.

- 22 -
3.5. Sentencias de asignación.

La manera de almacenar resultados es usando la sentencia de asignación, que


permite registrar en una variable el resultado obtenido al evaluar una
expresión aritmética. El símbolo de asignación es la pareja de caracteres :=,
que han de escribirse exactamente así, en ese orden y sin espacio en blanco
entre ellos. La forma general de la sentencia de asignación es:

variable := expresión

y el significado es el habitual en todos los lenguajes de programación. La


expresión es evaluada, y a continuación se asigna su valor a la variable. Dicha
variable puede intervenir en la expresión, en cuyo caso se utiliza su valor
previo, que es sustituido por el nuevo después del cálculo.

Para que una sentencia de asignación sea válida es preciso, como regla
general, que el tipo de la variable y el de la expresión coincidan. La única
excepción es que un valor entero puede ser asignado a una variable real.

A continuación se indican algunos ejemplos de sentencias de asignación


válidas, empleando las constantes y variables definidas como ejemplo en los
apartados anteriores, así como las funciones predefinidas:

AREA := UNMEDIO * BASE * ALTURA;


AREA := PI * SQR( DIAMETRO / 2 );
DIAS := DIAS + MESES * UNMES;
SEMANAS := ROUND( DIAS / 7 );
BASE := 3; (* excepcional*)

y se deja al lector como ejercicio el comprobar por sí mismo que los tipos de
los términos, variables, expresiones, funciones y argumentos son válidos.

3.6. Sentencias de lectura.

Otra manera de asignar un valor a una variable es almacenando en ella un


dato tomado del exterior de la máquina. Para ello existe una sentencia de
lectura, con dos variantes, para controlar la lectura por líneas. Partiendo de la
línea de texto usada como dato, la sentencia

READ(variable)

tomará de dicha línea un valor numérico en forma de una serie de caracteres


que sigan las reglas de escritura de una constante numérica válida, y lo
asignarán a la variable indicada. Para ello se seguirá la correspondencia de tipo
entre el dato y la variable, igual que en una sentencia de asignación. Los
valores se van tomando de la línea de entrada, a medida que se ejecutan
sentencias de lectura, sin que se pierda ninguno. Cuando se agoten los valores
de la línea el computador provocará la lectura de otra nueva automáticamente.
Los valores sucesivos que han de ser leídos deberán separarse por espacios en

- 23 -
blando o cambios de línea. Las líneas de datos que sólo contengan blancos
serán ignoradas al leer valores numéricos.

Con una sola sentencia de lectura se pueden leer varios valores, y asignar cada
uno a una variable. Para ello bastará escribir:

READ(variable, variable, … )

Una segunda variante de la sentencia de lectura permite tomar uno o varios


valores de la línea de datos y forzar al mismo tiempo que se ignore el resdto
de la línea. Se escribirá en la forma:

READLN( v1, v2, … , vn )

que es equivalente a

READ(v1); READ(v2); … READ(vn); READLN;

y como puede verse, el número de valores a leer puede ser cero, en cuyo caso
simplemente provoca un salto a una nueva línea de datos.

- 24 -
EJERCICIOS

1. En la siguiente lista, hay palabras clave, identificadores predefinidos,


identificadores válidos e incorrectos. Distínganse unos de otros,
razonadamente.
VAR PESETAS
1VAR $DOLLARES
“VAR” OF
8VAR P6 TRES
PUT TRUNC
IN PROCEDURE
MAXINT 3.14159221781

2. Dado el siguiente programa:

PROGRAM CUARTO;
CONST MASA = 1000;
VAR VELOCIDAD, ENERGIA : REAL;
BEGIN
READLN(VELOCIDAD);
ENERGIA := MASA * SQR(VELOCIDAD);
WRITELN( ‘ENERGIA= ‘, ENERGIA);
END.

a) Señalar las palabras clave.


b) Señalar los identificadores.
c) Determinar las líneas de escritura, cuando la línea de texto usada
como dato es: 300000.00

3. Si en el ejercicio anterior se sustituye la sentencia WRITELN(… por las


siguientes:

WRITELN;
WRITE( ‘ ENERGIA = ‘ ,ENERGIA); WRITELN

¿Cómo será el resultado impreso?

4. Escribir un programa para calcular el volumen de una esfera. El valor del


radio se leerá como dato de entrada.

5. Escribir un programa para calcular, dado un número:


a) El valor absoluto.
b) El cuadrado.
c) El valor entero más próximo.
d) La raíz cuadrada.
El valor del número se leerá como dato. Los resultados se escribirán en
una sola línea, precedidos de un título.

6. Dado el programa:
- 25 -
PROGRAM QUINTO;
VAR A,B,C,D,E,F : INTEGER;
BEGIN
READ( F, D); READ( B); READLN; READLN( E,C,A);
WRITE(A,B), WRITELN; WRITELN(C,D);
WRITE(E);WRITE(F);WRITELN
END.

Y sabiendo que el resultado ha sido:


Línea 1.- 1 4
Línea 2.- 2 5
Línea 3.- 3 6
Determinar el formato de los datos de entrada.

7. El siguiente programa calcula valores para una función de tipo


trigonométrico. Determínese cuál es.

PROGRAM SEXTO;
VAR X,Y,A,B,C,D : REAL;
BEGIN
READLN(X);
A:=X; B:=A* A; C:= SIN(X); D := COS(X);
C:= C * A; D := D*D; Y:= C*D;
WRITE( ‘y = ’, Y);
END.

8. Escribir un programa para determinar la fuerza de atracción de dos masas.


Los valores de las masas y su distancia serán datos de entrada en una
sola línea.

9. Escribir un programa para determinar el entero más próximo al valor de la


función Y = A seno (wt). Los valores A, w y t son datos de entrada en
líneas diferentes.

10. Escribir un programa que lea un número real y escriba por separado
parte entera y parte fraccionaria.

- 26 -
ESTRUCTURAS DE CONTROL
4
Los valores enteros y reales son suficientes para realizar operaciones de
cálculo numérico de todo tipo. Sin embargo hasta este momento sólo se ha
visto la manera de escribir programas consistentes en una secuencia fija de
operaciones.

Para permitir la programación de acciones condicionales o iterativas se


empezará por introducir un nuevo tipo de valores que permiten expresar
condiciones lógicas.

4.1 Constantes booleanas.

El conjunto de valores de tipo booleano contiene sólo dos elementos, cierto y


falso. Estos valores se representan por las constantes predefinidas TRUE y
FALSE, respectivamente.

4.2 Variables booleanas.

Se declaran exactamente igual que las enteras o reales, utilizando el


identificador predefinido BOOLEAN para especificar este tipo de valores. Por
ejemplo, se podría escribir:

VAR TEST: BOOLEAN;

para declarar una variable lógica de nombre TEST.

4.3 Operadores booleanos.

El lenguaje PASCAL contiene operadores para especificar las operaciones


booleanas básicas de unión, intersección y complemento. Estos operadores se
representan por las siguientes palabras clave:

unión OR
intersección AND
complemento NOT

Los dos primeros operadores trabajan con dos valores booleanos. El tercero es
un operador unitario que se escribirá precediendo a un término único.

En cuanto a la jerarquía de estos operadores, que hay que tener en cuenta al


escribir una expresión lógica, el operador AND equivale a la multiplicación

- 27 -
numérica, y el OR tiene el mismo rango que la suma. El operador NOT, si
precede a una expresión, se entiende que afecta precisamente al primer
término.

4.4 Operadores de comparación.

Pueden obtenerse valores booleanos como resultado de comparar valores


numéricos. Para ello existen los siguientes operadores mixtos, con operandos
numéricos y resultado booleano.

Operador Significado
> Mayor que
< Menor que
= Igual a
>= Mayor o igual que
<= Menor o igual que
<> Diferente a

Los operadores de doble símbolo exigen que se escriban precisamente en ese


orden, y sin espacios en blanco entre ellos.

Los operadores de comparación pueden aplicarse también a los propios valores


booleanos. En ese caso se considera que existe la relación de orden estricto

FALSE < TRUE

Los operadores de comparación se evalúan con jerarquía inferior a los demás.


Por ello hay que tener cuidado al escribir expresiones aritméticas compuestas,
que pueden resultar erróneas aunque tengan un aspecto natural. Por ejemplo,
las expresiones:

4 > 7 OR 6 < 4
NOT 10 > 20

son erróneas y no serán aceptadas por el compilador. En su lugar habría que


escribir:

( 4 > 7 ) OR ( 6 < 4 )
NOT ( 10 > 20 )

4.5. Funciones booleanas predefinidas.

Por el momento mencionaremos sólo una función booleana, que se escribe:

ODD(X)

- 28 -
siendo X un valor entero, y cuyo resultado es TRUE si es impar y FALSE en caso
contrario.
También existe otra función predefinida, de uso muy general, y que puede ser
aplicado en particular a los valores booleanos convirtiéndolos en enteros. Se
trata de la función

ORD(X)

que da valor 0 si X es FALSE y valor 1 si X es TRUE.


En lenguaje PASCAL no pueden leerse o escribirse directamente valores
booleanos. En su lugar pueden utilizarse los valores enteros 0 y 1 como
representación externa de FALSE y TRUE, y utilizar en el programa las
funciones mencionadas para realizar la transferencia de tipo necesaria.

4.6. Asignación booleana.

La sentencia de asignación

variable := expresión

puede ser utilizada con valores booleanos, exigiéndose que tanto la variable
como la expresión sean del mismo tipo.

4.7. La sentencia IF.

Permite ejecutar condicionalmente una sentencia dependiendo de una


condición lógica. Su formato es:

IF b THEN s1 ELSE s2

y significa que si la expresión booleana b es cierta se ejecutará la sentencia s1,


mientras que si es falsa se ejecutará la s2. Si la acción a ejecutar en caso de
condición falsa es no hacer nada, se opitirá s2 y también la palabra clave ELSE,
escribiéndose sólo:

IF b THEN s

Como ejemplo sencillo consideremos que deseamos que una variable N cuente
cíclicamente de 0 a 9 cada vez que se ejecuta una parte del programa.
Escribiremos:

IF N=9 THEN N:=0 ELSE n:=N+1

cuyo significado es fácil de comprender.

Si las acciones correspondientes a las sentencias condicionadas son demasiado


complicadas como para poderlas expresar en una sentencia simple, se usará
en su lugar la forma de sentencia compuesta, consistente en una serie de
sentencias simples separadas por punto y coma y encerradas entre las

- 29 -
palabras clave BEGIN y END. Si en el ejemplo anterior añadimos otra variable N
que cuente a su vez las decenas, habría de escribirse, por ejemplo:

IF N=9
THEN
BEGIN
N:=0;
N:=N+1;
END
ELSE
N:=N+1;

Y resulta aconsejable, como en este ejemplo, escribir las sentencias largas y


complicadas en varias líneas en forma ordenada para facilitar su lectura.

4.8. Sentencia WHILE.

Esta sentencia tiene por objeto permitir la programación de operaciones


iterativas, en que una parte del programa se repite para lograr un resultado
global. El formato de esta sentencia es:

WHILE b DO s

donde b es una expresión booleana que indica una condición que ha de


cumplirse para que se ejecute, tantas veces como sea necesario, la sentencia
s, que puede ser simple o compuesta. Un ejemplo sencillo sería la
construcción:

WHILE M>=N DO M:=M-N;

que calcula, aunque sea en forma poco eficiente, el resto de la división de M


entre N, supuestos positivos.
Si la condición no se cumple la primera vez, la sentencia controlada no se
ejecuta nunca.

4.9. Sentencia REPEAT.

Otra forma de realizar operaciones iterativas es empleando esta sentencia, que


se diferencia de la anterior en que la parte de programa controlada por ella se
ejecuta siempre al menos una vez, y la condición marca el final, y no el
principio, de las ejecuciones. El formato general es:

REPEAT s1; s2; … UNTIL b

siendo b la expresión booleana que marca el final de las repeticiones, y s1, s2,
etc. una serie de sentencias cuya ejecución repetida se gobierna. En este caso
las palabras clave REPEAT, UNTIL además de indicar una operación iterativa
actúan en cierta manera como la pareja BEGIN, END que encierra una sentencia
compuesta.

- 30 -
Como ejemplo sencillo, la suma S de los K primeros número de obtendría
mediante el fragmento de programa:

S := 0;
N := 0;
REPEAT
N := N + 1;
S := S + N;
UNTIL N = K;

4.10. Estructuras combinadas.

Las sentencias cuya ejecución se controla dentro de un IF, WHILE, REPEAT, o


cualquier otra estructura de control, puede tener a su vez una estructura
condicional o iterativa. De esta manera se pueden escribir en forma casi
directa operaciones complicadas, combinando unas estructuras dentro de
otras.
Como ejemplo se presenta un programa para calcular e imprimir el máximo
común divisor de dos enteros, y que emplea todas las estructuras de control
presentadas hasta ahora.

PROGRAM MDC,
(* programa para obtener el máximo común divisor por el
algoritmo de Euclides *)
VAR
A, B, X : INTEGER;
BEGIN
READLN(A,B);
WRITE(‘EL M.C.D. De ‘,A,’ Y ‘,B);
IF (A<=0) OR (B<=0)
THEN WRITELN(‘ no existe ‘);
ELSE BEGIN (* algoritmo *)
WHILE A<>B DO
IF A<B
THEN BEGIN
X:=A;
A:=B;
B:=X;
END
ELSE REPEAT
A:=A-B;
UNTIL A<=B;
WRITELN(‘ es ‘,A);
END; (* algoritmo *)
END.

- 31 -
EJERCICIOS

1. Supuesto que se han ejecutado las siguientes líneas de programa indicar el


valor de las variables A, B, C, D y E.

PROGRAM SEPTIMO;
VAR A,B,C,D,D,E : BOOLEAN;
BEGIN
A := (8>7) OR (4<9);
B := NOT A AND ((9-1)=8);
C := (NOT A) AND (NOT B);
D := (1<2) OR (7>2) OR A;
E := A OR (C AND D);
END.

2. Las siguientes sentencias o expresiones son incorrectas, ¿por qué?

a) 3≠2
b) READ(A). ( A variable booleana ).
c) 8>4 AND 8<4
d) A := 1. ( A variable booleana ).
e) NOT(4)

3 Dado el siguiente programa:

PROGRAM OCTAVO;
VAR A,B,C,Y,X1,X2 : REAL;
BEGIN
(* SOLUC. ECUACION SEGUNDO GRADO *)
READLN(A,B,C);
Y := B*B-4*A*C;
IF Y<0 THEN WRITELN(‘SOLUC. IMPOSIBLE’)
ELSE
BEGIN
Y := SQRT(Y);
X1 := (-B+Y)/(2*A);
X2 := (-B-Y)/(2*A);
WRITELN(X1,X2);
END;
END.

Determinar el resultado impreso para las siguientes ternas de valores de


A, B y C:
1.- 3, 4 y 5.
2.- 1, -10 y 16.

4. Escribir un programa para ordenar tres número A, B y C que son enteros


positivos.

5. Escribir un programa para leer un número entero y escribirlo en forma en


forma invertida. Por ejemplo: 12345 = 54321.
- 32 -
6. El programa siguiente calcula el valor de una función discontinua;
determinar cuál es esta.

PROGRAM NOVENO;
VAR X : REAL;
Y : INTEGER;
BEGIN
READLN(X);
IF X<0 THEN Y:=0
ELSE
IF (X<0.333)
THEN Y := 1
ELSE
IF (X<0.666)
THEN Y := 2
ELSE Y := 3;
WRITELN(Y);
END.

7. Escribir un programa para calcular la raíz cuadrada de un número y


comparar el resultado con el calculado por la función “SQRT”. Utilice un
algoritmo de aproximación por búsquedas sucesivas, y una precisión de
una millonésima.

8. Dados dos número enteros N y D que forman la fracción N/D, escribir un


programa para reducirla a la forma más simple, es decir, obtener su
representante canónico.

9. Escribir un programa que calcule la raíz de la ecuación: lg X = 1 + 1/X


Se partirá de un valor inicial igual a 3 y una tolerancia dada.

10. Determinar cuál será el resultado impreso producido por el siguiente


programa:

PROGRAM DIEZ; CONST ONCE = 10; DOCE = 1; VAR A,B : INTEGER;


BEGIN l:=0; B:=DOCE; REPEAT WHILE A<ONCE DO BEGIN B:=B+A;
— – AQUI NO ES “l:=0” SINO QUE ES “A:=0” - -
A:=A+DOCE END; UNTIL A>=ONCE; WRITELN (‘A=’,A,’ B=’,B) END.

- 33 -
- 34 -
ESTRUCTURAS DE CONTROL SECUNDARIAS
5
Las sentencias de control expuestas en el capítulo anterior son las
fundamentales, de acuerdo con las ideas de la programación estructurada. Sin
embargo hay muchos casos en que el limitarse estrictamente a ellas conduce a
programas algo artificiosos, que resultarían más claros empleando otras
estructuras de control más adaptadas a cada caso particular.
En este capítulo se introducen nuevas construcciones para la estructura
iterativa, usando una índice, y para la de selección, mediante el empleo de vías
múltiples. Finalmente se aborda el uso de sentencias de salto de tipo general,
no estructurado.

5.1 Sentencia FOR.

Esta estructura de control permite programar la repetición de una parte del


programa variando cada vez el valor de un índice. Su forma básica es:

FOR i := vi TO vf DO s

siendo i una variable entera que sirve de índice, vi y vf los valores inicial y
final que ha de tomar dicho índice, respectivamente, y s la sentencia cuyas
repeticiones se controlan. Los valores límite pueden darse en forma de
expresiones enteras cualesquiera. La sentencia s puede ser simple o
compuesta. El incremento del índice de una repetición a otra será siempre la
unidad. Si el valor inicial es superior al final la sentencia s no será ejecutada
ninguna vez. El valor del índice después de la última repetición es
indeterminado.

Otra variante de esta sentencia permite utilizar el incremento en sentido


decreciente, disminuyendo el índice en una unidad cada vez. Se escribe:

FOR i := vi DOWNTO vf DO s

La sentencia FOR resulta adecuada para programar un número determinado de


repeticiones, y más aún si en ellas hay que procesar una serie de valores
seguidos. El ejemplo de suma de los K primeros número se escribirá ahora
muy sencillamente:

S := 0;
FOR N:=1 TO K DO
S := S + N;

con ventaja respecto a la forma adoptada en el apartado 4.9.

- 35 -
5.2. Sentencia CASE.

Es relativamente frecuente tener que anidar unas sentencias IF dentro de


otras, o bien escribir series de ellas seguidas, en caso de una decisión con
opciones múltiples y excluyentes entre sí. Para estos casos se dispone de una
sentencia especial de selección gobernada por un índice. La condición para
ejecutar la parte del programa correspondiente a una vía determinada será
que el índice tome un valor determinado. La forma básica de esta estructura
de programa es:

CASE e OF
valor: acción;
valor: acción;
.............
END

donde e será la expresión que determina el valor del índice, y los valores
particulares correspondientes a cada vía han de darse en forma de constantes.
La expresión usada como índice ha de ser del mismo tipo que las constantes
correspondientes a los valores particulares. Es aconsejable que dichos valores
seas contiguos, ya que la mayoría de los compiladores generan una tabla con
todos los valores comprendidos entre el mínimo y el máximo que se
especifiquen, incluyendo espacio para los que no se utilicen dentro de este
margen, que en caso de ocurrir provocarían la terminación del programa por
error, así como si la expresión toma cualquier otro valor no especificado. Cada
acción será una única sentencia, simple o compuesta.

El tipo de valor usado para índice puede ser cualquier valor simple, excepto
real. No tiene sentido, sin embargo, usar un valor booleano ya que la sentencia
IF es mucho más directa en este caso.

En caso de que para varios valores diferentes del índice haya de realizarse la
misma acción, no es necesario repetirla, sino que se adopta la forma de
escritura abreviada:

CASE e OF
.............
valor, valor, … : acción;
.............
END

Los valores particulares correspondientes a cada vía a seleccionar no tienen


por qué aparecer en orden, sino que es válido escribirlos uno tras otro de
cualquier manera, la que resulte más cómoda.

Un ejemplo ilustrativo de esta sentencia de control podría ser el siguiente.


Supongamos que en una empresa la jornada es de 8 horas los lunes, miércoles
y viernes; de 7 horas los marte y jueves, y de 4 horas los sábados. El cálculo
del total de horas laborables del año, prescindiendo de fiestas y suponiendo
que el primer día es lunes, sería:
- 36 -
HORAS:=0;
FOR N:=1 TO 365 DO
CASE N MOD 7 OF
1, 3, 5: HORAS := HORAS + 8;
2, 4: HORAS := HORAS + 7;
6: HORAS := HORAS + 4;
0: ; (* domingo *)
END;

siendo fácil comprender este ejemplo, que contiene además el caso particular
de posible valor del índice en que no hay que realizar ninguna acción, en cuyo
caso hay que reseñar dicho valor para que no dé lugar a condición de error,
pero acompañándolo de una sentencia nula como acción.

5.3. Sentencia GOTO.

Aun cuando no es aconsejable, en general, su empleo, el lenguaje PASCAL


permite usar saltos de forma no estructurada, empleando la sentencia GOTO,
existente en la mayoría de los lenguajes, y usando “etiquetas” en forma de
números de referencia para indicar los destinos de los saltos.

Los números de referencia usados como etiquetas han de ser enteros sin
signo. Algunos compiladores los limitan a cuatro cifras como máximo. En
cualquier caso han de ser declarados explícitamente antes de utilizarlos, al
comienzo del programa. La declaración de números de etiquetas, si la hay, ha
de preceder a la de constantes y variables, y estará situada, por tanto,
inmediatamente después de la especificación del nombre del programa. La
declaración será de la forma:

LABEL número, número, … ;

Estos números de referencia pueden colocarse, sólo una vez delante de una
sentencia del programa, en la forma:

número: sentencia;

y se puede ordenar un salto al comienzo de dicha sentencia mediante la orden

GOTO número;

siendo la expresión GOTO una palabra clave que ha de escribirse sin blancos
entre sus letras.

La sentencia GOTO puede ser utilizada para salir de una estructura de control,
pero nunca para entrar en ella desde fuera, sin pasar por su encabezamiento.
Este tipo de salto puede provocar acciones irregulares, aunque la mayoría de
los compiladores los admiten y algunos incluso no dan mensaje de advertencia.

Como ejemplo final se presenta un programa para obtener la función


exponencial por desarrollo en serie
- 37 -
x x x2 x3
e =1+ + + +... .
1! 2! 3!

y utilizándose en el programa sólo los 100 primeros términos, como máximo.

PROGRAM EXP;
(* este programa calcula ex por desarrollo en serie *)
LABEL 8;
VAR X,Y,Z,S: REAL;
N: INTEGER;
BEGIN
READLN(X);
Y:=1; Z:=1; S:=1;
FOR N:=1 TO 100 DO
BEGIN
Y:=Y*X/N;
S:=S+Y;
IF S=Z THEN GOTO 8;
Z:=S;
END;
8: WRITELN(X,S);
END.

En este ejemplo la variable S contiene la suma de la serie, Y el término a


sumar, y Z el valor anterior de la suma. La sentencia GOTO 8 detiene los
cálculos si el valor del término es tan pequeño que no provoca modificación
significativa de la suma, habida cuenta de la limitada precisión del computador.

- 38 -
EJERCICIOS

1. Indicar el valor final de S después de ejecutarse el siguiente grupo de


sentencias. Todas las variables son de tipo INTEGER.

S := 0;
FOR I:=122 TO 123 DO
FOR J:=122 DOWNTO I DO
FOR K:=121 TO J DO
FOR L:=1 TO 10 DO S:=S+L;

2. En el ejercicio anterior ¿cuántas veces se realiza la suma? Indicar los


sucesivos valores de las variables I, J, K y L.

3. Indicar el valor final de S después de ejecutarse el siguiente grupo de


sentencias. Todas las variables son de tipo INTEGER.

S:=0; FOR I:=101 TO 109 DO


CASE I MOD 4 OF
1,2 : S:=S-5;
3 : S:=S+5;
0 : CASE I OF
104 : S:=S-1;
108 : S:=S+1;
END;
END;

4. Indicar los valores de las variables I, J y K después de ejecutarse el


siguiente programa:

PROGRAM ONCE;
LABEL 11,22,33,44,55;
VAR I,J,K : INTEGER;
BEGIN I:=0; J:=0; K:=0;
11 : I:=I+1;
IF I<0 THEN GOTO 22 ELSE GOTO 44;
22 : J:=J+1; IF J<0 THEN GOTO 55;
33 : K:=K+1;
44 : I:=I-2; J:=J-2; K:=J-2; GOTO 11;
55 : END.

5. Escribir un programa para transformar un número entero en otro de


acuerdo a las siguientes reglas, que se aplicarán en el orden indicado.
a) Si el número no está comprendido entre 1 y 31 se transforma en -1.
b) Si el número es divisible por cualquier número natural anterior a él
mismo se transforma en 1.
c) Si el número no es divisible por cualquier número natural
comprendido entre él mismo y 31 se transforma en 2.
d) El resto se transforma en 3.

- 39 -
6. Escribir un programa para calcular los resultados de una estadística. Los
datos son uno por línea e indican:
1. Soltero
2. Casado
3. Viudo
4. Divorciado
-1. Fin de datos.
Imprimir los porcentajes correspondientes a los distintos estados.

7. Escribir un programa para listar las ternas de valores enteros que forman
triángulo rectángulo. En el listado cada línea será una terna con los valores
ordenados de menor a mayor. Se leerán dos valores que serán el menor y
el mayor de cualquier posible terna.

8. Escribir un programa para listar, en ocho columnas, los números primos


comprendidos entre dos valores que se leerán.

9. Sabiendo que el 1 de enero de 1981 fue jueves, diseñar un programa para


calcular el día de la semana de una fecha, expresada en forma de día y
mes, correspondiente al año 1981.

10. Escribir un programa para determinar la diferencia en días entre dos fechas
cualesquiera.

- 40 -
SUBPROGRAMAS
6
Los subprogramas son elementos fundamentales en todo sistema de
programación. Todos los lenguajes de uso general permiten la definición y
empleo de subprogramas.

El PASCAL, al igual que otros muchos lenguajes, permite utilizar


subprogramas. Un subprograma tiene por objeto realizar una acción
predeterminada al invocarlo. Si dicha acción es la obtención de un valor
numérico el subprograma se dice que es una función. Ya se han mencionado
ciertas funciones predefinidas en el lenguaje y la manera de usarlas.

Los subprogramas que no calculan un valor como resultado se denominan


procedimientos. La definición de funciones y procedimientos es muy
parecida. La manera de usarlos, en cambio, es diferente. En ambos casos el
subprograma se identifica por un nombre, y su acción puede depender de
datos o argumentos que se suministran al invocarlo.

6.1. Funciones.

Una función se define como un programa completo que calcula como resultado
un valor simple o escalar. La manera de producir el resultado es asignar ese
valor finalmente al identificador de la función, considerado como variable
especial.

Puesto que la función es un programa completo, tendrá todas las partes


mencionadas para un programa principal. Llevará un encabezamiento en que
se declara el nombre de la función, el tipo de resultado que produce, y los
argumentos, con sus tipos respectivos. La forma es:

FUNCTION nombre(arg:tipo, arg:tipo; … ): tipo;

donde el nombre de la función es un identificador, así como los de los


argumentos. Cada argumento va acompañado de una indicación de su tipo, y
el tipo del resultado de la propia función se escribe al final de todo. Si varios
argumentos seguidos son del mismo tipo, bastará escribirlo tras el último.

Tras este encabezamiento vendrá el programa de cálculo, que comprenderá la


declaración de etiquetas de salgo, constantes, etc, y finalmente la parte de
ejecución, compuesta por una secuencia de sentencias precedidas de la
palabra BEGIN y finalizando con END. Al final del END no se pone punto, ya que
ese punto final es sólo para marcar la terminación del programa completo. En
general, habrá al menos una asignación al identificador de la función.

- 41 -
Las funciones definidas por el programador se incluirán en el programa que las
vaya a usar, situando la declaración a continuación de las de variables, y antes
de la parte ejecutable. Si hay varias funciones se definirán seguidas, en
cualquier orden.

Una función puede usar otra como auxiliar. En este caso puede incluir su
definición dentro de ella misma. Otra posibilidad es que una función puede
usar las definidas anteriormente, en cuyo caso el orden de definición sí es
importante.Las funciones definidas en un programa se usarán en expresiones
aritméticas exactamente igual que las predefinidas. Al usar una función es
obligatorio que el número y tipo de argumentos suministrados coincida con el
de la definición.

El siguiente programa de ejemplo imprime una lista de triángulos rectángulos


cuyos lados son enteros y menores que 100.

PROGRAM TRIANG;
(* Programa para obtener todos los triángulos rectángulos
cuyos lados son enteros <= 100 *)
LABEL 3;
CONST LADOMAX=100;
VAR H,A,B,H2 : INTEGER;
FUNCTION SUMCUAD(N,M: INTEGER): INTEGER;
BEGIN
SUMCUAD:= N*N + M*M;
END; (* sumcuad *)
FUNCTION CUADRADO(I: INTEGER): BOOLEAN;
BEGIN
CUADRADO := I=SQR(SQRT(I));
END; (* cuadrado *)
BEGIN (* triang *)
FOR A:=1 TO LADOMAX DO
BEGIN
FOR B:=A TO LADOMAX DO
BEGIN
H2 := SUMCUAD(A,B);
H:= SQRT(H2);
IF H > 100 THEN GOTO 3
ELSE IF CUADRADO(H2)
THEN WRITELN(A,B,H);
END;
3: END; (* for a *)
END.

6.2. Procedimientos.

Son subprogramas en los que la acción principal no es el cálculo de un valor


numérico. Se definen en forma totalmente análoga a las funciones, excepto en
que no hay que declararles un tipo de valor determinado. El nombre del
procedimiento no puede ser usado como variable. Se les define con la palabra
PROCEDURE.

- 42 -
En PASCAL existen procedimientos predefinidos. Entre ellos se encuentran los
de lectura y escritura READ, READLN, WRITE y WRITELN que ya se han explicado.
En realidad son algo excepcionales en el sentido de que el número y tipo de los
argumentos es variable. En un procedimiento definido por el usuario los
argumentos empleados al usar el procedimiento deben coincidir con los de la
definición.

La manera de utilizar un procedimiento definido por el programador es,


análogamente a los predefinidos, escribir una sentencia con el nombre del
procedimiento seguido de sus argumentos entre paréntesis.

A continuación se presenta un ejemplo de procedimiento para imprimir valores


booleanos.

PROCEDURE WRITEB(B: BOOLEAN);


BEGIN
IF B THEN WRITE(‘true’)
ELSE WRITE(‘false’);
END;

La manera de usar el procedimiento será escribir una sentencia de la forma:

WRITE(valor)

siendo valor una expresión booleana cualquiera.

6.3. Llamada por valor y por nombre.

Al usar un subprograma los argumentos se pueden dar en forma de


expresiones. Dicha expresión es evaluada y el resultado se almacena en un
lugar donde operará con él el subprograma. En este caso se dice que el
argumento se pasa por valor.

El paso de argumento por su valor implica que si se usa el de una variable, en


realidad se saca una copia de él antes de que opere el subprograma. Si dicho
subprograma contiene sentencias que asignen nuevos valores a los
argumentos, ello no tendrá efecto sobre la variable del programa principal.

En ciertos casos es deseable que el subprograma pueda modificar las variables


que se usen como argumentos, lo cual permitirá producir varios resultados
numéricos, y no uno sólo. En este caso la variable usada como argumento hay
que pasarla por nombre, de manera que no se saque copia de ella, sino que
el subprogrma opere directamente sobre ella. La manera de conseguirlo es
usar el calificativo VAR delante de dicho argumento en el encabezamiento de la
función o procedimiento. Ello implica al mismo tiempo que siempre habrá de
usarse una variable en la posición de dicho argumento, que ya no podrá ser un
valor dado en forma de una expresión.
Un sencillo ejemplo sería:

- 43 -
PROCEDURE INCRE(VAR N: INTEGER);
BEGIN
N:=N+1;
END;

que al ser llamado en la forma:

INCRE(K)

produciría el mismo efecto que

K := K+1

cosa que no sería posible en la llamada por valor, en la que el valor de K no


podría ser modificado por el procedimiento.

6.4. Símbolos locales y globales.

Aunque no se haya usado en los sencillos ejemplos expuestos, un


subprograma puede contener definiciones de constantes, variables, etc. Dichos
elementos tienen un sentido local, de manera que no son accesibles desde el
exterior, es decir, desde el programa que utilice el procedimiento.

Por el contrario, los elementos definidos en el programa principal pueden ser


usados por el subprograma, a menos que haya empleado nombre idénticos
para sus definiciones locales. Esta es otra manera en que un subprograma
puede producir resultados secundarios, asignando valores directamente a las
variables del programa principal que lo utiliza.

Un programa en PASCAL se dice que tiene estructura de bloques. El concepto


de bloque coincide con el de programa o subprograma. La figura 6.1 contiene
una representación simbólica de la estructura de un programa de ejemplo, con
indicación de a qué elementos se puede acceder desde cada bloque.

Bloque Puede acceder a


A B
A A
C
B B, A
D
C C, B, A

E D D, C, B, A

F E E, A

G F F, E, A

G G, E, A

Figura 6.1.- Acceso a elementos de distintos bloques.

- 44 -
6.5. Recursividad.

Se dice que un subprograma es recursivo cuando se utiliza a si mismo.

La recursividad da una gran potencia a los lenguajes que la utilizan, aunque al


programar hay que tener en cuenta que resulta algo costosa en términos de
memoria ocupada y tiempo de ejecución, por lo que debe evitarse cuando
exista otra solución no recursiva de similar dificultad.

Un ejemplo típico de función recursiva es la siguiente, que calcula el factorial


de un número entero no negativo.

FUNCTION FACTORIAL(N: INTEGER): INTEGER;


BEGIN
IF N<=1 THEN FACTORIAL := 1
ELSE FACTORIAL := N * FACTORIAL(N-1);
END;

En este caso hubiera sido preferible adoptar una solución no recursiva


igualmente sencilla, como por ejemplo:

FUNCTION FACTORIAL(N: INTEGER): INTEGER;


VAR I:INTEGER;
BEGIN
FACTORIAL:=1;
FOR I:=2 TO N DO
FACTORIAL := FACTORIAL * I;
END;

- 45 -
EJERCICIOS

1. La siguiente lista de definiciones de funciones incluye algunos errores.


Localícense.
a) FUNCTION ( ARG1, ARG2 : INTEGER) : REAL;
b) FUNCTION CUBO( NUMERO) : INTEGER;
c) FUNCTION CUADRADO(NUMERO : INTEGER, ‘UNO’) : REAL;
d) FUNCTION CUADRADO( NUMERO) : REAL;
e) FUNCTION UNO(A :REAL, B : INTEGER : BOOLEAN ;

2. Decir cuáles de los argumentos se pasan por valor o por nombre, en las
siguientes definiciones de subprogramas.

a) PROCEDURE PAGINA( VAR A :REAL);


b) PROCEDURE PAGINA( A : REAL);
c) PROCEDURE PAGINA( A: INTEGER, VAR B :BOOLEAN);
d) PROCEDURE PAGINA(A,B,C);
e) PROCEDURE PAGINA;

3. Modificar los ejercicios 5.9 y 5.10 usando subprogramas.

4. Escribir un subprograma para calcular el área de un triángulo; los valores de


los lados serán los argumentos.

5. Escribir un procedimiento que calcule las potencias negativas de cos.

6. Escribir una función que determine el número de cifras que contiene un


número entero pasado como argumento.

7. Escribir un subprograma para comprobar la validez de una fecha dada en


forma dd,mm,aa.

8. (Problema de las torres de Hanoi). Se dan tres barras verticales y N discos


de diferentes tamaños. Los discos pueden apilarse sobre las barras
formando “torres”. Se suponen los N discos colocados inicialmente en la
primera barra A en orden de tamaño decreciente. La tarea a realizar es
mover los N discos desde la barra A hasta la tercera C, de forma que
queden ordenados de la misma forma inicial. Esto debe realizarse bajo
las siguientes restricciones:
a) En cada paso se mueve exactamente un disco desde una barra a
otra.
b) En ningún momento puede situarse un disco encima de otro más
pequeño.
c) Puede utilizarse la barra central B como almacén auxiliar.
Diseñar un programa recursivo. El número N es dato de entrada.

- 46 -
9. La siguiente función calcula los números de Fibonacci, que se definen por la
relación de recurrencia:

fibn+1 = fibn + fibn-1 para n>1

fib1 = 1 y fib0 = 0

Estudiar por qué este algoritmo no resulta eficiente y escribir uno que lo
sea.

FUNCTION FIB( N : INTEGER) : INTEGER;


BEGIN
IF N = 0 THEN FIB := 0
ELSE IF N = 1 THEN FIB := 1
ELSE FIB := FIB(N-1) + FIB(N-2);
END;

10. Escribir un procedimiento para encontrar el número primo más próximo


por exceso y por defecto, de un número dado.

- 47 -
- 48 -
MANEJO DE CARACTERES
7
Hasta el momento sólo se han podido usar caracteres en un programa en las
sentencias de escritura, como rótulos aclarativos. Existe además la posibilidad
de almacenar caracteres en variables, y operar con ellos.

7.1. Valores de tipo carácter.

A los anteriores tipos de valores, INTEGER, REAL y BOOLEAN, añadiremos otro


nuevo, correspondiente a un carácter, que se designará con el identificador
CHAR. Las constantes de este valor se escribirán poniendo el carácter entre
apóstrofos (‘), es decir, con la misma notación empleada en los literales de las
sentencias de escritura, pero con un símbolo único. Si el valor es precisamente
el apóstrofo, se le escribe duplicado.

Son ejemplos válidos de tipo carácter:

‘A’ ‘X’ ‘-’ ‘5’ ‘ ’(blanco) ‘‘’’(apóstrofo) etc. …

Se pueden declarar constantes con nombre y variables de tipo carácter en la


forma habitual, por ejemplo:

CONST PUNTO = ‘.’;


BLANCO = ‘ ‘;
VAR C, X : CHAR;

A las variables de tipo carácter se les pueden asignar valores en la misma


forma que a las de otros tipos.

7.2. Lectura y escritura de caracteres.

Las variables y constantes de tipo carácter pueden aparecer en las sentencias


de lectura y escritura. En el caso de la escritura el efecto ya es conocido. En
loa lectura se tomará el siguiente carácter de la línea de datos, sea cual sea, y
ese valor se asignará a la variable especificada. Por ejemplo, la sentencia:

READ(A,B,C)

siendo A, B y C variables de tipo CHAR, y con una línea de datos:

3.6

provocará que se hagan:

- 49 -
A = ‘3’ B = ‘.’ C = ‘6’

suponiendo que el 3 sea el primer carácter disponible. Al leer o escribir


caracteres los espacios en blanco cuentan igual que los demás caracteres.

7.3. Funciones de caracteres.

Se dispone de varias funciones predefinidas para operar con caracteres. Una de


ellas, la función ORD, ya a sido mencionada. Dicha función devuelve un valor
entero correspondiente al número de orden del carácter dentro del juego de
caracteres que acepte el computador, siendo este resultado dependiente de la
máquina que se utilice.

En cualquier caso el lenguaje PASCAL garantiza que las letras del alfabeto
poseen ordinales consecutivos, en el orden alfabético habitual, al igual que los
dígitos numéricos en el orden de sus valores. Llamando n al ordinal de la A y m
al ordinal del carácter 0 (cero), se cumplirá:

ORD(‘A’) = n
ORD(‘B’) = n+1
....
ORD(‘Z’) = n+25
ORD(‘0’) = m
ORD(’1’) = m+1
....
ORD(‘9’) = m+9

pero no hay ninguna garantía de relación entre n y m y entre ellos y los


ordinales de los demás caracteres.

Existe una función inversa de la ORD cuyo nombre es CHR. Su argumento es un


valor entero y el resultado un carácter, el que le corresponde. Con la notación
anterior, será:

CHR(n) = ‘A’
CHR(n+1) = ‘B’
etc.

Otras funciones que pueden ser utilizadas con caracteres son PRED y SUCC, que
suministran respectivamente el carácter anterior y el siguiente a uno dado. En
realidad estas funciones son muy generales, y pueden usarse con valores de
cualquier tipo, excepto los reales. Las funciones PRED y SUCC están
relacionadas con las ORD y CHR en la forma:

PRED(x) = CHR(ORD(x)-1)
SUCC(x) = CHR(ORD(x)+1)

- 50 -
7.4. Operaciones con caracteres.

Aparte de las funciones mencionadas, no existen operadores que generen


caracteres. Una expresión aritmética cuyo resultado sea de tipo carácter será
necesariamente una constante, una variable o una referencia a función, a ese
tipo.

La sentencia de asignación puede ser utilizada para dar valores a una variable
de tipo carácter, en la forma habitual.

Los únicos operadores que pueden utilizarse con caracteres son los de
comparación, siendo el resultado el mismo que comparando sus ordinales.
Usando estos operadores se determina si dos caracteres coinciden, por
ejemplo, o si están en orden alfabético. Así, darán resultado TRUE las
expresiones:

‘C’ >= ‘D’


‘9’ > ‘7’

y darán valor FALSE las:

‘+’ = ‘-’
‘X’ > ‘Y’

mientras que el resultado de expresiones tales como:

‘3’ < ‘A’

dependerá del equipo que se utilice.

En bastantes casos la transformación de caracteres exigirá operar con sus


ordinales, explícitamente. Por ejemplo, las siguientes funciones permiten
convertir un dígito numérico en el valor asociado, y viceversa.

FUNCTION VALOR(D: CHAR): INTEGER;


BEGIN
IF (D<’0’)OR(D>’9’)THEN
VALOR:=-1
ELSE VALOR := ORD(D) – ORD(‘0’);
END;

FUNCTION DIGITO(N: INTEGER): CHAR;


BEGIN
IF(N<0) OR (N>9) THEN
DIGITO:= ‘?’
ELSE DIGITO:= CHR(ORD(‘0’)+N);
END;

Los valores de tipo carácter pueden ser usados como índice en sentencias FOR
y CASE. La sentencia:

- 51 -
FOR C := ‘A’ TO ‘Z’ DO
WRITELN( C, ORD(C) );

imprimirá las letras del alfabeto acompañadas de sus respectivos ordinales.

Otro ejemplo sería:

PROGRAM CALCULO;
VAR X,Y,X: REAL; OP: CHAR;
BEGIN
READ(X);
REPEAT READ(OP) UNTIL OP<>’ ‘;
READ(Y);
CASE OP OF
‘+’: Z:=X+Y;
‘-’: Z:=X-Y;
‘*’: Z:=X*Y;
‘/’: Z:=X/Y;
END;
WRITELN(X,OP,Y,’=’,Z);
END.

cuyo análisis puede ser realizado como ejercicio.

- 52 -
EJERCICIOS

1. Escribir un subprograma para convertir un número Hexadecimal a su


equivalente decimal.

2. Escribir un subprograma que lea 100 caracteres, y determine el número de


veces que aparece uno determinado leído previamente.

3. Escribir una función que lea N caracteres y devuelva, según el orden


alfabético, el menor carácter de los leídos.

4. Se trata de cifrar un mensaje. Para ello se sustituirá cada carácter por un


número resultante de la función n=64-ordinal (carácter): Escribir un
procedimiento para ello y otro para descifrar mensajes.

5. Escribir un segmento de programa para leer palabras en el fichero de


entrada y:
• Formar su plural (simplificado) añadiendo una “s”.
• Dejar sólo un blanco de separación entre las palabras resultantes.
El final viene dado por el carácter punto (.).

6. Escribir un programa que lea un texto comprimido en el fichero de entrada y


escriba el texto correctamente. Se han usado los siguientes caracteres
especiales:
/ : indica punto y aparte.
XX: XX es un número entero y fija el tabulador.
El resto de las líneas se escribirán a partir de la columna XX.
La línea de texto es de 80 caracteres. Las palabras pueden dividirse por
cualquier sitio, vienen separadas por blancos y los signos de puntuación
forman parte de la palabra anterior.
El final del texto se marca con un asterisco “*”.

7. Escribir un programa que lea un texto y determine el número de palabras


que tiene. Cada palabra está separada por uno o más blancos. El texto
termina con un punto decimal (.).

8. Escribir un programa que cuente el número de letras y dígitos en una


entrada de datos. El final se indica con el carácter punto.

9. Escribir un programa para calcular el valor decimal de un número entero


positivo, escrito en base 26. Para la representación del número se utilizan
exclusivamente los caracteres de la ‘A’ a la ‘Z’, correspondiendo a la ‘A’ el
valor 0 y a la ‘Z’ el valor 25. El número se leerá del fichero de entrada.
Un carácter en blanco indica el final del número.

10. Escribir un programa para calcular el valor decimal de un número romano


inferior a 3000. Un carácter en blanco determina el final del número.

- 53 -
- 54 -
DEFINICIÓN DE NUEVOS TIPOS
8
Se denominan tipos escalares a los que toman valores simples. En PASCAL
existen los tipos escalares predefinidos ya mencionados INTEGER, REAL,
BOOLEAN y CHAR. Otros tipo sde valores pueden ser definidos por el
programador en la forma que se indica en los apartados siguientes.

8.1. Enumeración.

Para definir nuevos tipos de valores, en forma abstracta, se usará un


identificador para designar cada posible valor, y otro para designar el nuevo
tipo. Las definiciones de nuevos tipos se realizan todas seguidas entre las de
constantes y las de variables. La primera de ellas irá precedida de la palabra
clave TYPE.

La forma general de una definición por enumeración es:

tipo = (valor, valor, … )

donde el tipo y los valores son identificadores que los representan. Cada uno
de los identificadores de valores queda al mismo tiempo declarado como
constante. Ejemplos de estas definiciones serían:

TYPE COLORPRIMARIO = (ROJO, AMARILLO, AZUL);


SEXO = (VARON, MUJER);
DIADELASEMANA = (LUNES, MARTES, MIERCOLES, JUEVES,
VIERNES, SABADO, DOMINGO);

Tras la definición del tipo pueden declararse variables de esa naturaleza, y


operar con ellas. Por ejemplo, declarando:

VAR HOY: DIADELASEMANA;

se podrán escribir asignaciones tales como:

HOY := VIERNES;

y similares.

La enumeración implica al mismo tiempo la ordenación de los valores de un


tipo. Las funciones ORD, PRED y SUCC son aplicables a esta clase de valores, con
el significado ya conocido expuesto al hablar de los caracteres. El ordinal del

- 55 -
primer elemento de la lista de valores es cero. En los ejemplos anteriores se
cumplirá que:

ORD(ROJO) = 0
PRED(VIERNES) = JUEVES
SUCC (LUNES) = MARTES

Es evidente, de acuerdo con las explicaciones anteriores, que la declaración:

TYPE BOOLEAN = (FALSE, TRUE);

coincide con la definición implícita de este tipo de valores.

8.2. Operaciones con valores enumerados.

Los tipos definidos por enumeración permiten operar de manera similar a la


expuesta para el caso de los caracteres. Las únicas expresiones aritméticas
posibles serán una constante, una variable o una referencia a las funciones
PRED y SUCC.

Usando las definiciones del apartado anterior, se podrá escribir:

IF HOY=DOMINGO THEN HOY := LUNES


ELSE HOY := SUCC(HOY);

para pasar de un día de la semana al siguiente. También pueden usarse estos


valores en índices de sentencias FOR y CASE. El ejemplo del apartado 5.2 puede
reescribirse como:

HORAS:=0; HOY:=DOMINGO;
FOR N:=1 TO 365 DO
BEGIN
IF HOY=DOMINGO
THEN HOY:=LUNES
ELSE HOY:=SUCC(HOY);
CASE HOY OF
LUNES, MIERCOLES, VIERNES: HORAS:=HORAS+8;
MARTES, JUEVES : HORAS:=HORAS+7;
SABADO : HORAS:=HORAS+4;
DOMINGO : ;
END;
END;

Las sentencias de lectura y escritura no permiten emplear valores definidos por


enumeración. Para dichos valores deberá establecerse una representación
externa adecuada y programar explícitamente la transformación entre esa
representación externa y el valor interno correspondiente. Esto mismo ha de
hacerse también para los valores booleanos.

- 56 -
Siendo N una variable entera y B una booleana, se puede leer indirectamente
un valor booleano representado externamente por cero o uno mediante la
secuencia

READ(N); B:= N=1;

En el caso del ejemplo de los días de la semana, usando como representación


externa las mismas palabras LUNES, MARTES, etc. empleadas también como
identificadores simbólicos de los valores, puede usarse el siguiente
procedimiento para discriminar entre ellas y devolver el valor correspondiente:

PROCEDURA LEEDIA(VAR DIA: DIADELASEMANA);


CONST BLANCO = ‘ ‘;
VAR C: CHAR;
BEGIN (* saltar blancos iniciales *)
REPEAT
READ(C);
UNTIL C<>BLANCO;
CASE C OF (* letra inicial *)
‘l’ : DIA:=LUNES;
‘M’ : BEGIN
READ(C);
IF C=’A’ THEN DIA:=MARTES
ELSE DIA:=MIERCOLES;
END;
‘J’ : DIA:=JUEVES;
‘V’ : DIA:=VIERNES;
‘S’ : DIA:=SABADO;
‘D’ : DIA:=DOMINGO;
END;
(* saltar el resto de la palabra *)
REPEAT
READ(C);
UNTIL C=BLANCO;
END;

8.3. Subrango.

Otra manera de especificar nuevos tipos de valores es acotando parte del


rango de variación de otro tipo ya definido, en la forma:

vmin..vmax

siendo vmin y vmax constantes del tipo original, tales que

vmin < vmax

y los dos puntos entre ellos se escriben seguidos, sin blanco intercalado. No
pueden definirse subrangos del tipo REAL.

Son definiciones válidas, basadas en ejemplos anteriores:

- 57 -
TYPE DECIMAL = 0..9;
LETRA = ‘A’..’Z’;
LABORABLE = LUNES..VIERNES;

Las variables de un tipo declarado como subrango tienen la consideración de


variables del tipo base, y como tales pueden aparecer en expresiones
aritméticas y sentencias de asignación. Por ejemplo, las declaraciones:

VAR D: DECIMAL;
INICIAL: LETRA;
LAB: LABORABLE;

harán que la variable D sea considerada como entera, INICIAL como carácter y
LAB como día de la semana. Es válido, por tanto, escribir las sentencias:

D := 28-25;
READ(INICIAL);
LAB := PRED(JUEVES);

La ventaja principal de usar subrangos explícitos es que cada vez que se


asigna valor a una variable de ese tipo se comprueba que está dentro del
rango declarado. De no ser así el programa termina inmediatamente con una
indicación de error.

En algunos casos resulta engorroso tener que dar nombres particulares a los
subrangos. La especificación puede hacerse directamente al declarar las
variables. Los ejemplos anteriores se podrían haber escrito también en la
forma:

VAR D: 0..9;
INICIAL: ‘A’..’Z’;
LAB: LUNES..VIERNES;

con resultados equivalentes.

- 58 -
EJERCICIOS

1. Utilizando la definición de tipo subrango crear los tipos de variables:


DIASEMANA, MESES, DIGITO, SIGLOXV, HORASDIA.

2. Definir por enumeración y subrango la variable MESES y escribir un segmento


de programa que pase automáticamente la variable MESES al valor
siguiente.

3. Determinar el resultado de asignar las siguientes expresiones a la variable:


A: -2..5;

a) 3 – SUCC (1) – PRED (SUCC (PRED (2)))


b) SUCC (PRED (SUCC (PRED (PRED (0)))))
c) SUCC (ORD (‘A’))) + 23 – PRED (A)
d) PRED (SUCC (4))

4. Determinar el resultado impreso por el siguiente programa:

PROGRAM DOCE;
TYPE NUMERO = (AZUL,ROJO,VERDE,MARRON,BLANCO,NEGRO);
VAR N: NUMERO;
I,J: INTEGER;
BEGIN
J:=0;
N:=AZUL;
FOR I:=1 TO 5 DO
BEGIN
J:=J+ORD(N);
N:=SUCC(N);
END;
WRITELN(‘J= ‘,J);
END.

- 59 -
5. Determinar el resultado impreso por el siguiente programa, así como los
sucesivos valores de la variable TONO.

PROGRAM TRECE;
TYPE COLOR=(BLANCO, VERDE,AZUL,ROJO,NEGRO);
VAR TONO: COLOR;
CTONO: INTEGER;
BEGIN
TONO:=AZUL;
CTONO:=0;
REPEAT
CASE TONO OF
BLANCO,NEGRO : BEGIN
CTONO:=CTONO+1;
TONO:=AZUL;
END;
VERDE : BEGIN
CTONO:=CTONO+2;
TONO:=PRED(TONO);
END;
AZUL,ROJO : BEGIN
CTONO:=CTONO+3;
TONO:=SUCC(TONO);
END;
END;
UNTIL CTONO>15;
WRITELN(‘CONTROL DE TONO: ‘,CTONO);
END.

6. Escribir un procedimiento que transforme los datos de entrada en valores de


la variable TONO definida en el ejercicio anterior. Los datos serán enteros
comprendidos entre 0 y 4. La lectura se realizará en el procedimiento.

- 60 -
CONJUNTOS
9
Todos los tipos de valores utilizados hasta el momento se denominan
escalares, y son valores simples, en el sentido de que no pueden
descomponerse. En este capítulo y los siguientes se introducirán nuevos tipos
de valores estructurados, compuestos de otros valores más simples.

9.1. Concepto de conjunto.

Los conjuntos utilizables en PASCAL han de definirse sobre un referencial, que


ha de ser el conjunto de valores de un tipo escalar previamente definido que
sirva como base. Los conjuntos son en realidad subconjuntos de ese universal.
Tomando como ejemplo el tipo escalar de base:

TYPE COLORPRIMARIO = (ROJO, AMARILLO, AZUL);

los conjuntos definidos sobre él en la forma:

COLOR = SET OF COLORPRIMARIO;

podrán tomar uno de los siguientes varlores:

[]
[ROJO]
[AMARILLO]
[AZUL]
[ROJO, AMARILLO]
[ROJO, AZUL]
[AMARILLO, AZUL]
[ROMO, AMARILLO, AZUL]

El primer elemento de la lista corresponde al conjunto vacío, sin ningún


elemento. Los tres siguientes son conjuntos singulares, con sólo un elemento.
No hay que confundir el conjunto singular con el valor simple del tipo base, es
decir, no es lo mismo el valor simple AZUL que el conjunto [AZUL] que sólo
contiene dicho elemento. El último conjunto de la lista es el referencial o
universal, que contiene todos los elementos posibles.

Una vez definido el tipo de conjunto, pueden declararse variables de ese tipo,
tales como:

VAR PINTURA: COLOR;

o bien declarar el tio de conjunto al tiempo que la variable:


- 61 -
PIGMENTO: SET OF COLORPRIMARIO;

En la mayoría de las versiones de PASCAL se dispone de un espacio limitado en


memoria para registrar el valor de un conjunto. De aquí que exista una
restricción en cuanto al tipo escalar que sirva de base.

En primer lugar, no pueden definirse conjuntos con elementos reales. Además


el número de elementos distintos, es decir, la gama de valores del tipo base,
ha de ser bastante limitada. En muchas versiones este límite estará entre 30 y
60 elementos, como máximo.

La limitación es en realidad algo más restrictiva, ya que no se impone


simplemente al número de valores básicos diferentes, sino que sus ordinales
deben estar comprendidos en el rango predefinido, desde cero al límite
máximo. Por ejemplo, si los conjuntos están limitados a 32 elementos, sólo
serán admisibles tipos base en que los ordinales estén en el rango 0..31. Esto
incluye los tipos definidos por enumeración de hasta 32 valores.

En particular, no hay garantía de que puedan definirse conjuntos sobre el tipo


CHAR, y los subrangos de él sobre los que puedan definirse conjuntos
dependerán de la representación interna de los caracteres usados por el
computador.

9.2. Expresiones con conjuntos.

El valor de un conjunto puede expresarse en función de valores del tipo base


mediante el “constructor” de conjunto, consistente en escribir la lista de
valores base entre corchetes, tal como ya se hizo en el apartado anterior.

Los valores de los elementos de base pueden darse en forma de constantes, en


cuyo caso habremos construido una “constante” de tipo conjunto, o bien
mediante expresiones cualesquiera. El orden en que se den los valores es
indiferente. Cuando pertenezcan al conjunto varios elementos consecutivos
puede usarse la notación valor..valor, equivalente a la de subrango.

El resultado de aplicar un operador de comparación será de tipo booleano.


También existe otro operador con resultado booleano que permite detectar la
pertenencia de un elemento a un conjunto dado. Se le representa por la
palabra clave IN, que llevará el elemento a examinar como primer operando y
el conjunto como segundo operando.
Operador Significado
IN pertenencia
Algunos ejemplos de expresiones con conjuntos son:
Expresión Resultado
[ROJO,AMARILLO] + [ROJO,AZUL] [ROJO,AMARILLO,AZUL]
[ROJO,AMARILLO] * [ROJO,AZUL] [ROJO]
[ROJO,AMARILLO] – [ROJO,AZUL] [AMARILLO]
[ROJO,AMARILLO] <> [ROJO,AZUL] TRUE
[ROJO,AMARILLO] <= [ROJO,AZUL] FALSE
ROJO IN [ROJO,AZUL] TRUE

- 62 -
9.3. Manejo de conjuntos.

Los conjuntos son valores estructurados. Aunque puedan usarse como


términos en expresiones aritméticas, no pueden servir de índices en sentencias
FOR o CASE. Tampoco pueden aparecer en sentencias de lectura o escritura. La
lectura o escritura de conjuntos ha de hacerse elemento a elemento, de
acuerdo con el tipo base.

El siguiente programa de ejemplo calcula e imprime una lista de los primeros


números primos (hasta 40) empleando el método de la criba de Eratóstenes,
definida aquí como conjunto de números.

PROGRAM CRIBA;
(* Programa para imprimir los primeros números primos hasta 40 *)
CONST MAX = 40;
VAR J,N: 1..MAX;
CRIBA: SET OF 1..MAX;
BEGIN
CRIBA:=[1..MAX];
FOR N:=1 TO MAX DIV 2 DO
BEGIN
J:=N+N;
WHILE J<MAX DO
BEGIN
CRIBA:=CRIBA-[J];
J.=J+N;
END;
END;
FOR J:=1 TO MAX DO
IF J IN CRIBA THEN WRITELN(J);
END.

- 63 -
EJERCICIOS

1. Definir mediante enumeración o declaraciones de tipo subrango los


conjuntos siguientes:
a) DIASDEENERO
b) COLORESBASICOS
c) MESES
d) TIPOCARACTER

2. Suponiendo que tomamos como básico el TIPO enumerado 0..9, calcular la


representación interna de los conjuntos:
A = 1,2,5
B = 2,6
C = 1,3,8,9
D = (vacio)
E = 1,7,8,9

3. Tomando como datos los conjuntos definidos en el ejercicio anterior, hallar


los conjuntos siguientes:
a) A + B
b) A – B
c) A * B
d) (A + E) * B
e) C - D

4. Escribir una función, que dado un carácter devuelva uno de los códigos
numéricos siguientes:
1: Si es una letra.
2: S es un dígito.
3: Si es un signo de puntuación (. , : ;).
4: Si es un espacio en blanco.
5: Si no es ninguno de los anteriores.

5. Hallar los siguientes conjuntos partiendo de los datos del ejercicio 9.2.
a) IF 3 IN B THEN H:=C-E ELSE H:=C+E
b) IF 0 IN D THEN H:=A+B ELSE H:=A-B
c) IF (1 IN B) OR (3 IN A) THEN H:=E-C
ELSE H:=E

6. Un avión dispone de 52 plazas. Se desea escribir un programa que lea el


número que identifica una plaza e informe si la plaza está libre. Si es así
se leerá un carácter, si éste coincide con una (S) se endiende que se
confirma la reserva y la plaza está ocupada a partir de este momento,
volviendo a leer otro número de identificación.
Para terminar el proceso se dará un número de identificación no
comprendido entre 1 y 52, produciéndose entonces un listado indicando
el estado de cada plaza.

- 64 -
VECTORES Y MATRICES
10
Estas estructuras de datos son admitidas por casi todos los lenguajes de
programación de alto nivel. Consisten en una serie de datos, todos de la
misma naturaleza, a los que se da un nombre común, distinguiendo cada
elemento por su índice o número de orden que ocupa en la serie. Coinciden
con el concepto matemático de las mismas.

V = (V1, V2, …, Vn)

10.1. Declaración de vectores.

La definición de una estructura de tipo vector es de la forma:

TYPE nombre = ARRAY tipoindice OF tipoelemento

donde “nombre” es el nuevo tipo vectorial, “tipoindice” es el tipo de valores


del subíndice, que ha de ser escalar y de rango limitado, y “tipoelemento” es
el tipo de cada componente del vector. Una vez definido el tipo pueden
declararse variables, o bien puede especificarse el tipo vectorial directamente
en la declaración de la variable, sin dar nombre particular al tipo.

A continuación se indican algunos ejemplos de declaración de tipos y variables


vectoriales:

TYPE DIASEM = (LUN,MAR,VIE,JUE,VIE,SAB,DOM);


COORDENADA = (X,Y,Z);
CASILLAAJEDREZ = (VACIA,PB,PN,TB,TN,CB,CN,AB,
AN,DB,DN,RB,RN);
PUNTO = ARRAY[COORDENADA] OF REAL;
HORARIODIA = SET OF 0..23;
VAR SEGMENTO: ARRAY[1..2] OF PUNTO;
HORARIOSEM: ARRAY[DIASEM] OF HORARIODIA;
TABLERO: ARRAY[1..8] OF ARRAY[1..8] OF CASILLAAJEDREZ;

Los nemotécnicos empleados en estos ejemplos son lo bastante significativos


como para no exigir mayores explicaciones.

10.2. Selección de componentes.

La sentencia de asignación puede ser usada para copiar una variable vectorial
en otra del mismo tipo, en la forma:

vector A := vector B
- 65 -
pero salvo este caso particular el manejo de estructuras vectoriales exigirá
operar con cada elemento por separado. Para hacer referencia a un
componente en particular se escribirá su subíndice a continuación del nombre
del vector, entre corchetes. Por ejemplo, usando las variables:

VAR PUNTOA, PUNTOB : PUNTO;

sería válido hacer:

PUNTOA[X] := 1.2;
PUNTOB[Y] := 4.3;
PUNTOC[Z] := 0.7;

para asignar valores a las coordenadas del punto A. Un giro de 90º alrededor
del eje Z podría conducir a las asignaciones:

PUNTOB[X] := PUNTOA[Y];
PUNTOB[Y] := -PUNTOA[X];
PUNTOB[Z] := PUNTOA[Z];

Si el vector tiene por componentes otros vectores, la selección mediante


subíndice se aplicará repetidamente. Por ejemplo:

SEGMENTO[1][X] := 3.7

10.3. Uso de matrices.

Un vector formado por vectores se denomina matriz, y en PASCAL se puede


usar para ello una notación más directa. Los ejemplos anteriores podrían
reescribirse:

VAR SEGMENTO : ARRAY [1..2,COORDENADA] OR REAL;


TABLERO : ARRAY[1..8,1..8] OF CASILLAAJEDREZ;

y la selección de un elemento se hará escribiendo los dos subíndices seguidos


entre corchetes, en la forma:

SEGMENTO[1.X] := 3.7;
TABLERO[3,6] := VACIO;
etc.

En cualquier caso los subíndices de un elemento pueden darse en forma de


expresiones cualesquiera, del tipo adecuado. Con un elemento dado podrán
construirse expresiones aritméticas de acuerdo con su tipo.

10.4. Manejo de vectores.

Para ilustrar el empleo de vectores o matrices, se presenta un ejemplo de


programa que construye una tabla de horario semanal, y luego cuenta las

- 66 -
horas de trabajo totales. Se supone un horario de 9 a 1 y de 4 a 8 de lunes a
viernes; de 9 a 2 los sábados, y cerrado los domingos.

PROGRAM HORARIO;
TYPE DIASEM = (LU,MA,MI,JU,VI,SA,DM);
HORARIODIA = SET OF 0..23;
VAR DIA: DIASEM; HORA: 0..23; HORA: INTEGER;
HORARIO: ARRAY[DIASEM] OF HORARIODIA;
BEGIN
FOR DIA:=LU TO VI DO
HORARIO[DIA]:=[9..13,16..19];
HORARIO[SA]:=[9..14];
HORARIO[DM]:=[];
FOR DIA:=LU TO DM DO
FOR HORA:=0 TO 23 DO
HORAS:=HORAS+ORD(HORA IN HORARIO[DIA]);
WRITELN(‘total ‘,HORAS, ‘ horas semanales’);
END.

10.5. Vectores de caracteres.

Un texto puede ser almacenado en forma de vector en el que cada elemento es


un carácter. Esta manera de operar es tan frecuente que el PASCAL da algunas
facilidades especiales para el manejo de este tipo de vectores que no pueden
utilizarse en los demás.

Una de estas facilidades, ya expuesta indirectamente, es la posibilidad de usar


“constantes” en forma de un texto entre apóstrofos. Un texto de n caracteres
se considera implícitamente del tipo:

ARRAY[1..n] OF CHAR

y puede ser asignado como valor a vectores declarados como tales. Sería
válido escribir:

VAR NOMBRE: ARRAY[1..8] OF CHAR;


............
NOMBRE := ‘EJEMPLO ’
.........…
(nótese el espacio en blando para completar los 8 caracteres)

Un vector de caracteres puede ser usado en sentencias de escritura igual que


un texto literal. Continuando con el ejemplo anterior, podría escribirse:

WRITE(‘El nombre es: ‘,NOMBRE)

- 67 -
Desgraciadamente no es posible emplear la sentencia de lectura para tomar
una serie de caracteres y almacenarlos en un vector directamente. La lectura
de caracteres ha de hacerse siempre uno a uno. En el caso anterior podría
escribirse:

FOR N:=1 TO 8 DO READ(NOMBRE[N])

para leer los 8 caracteres consecutivos necesarios. Para ello será necesario que
la línea de datos contenga al menos 8 caracteres, pues de no ser así se
tomarán los que falten de la línea siguiente. En capítulos posteriores se verá la
manera de detectar el fin de la línea de datos.

- 68 -
EJERCICIOS

1. Escribir un programa que calcule:

M = 1 / (N ΣXi) siendo N = 11 e i = 1,2,3,…,11

Los valaores de Xi se leerán del fichero de entrada.

2. Indicar cual será el resultado de la matriz A después de ejecutar:

FOR I:=1 TO N DO
FOR J:=1 TO N DO
A[I,J] := I=J;

Siendo A una matriz de valores booleanos, de dimensión NxN.

3. Escribir un segmento de programa que invierta el orden de los caracteres en


un texto. Se leerá en primer lugar el número de caracteres que
componen el texto.

4. Dada la matriz cuadrada de orden M, calcular la matriz que resulte de restar


a cada elemento de la matriz la media aritmética de su fila, es decir:
M
1
A ij = Aij −( )∑ A
M 1 ij

Mirar esta fórmula porque creo que está mal, la ultima A ij debe ser otra cosa

5. Escribir un programa para calcular todas las combinaciones posibles para


colocar ocho reinas en un tablero de ajedrez, sin que se tomen entre sí.

6. Escribir un programa que escriba ordenadamente N números, que se leerán


a tal efecto.

7. Se dispone de un almacén con cinco productos, de los cuales se conoce su


precio por unidad y el número de unidades existentes en stock. Las
operaciones se pretenden controlar mediante un subprograma que
admitirá los siguientes comandos:
I – Inicializar precios y cantidades en stock.
V – Venta de un producto.
C – Compra de un producto.
B – Balance final de ventas, compras y existencias.

8. Escribir un programa para sumar dos números enteros con cien cifras cada
uno.

9. Escribir un programa que calcule las potencias negativas de 2.

- 69 -
10. Escribir un programa para realizar la contabilidad mensual de una empresa
que procesa al final de mes el conjunto de datos que teienen el siguiente
formato por línea:

TIPO, TIPO-CONCEPTO, FECHA, CANTIDAD

Donde:
TIPO, es un entero que indica:
1. Cobro
2. Pago
3. Fin de datos
TIPO-CONCEPTO, es un número entero que indica el concepto por
el que se realiza el pago o cobro, tipificados de la siguiente forma:
1. Recibos (Cobrados o pagados)
2. Nóminas
3. Letras (Cobradas o pagadas)
4. Bancos.
5. Compras diversas
FECHA, es el día (entero) correspondiente dentro del mes.

CANTIDAD, es el importe en pts. de la operación.

Se desea un listado detallado con el siguiente formato:


FECHA CONCEPTO COBROS PAGOS TOTAL

XX - en letra - x,xxx.xxx x,xxx.xxx xx,xxx.xxx

“ “ “ “ “

“ “ “ “ “

“ “ “ “ “

TOTALES xx,xxx.xxx xx,xxx.xxx xxx,xxx.xxx

- 70 -
REGISTROS
11
Esta forma estructural consiste en una colección o secuencia de elementos
componentes que no han de ser de la misma naturaleza, como en el caso de
los vectores. Los componentes no se distinguen por número de orden, sino por
nombre particular. Los componentes se llaman también “campos”.

11.1. Declaración de registros.

La declaración de un tipo de estructura de esta naturaleza se hace en la forma:

registro = RECORD
campo: tipo;
campo: tipo;
........
END

donde registro recibe un nombre global, al tiempo que cada campo se define
por un nombre que lo identifica, con indicación del tipo de valor que le
corresponde. Ejemplos de registros serían:

TYPE
MES = (ENE,FEB,MAR,ABR,MAY,JUN,JUL,AGO,SEP,OCT,NOV,DIC);
FECHA = RECORD
DIA: 1..31;
MESS: MES;
ANNO: INTEGER;
END;
PUNTO = RECORD
X:REAL;
Y:REAL;
Z:REAL;
END;

donde estas declaraciones definen solamente el tipo, pudiéndose luego


declarar variables en la forma habitual.

Si varios campos seguidos son del mismo tipo, éste puede indicarse sólo una
vez, en el último, escribiendo los campos separados por comas. La última
definición del ejemplo podría reescribirse:

PUNTO = RECORD
X,Y,Z: REAL;
END;

- 71 -
En los ejemplos anteriores cada campo es un valor simple, pero esto no es una
limitación, sino que cada campo puede ser una estructura tan compleja como
se desee. Por otra parte, el nombre de un campo puede coincidir con el de la
misma variable registro, o con el de otra variable cualquiera.

11.2. Selección de componentes.

Excepto en el caso de la asignación a un registro del valor de otro del mismo


tipo, que puede hacerse directamente, las operaciones con registros obligarán
a trabajar con cada campo por separado. La selección de un campo se expresa
añadiendo al ombre de la variable registro el nombre del camp, separado por
un punto. Si consideramos la variable:

VAR HOY: FECHA;

será correcto escribir:

HOY.DIA := 6;
HOY.MESS := ENE;
HOY.ANNO := 1981;

por ejemplo. Del mismo modo, para cambiar el mes por el siguiente se podría
programar:

IF HOY.MESS = DIC THEN HOY.MESS := ENE


ELSE HOY.MESS := SUCC(HOY.MESS);

11.3. Sentencia WITH.

En una sentencia o grupo de sentencias seguidas es frecuente encontrar


referencias a campos de un mismo registro. Se puede usar una notación más
sencilla, evitando repetir el nombre del registro cada vez, mediante la
sentencia WITH, cuyo formato es:

WITH variable DO sentencia

donde la variable será de tipo registro, y la sentencia podrá contener


referencias a sus campos mencionando sólo el nombre de éstos. Por ejemplo,
el incremento del mes podría reescribirse:

WITH HOY DO
IF MESS = DIC THEN MESS := ENE
ELSE MESS := SUCC(MESS);

que resulta bastante más legible.

Si la sentencia controlada por un WITH es también de ese tipo, tal como en:

WITH v1 DO WITH v2 DO sentencia

- 72 -
se puede abreviar la redacción en le forma:

WITH v1, v2 DO sentencia

y habrá que recordar que si v1 y v2 contienen campos del mismo nombre, se


entenderá que dicho nombre por sí sólo hace referencia a la segunda, de
acuerdo con la construcción no simplificada.

11.4. Operaciones con registros.

El manejo de estructuras de tipo registro no presenta grandes dificultades.


Como ejemplo se presenta un programa que lee los resultados de un examen
con tres ejercicios, y calcula la nota global de cada alumno, la media de la
clase y los totales estadísticos.

PROGRAM EXAMEN;
LABEL 5;
CONST MAX = 100;
TYPE NOTA = 1..10;
VAR
N, ALUMNOS: INTEGER;
TABLA: ARRAY[1..MAX] OF
RECORD
MATRICULA: INTEGER;
NOTA1,NOTA2,NOTA3,CALIFICACION: NOTA;
END;
MEDIAS: RECORD
MEDIA1,MEDIA2,MEDIA3,MEDIA: REAL;
END;
TOTAL: RECORD
SUSP,APROB,NOTABLE,SOBRES,MDEHON: INTEGER;
END;
BEGIN
ALUMNOS := 8;
FOR N:=1 TO MAX DO
WITH TABLA[N] DO
BEGIN
READ(MATRICULA);
IF MATRICULA=0 THEN GOTO 5;
ALUMNOS:=ALUMNOS+1;
READ(NOTA1,NOTA2,NOTA3);
END;
- 73 -
WRITELN(‘MATRICULA NOTA1 NOTA2 NOTA3 CALIFICACIÓN’);
5:WITH MEDIAS,TOTAL DO
BEGIN
MEDIA1:=0.0;
MEDIA2:=0.0;
MEDIA3:=0.0;
MEDIA:=0.0;
SUSP:=0;
APROB:=0;
NOTABLE:=0;
SOBRES:=0;
MDEHON:=0;
FOR N:=1 TO ALUMNOS DO
WITH TABLA[N] DO
BEGIN
MEDIA1:=MEDIA1+NOTA1;
MEDIA2:=MEDIA2+NOTA2;
MEDIA3:=MEDIA3+NOTA3;
CALIFICACION:=ROUND((NOTA1+NOTA2+NOTA3)/3);
MEDIA:=MEDIA+CALIFICACION;
WRITELN(MATRICULA,NOTA1,NOTA2,NOTA3,CALIFICACION);
CASE CALIFICACION OF
0,1,2,3,4: SUSP:=SUSP+1;
5,6: APROB:=APROB+1;
7,8: NOTABLE:=NOTABLE+1;
9: SOBRES:=SOBRES+1;
10: MDEHON:=MDEHON+1;
END; (* del CASE *)
END;
MEDIA1:=MEDIA1/ALUMNOS;
MEDIA2:=MEDIA2/ALUMNOS;
MEDIA3:=MEDIA3/ALUMNOS;
MEDIA:=MEDIA/ALUMNOS;
WRITELN(‘NOTA MEDIA ’,MEDIA1,MEDIA2,MEDIA3,MEDIA);
WRITELN;
WRITELN(‘SUSPENSOS ‘,SUSP);
WRITELN(‘APROBADOS ‘,APROB);
WRITELN(‘NOTABLES ‘,NOTABLE);

- 74 -
WRITELN(‘SOBRESALIENTES ‘,SOBRES);
WRITELN(‘M DE HON. ‘,MDEHON);
WRITELN(‘TOTAL ‘,ALUMNOS);
END;
END.

Este ejemplo resulta algo particular en el sentido de que todas las referencias a
componentes de registros tienen lugar dentro de sentencias WITH, usándose
directamente el nombre del campo.

Puede observarse que la sentencia WITH permite usar como variable de tipo
registro una que sea un elemento de un vector, cuya situación puede depender
de una variable. Si es así hay que tener cuidado de no alterar dicha variable
dentro de la propia sentencia WITH, ya que el compilador se limita a calcular la
posición de la componente sólo una vez, al iniciarse la sentencia WITH. Por
tanto, es correcto escribir, como en el ejemplo:

FOR N:=1 TO ALUMNOS DO


WITH TABLA[N] DO
........

y en cambio sería errónea la construcción:

WITH TABLA[N] DO
FOR N:=1 TO ALUMNOS DO
........

ya que la posición de TABLA[N] no es fija y por tanto no puede ser calculada al


iniciar la sentencia WITH.

11.5. Registros variantes.

Existen situaciones en que resulta interesante poder almacenar en una


determinada estructura de datos diferentes tipos de valores, según los casos.
Esto ocurre cuando hay situaciones mutuamente excluyentes.

En lenguaje PASCAL se permite definir el último campo de una estructura de


tipo registro en forma variable, con un número fijo de variantes posibles. Si se
usa este mecanismo la sintaxis de la definición del último campo será:

CASE indicador: tipo OF


valor1: (variante1);
valor2: (variante2);
.............…
valorN: (varianteN),
END

- 75 -
donde el indicador será una variable escalar del tipo indicado, que constituye
además implícitamente un campo fijo del registro; valor1-valorN será la
colección de valores posibles de dicho indicador, y las variantes, escritas cada
una entre paréntesis, especificarán la estructura del campo variable en cada
caso. Si para algún valor del indicador no hubiese que registrar ninguna
información se especificará una variante nula en la forma ().

Como ejemplo tomaremos el caso de la matrícula de un automóvil, que puede


tener dos formatos distintos, básicamente, en función de su antigüedad.
Prescindiendo del valor numérico de los campos, y considerándolos todos como
series de caracteres, se podría definir:

MATRICULA: RECORD
PROVINCIA: ARRAY[1..2] OF CHAR;
CASE ANTIGUA: BOOLEAN OF
TRUE: (NUMERO:ARRAY[1..6] OF CHAR);
FALSE: (RECORD CIFRAS: ARRAY[1..4] OF CHAR;
LETRAS: ARRAY[1..2] OF CHAR)
END;

y luego en el programa podría haber sentencias tales como:

MATRICULA.ANTIGUA:=FALSE;
MATRICULA.CIFRAS:=’0852’;
MATRICULA.LETRAS:=’AB’;

y además se puede verificar al ejecutarlas que el campo que se utiliza


corresponde a la variante especificada por el valor del indicador en ese
momento, de manera que si se escribiese:

MATRICULA.ANTIGUA:=TRUE;
MATRICULA.CIFRAS:=’7380’;

podría detectarse que la segunda sentencia provocaría un error, y detener el


programa.

Si este tipo de detección es innecesario puede, si se desea, eliminarse el


campo de indicador, y escribir simplemente:

CASE tipo OF
valor1: (variante1);
valor2: (variante2);
.............…
valorN: (varianteN),
END

pero entonces la variante válida debe ser implícita en la ejecución del


programa, y no puede ser determinada a partir del contenido del registro.

- 76 -
EJERCICIOS

1. Construir un registro jerarquizado para representar el horario de un


determinado tren, cuyos campos significativos son:
- Número : 6 dígitos.
- Origen : 25 caracteres.
- Destino : 25 caracteres.
- Hora de salida : (día, hora, minutos) DDHHMM.
- Hora de llegada : DDHHMM.
- Hora de paso : DDHHMM.
- Número de vagones : 3 dígitos.

2. Se tienen dos registros que representan un mismo punto del plano:


RECTANGULAR. Tiene las dos coordenadas rectangulares del punto.
POLAR. Tiene la distancia al origen y al ángulo.
Diseñar dos procedimientos que efectúan la conversión de uno a otro.

3. Escribir un procedimiento para multiplicar parámetros de tipo COMPLEJO y


otro para dividir.

4. Construir un registro variante, para contener los datos personales del


profesorado de un centro docente.
Estos datos son:
Nombre.
Dirección postal.
Teléfono.
Cátedra o departamento.
Cargo dentro de ella. (Catedrático, Agregado, Adjunto, Profesor
encargado de curso-P.E.C.-)
Título. (Licenciado, Doctor, Título Administrativo, etc.)
Dedicación. (Plena, Exclusiva, N. de horas)
Asignaturas. (Sólo para P.E.C.)
Observaciones.
Además en el caso de Catedrático se incluirán: Número de personas que
forman la cátedra o Departamento y el número de asignaturas que
imparten.

5. Un banco constituye sus números de cuenta de la siguiente forma:


- Los cinco primeros dígitos son un número secuencial.
- Los dos siguientes son el número de sucursal.
- Los dos siguientes son el tipo de ahorro.
- El último es un dígito de control.
Escribir un procedimiento que recibe como argumento un texto de 10
caracteres y lo descompone en los datos del registro descrito.

6. Escribir un procedimiento para listar todos los datos del profesorado de un


centro contenidos en una tabla, en la que cada línea es un registro como
el descrito en el ejercicio 11.4.

- 77 -
7. Escribir un procedimiento para listar Nombre y dirección postal, del
profesorado de un centro. Los datos se encuentran en una tabla, en la
que cada línea es un registro como el descrito en el ejercicio 11.4. El
listado podrá hacerse de forma selectiva, es decir:
- Sólo de catedráticos.
- Catedráticos y agregados.
- Catedráticos, agregados y adjuntos.
- Todos.

- 78 -
12
FICHEROS SECUENCIALES

Todas las estructuras de datos presentadas hasta el momento tienen un


tamaño fijo. El caso de registros variantes consiste simplemente en que varias
organizaciones, cada una de un tamaño diferente, pero fijo, comparten una
misma zona de memoria, cuya extensión equivaldrá a la variante de mayor
tamaño.

Existen también en PASCAL estructuras de datos de tamaño variable. La más


sencilla de ellas es la secuencia, consistente en una serie ordenada de
elementos componentes, todos del mismo tipo, en número indeterminado. A
esta estructura la denominaremos fichero secuencial, y podremos considerarla
asociada con dispositivos de almacenamiento auxiliares, exteriores a la
memoria central del computador.

La característica de un fichero secuencial es que sus componentes sólo pueden


ser usadas una tras otra en el orden en que constituyen el fichero, y sólo una a
la vez.

12.1. Declaración de ficheros. Variable asociada.

Los fichero sconstituyen tipos estructurales, que se especifican en la forma:

FILE OF tipobase

donde tipobase será cualquier tipo válido en PASCAL, bien un dato simple o
una estructura cualquiera. Un ejemplo trivial sería:

VAR LISTA: FILE OF INTEGER;

que declara la variable fichero LISTA como secuencia de números enteros.

El acceso al fichero es, como se ha indicado, usando un elemento cada vez.


Para ello se utiliza una variable del tipo base, asociada al fichero, y que puede
considerarse como una ventana a través de la cual aparece el elemento
accesible en un instante dado. El nombre de esta variable asociada se
construye añadiendo al nombre del fichero una flecha, en la forma:

fichero^

- 79 -
es decir, la declaración usada como ejemplo especifica implícitamente la
existencia de una variable, de tipo INTEGER, asociada al fichero, a la que se
hará referencia en la forma:

LISTA^

y que representa el valor accesible en cada momento.

12.2. Operaciones básicas con ficheros.

El manejo de ficheros se realiza mediante procedimientos y funciones


predefinidos, que se exponen a continuación:

• EOF(fichero) es una función booleana que vale TRUE cuando han sido
usados ya todos los componentes del fichero en cuyo caso la variable
asociada tiene un valor no definido (End Of File).
• RESET(fichero) es un procedimiento que prepara al fichero para ser
leído desde el principio, de manera que la variable asociada corresponde
al primer elemento. Si el fichero está vacío dicha variable permanecerá
indefinida y EOF(fichero) valdrá TRUE.
• REWRITE(fichero) es un procedimiento que prepara al fichero para ser
grabado desde el principio. El contenido del fichero se pierde, quedando
vacío y en condición de EOF.
• GET(fichero) es un procedimiento que mueve la variable asociada al
siguiente componente. Sólo tiene sentido ejecutarlo si la condición EOF
es FALSE. Si no hay más componentes se producirá EOF.
• PUT(fichero) es un procedimiento que añade un nuevo elemento al
fichero. Sólo tiene sentido si se está en condición de EOF, que se seguirá
cumpliendo tras su ejecución. El valor del elemento añadido será el que
se haya asignado explícitamente a la variable asociada, que habrá dejado
así de resultar indefinida.

Es importante hacer notar que antes de utilizar un fichero hay que ejecutar
sobre él un RESET o REWRITE, ya que de otro modo el componente el que se
accedería estaría indeterminado. Estas operaciones iniciales corresponden a lo
que se llama “abrir” el fichero.
Frecuentemente la lectura o escritura del fichero se realiza copiando valores
entre la variable asociada y otra variable del mismo tipo, definida aparte, y que
se usa para elaborar la información. Esta manera de operar se ve facilitada con
la existencia de otros procedimientos predefinidos, que pueden ser descritos en
función de los anteriores, y que son los siguientes:

- READ(fichero, variable) – variable:=fichero^;


GET(fichero)
- WRITE(fichero, variable) – fichero^:=variable;
PUT(fichero)

- 80 -
Un sencillo ejemplo de cómo usar estos procedimientos predefinidos es el
siguiente programa, que obtiene el valor medio de una lista de números
enteros.

PROGRAM PROMEDIO;
VAR N,NUMERO : INTEGER;
SUMA : REAL;
LISTA : FILE OF INTEGER;
BEGIN
N:=0; SUMA:=0.0; RESET(LISTA);
WHILE NOT EOF(LISTA) DO
BEGIN
N:=N+1;
READ(LISTA,NUMERO);
SUMA:=SUMA+NUMERO;
END;
IF SUMA<>0 THEN SUMA:=SUMA/N;
WRITELN(‘VALOR MEDIO = ‘,SUMA);
END.

12.3. Ficheros de caracteres.

Un tratamiento especial tienen los ficheros definidos de la forma:

FILE OF CHAR

cuyos componentes son caracteres, y que constituyen, por tanto, un texto.


Dicho texto se asume que puede descomponerse en líneas de longitud
variable, separadas por un carácter especial de cambio de línea. Dicho carácter
se considera de valor equivalente al espacio en blanco, y sólo puede ser
distinguido de él empleando la función booleana predefinida:

EOLN(fichero)

que toma valor TRUE cuando el contenido de la variable asociada es


precisamente el carácter de cambio de línea. Si en ese momento se lee dicho
carácter se obtendrá como resultado el espacio en blanco, indistinguible de
otro que figurase explícitamente en el texto. Otra manera de manejar el
cambio de línea es mediante los siguientes procedimientos predefinidos,
válidos sólo para ficheros de caracteres:

• WRITELN(fichero) graba un carácter de cambio de línea.


• READLN(fichero) salta los caracteres hasta el primer cambio de línea. La
variable asociada pasa a contener el primer carácter de la línea siguiente
si existe.

Otro privilegio de los ficheros de caracteres es que pueden ser leídos o


grabados a partir de variables numéricas, ejecutándose automáticamente la
conversión entre el valor numérico y su representación en forma de secuencia
de caracteres. Este hecho no constituye ninguna novedad, ya que en capítulos
anteriores se ha usado en la lectura de datos y escritura de resultados.

- 81 -
Además puede ordenarse la escritura de vectores de caracteres (aunque no le
lectura) resultando equivalente a una orden de escritura por cada carácter del
vector, consecutivamente. Estas lecturas y escrituras de varios caracteres sólo
son posibles con sentencias READ, y WRITE. La variable asociada sólo accede a
caracteres sueltos.

Al mandar escribir valores numéricos se obtendrá su representación decimal,


en un formato predefinido, precedida de algún espacio en blanco. Los valores
numéricos a leer deberán ir precedidos y seguidos de algún espacio en blanco
o cambio de línea, y deben ser una representación válida de un valor del tipo
adecuado, de acuerdo con las reglas de programación del PASCAL.

12.4. Ficheros predefinidos.

En todo programa PASCAL se presupone la existencia de dos ficheros de


caracteres, declarados implícitamente como:

VAR INPUT,OUTPUT: FILE OF CHAR;

y destinados a servir, como su nombre indica, como elementos primarios para


la lectura de datos y la escritura de resultados. Además se asume que al
comienzo del programa se ejecutan automáticamente las operaciones:

RESET(INPUT); REWRITE(OUTPUT);

que preparan a ambos ficheros para ser usados desde el principio. Estos
ficheros predefinidos serán los que se usen implícitamente en las sentencias
READ y WRITE que no lleven como primer argumento un nombre de fichero. De
esta manera si X es una variable o expresión de tipo INTEGER, REAL o CHAR,
según los casos, se cumplirá que:

READ(x) equivale a READ(INPUT,x)


WRITE(x) equivale a WRITE(OUTPUT,x)
READLN equivale a READLN(INPUT)
WRITELN equivale a WRITELN(OUTPUT)

lo cual simplifica la escritura del programa, en la forma usada de los capítulos


anteriores.

12.5. Ficheros externos.

Los ficheros usados en un programa pueden ser internos o externos. Los


ficheros internos son meras zonas auxiliares de trabajo, y no necesitan
declaración especial. Los ficheros externos permiten almacenar información
que se conserva después de terminado el programa, o procesar datos
preexistentes. Los ficheros externos se declaran como argumentos del
programa, escribiéndolos a continuación del nombre del programa, entre
paréntesis, igual que se hace con los argumentos en la declaración de
funciones o procedimientos. La forma general de la primera sentencia del
programa será, pues:
- 82 -
PROGRAM programa(fichero,fichero, …);

donde los nombres de ficheros deberán aparecer después en la declaración de


variables correspondiente. La mayoría de las versiones de PASCAL asumen que
los ficheros predefinidos son externos, en cuyo caso un programa que no
declarase ningún fichero equivaldría a otro que comenzara por:

PROGRAM programa(INPUT, OUTPUT);

aunque en otros casos esta declaración debe hacerse explícitamente.

12.6. Escritura con formato explícito.

Tal como se ha indicado, los valores numéricos pueden ser escritos sobre
ficheros de caracteres ocupando el espacio predefinido, que será suficiente
para contener la representación de cualquier valor posible, más algún espacio
en blanco que la separa del resultado anterior. Además los valores reales
aparecerán siempre en notación científica, como mantisa normalizada seguida
de una potencia de 10.

Se puede controlar parcialmente este formato, especificando explícitamente el


número de caracteres que han de grabarse en el fichero de resultados,
indicándolo a continuación del valor a escribir, en la sentencia WRITE
correspondiente, separado por dos puntos, en la forma:

WRITE(… valor: espacio …)

donde el espacio será el número de caracteres a grabar, que puede darse


como una expresión aritmética. Esta especificación es válida para valores
numéricos reales o enteros, caracteres simples, o vectores de caracteres. Es
responsabilidad del programador reservar espacio suficiente para el valor a
escribir. Este valor aparecerá siempre ajustado a la derecha del espacio
reservado rellenándose la parte no usada con espacios en blando. En algunas
versiones se amplía automáticamente el espacio utilizado, para valores
grandes, en caso necesario.

En el caso de valores reales, es posible también ordenar su representación en


la notación habitual, con una mantisa y el punto decimal intercalado. En este
caso a continuación del número total de caracteres se especificará el número
de cifras decimales de la parte fraccionaria, obteniéndose el resultado
redondeado a dicha precisión. La forma general es pues:

WRITE(… valor: espacio: decimales, ...)

- 83 -
EJERCICIOS

1. Escribir un programa que imprima el número de caracteres en blanco


(espacios) y el de no blancos que contiene un fichero de texto.

2. Escribir un programa para intercalar dos ficheros de personal. Ambos


ficheros están ordenados de menor a mayor por número de empleado. Se
considera error si aparece el mismo número de empleado en los dos. El
fichero resultante de la intercalación también estará ordenado. Si los
números de empleado de los dos ficheros fueran:
1, 3, 10, 12, 18
2, 6, 7, 11, 15
El fichero resultante sería: 1, 2, 3, 6, 7, 10, 11, 12, 15, 18
Los datos por empleado son:
Nombre y apellidos.
Número de identificación.
Sueldo.
Puesto en le empresa.

3. Escribir un programa que liste un fichero de texto, numerando cada línea del
mismo.

4. Escribir un programa que lea un número de hasta tres cifras e imprima su


valor en letra.

5. Escribir un programa para imprimir los valores leídos de un fichero externo,


ajustando a la izquierda.

6. Escribir un programa para imprimir ordenadamente (de menor a mayor) los


registros de un fichero externo definido de la siguiente forma:

TYPE
VE: RECORD
NUMERO: INTEGER;
TEXTO: ARRAY[1..20] OF CHAR;
END;
VAR
VALOR: FILE OF VR;

- 84 -

Das könnte Ihnen auch gefallen