Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Introduccionpascal PDF
Introduccionpascal PDF
Pascal.
Vicente López
( vicente.lopez@ii.uam.es )
2
Índice General
1 Esquemas Básicos 7
1.1 Ordenación temporal . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Componentes básicos . . . . . . . . . . . . . . . . . . . . . . . 8
1.3 Tráfico de información . . . . . . . . . . . . . . . . . . . . . . 9
2 Lenguajes 13
2.1 Procesamiento de información: hombre y ordenador . . . . . . 13
2.2 Formalización de los lenguajes . . . . . . . . . . . . . . . . . . 15
2.3 Las máquinas de Von Neuman . . . . . . . . . . . . . . . . . . 16
2.4 Breve historia de los lenguajes . . . . . . . . . . . . . . . . . . 17
2.5 Tipos de lenguajes . . . . . . . . . . . . . . . . . . . . . . . . 20
3 Algoritmos 23
3.1 Pasos en la resolución . . . . . . . . . . . . . . . . . . . . . . . 23
3.2 Uso múltiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.3 El ejemplo de Josefo . . . . . . . . . . . . . . . . . . . . . . . 25
4 Pascal 33
4.1 Caracterı́sticas . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2 El programa Pascal . . . . . . . . . . . . . . . . . . . . . . . . 34
4.3 Palabras reservadas y estructuras . . . . . . . . . . . . . . . . 35
4.4 Instrucciones sencillas y compuestas . . . . . . . . . . . . . . . 37
4.5 Diagramas de sintaxis . . . . . . . . . . . . . . . . . . . . . . 38
5 Datos 39
5.1 Variables, datos y direcciones . . . . . . . . . . . . . . . . . . 39
5.2 Identificadores . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.3 Tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3
4 ÍNDICE GENERAL
6 Entrada y salida 51
6.1 Dispositivos de entrada, salida y almacenamiento . . . . . . . 51
6.2 Las funciones Read y Write . . . . . . . . . . . . . . . . . . . 52
6.3 Formatos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.4 Las funciones WriteLn y ReadLn . . . . . . . . . . . . . . . . 55
7 Acciones 59
7.1 Operaciones básicas. . . . . . . . . . . . . . . . . . . . . . . . 59
7.1.1 Operadores aritméticos y expresiones aritméticas. . . . 59
7.1.2 Funciones aritméticas. . . . . . . . . . . . . . . . . . . 61
7.1.3 Aritmética entera y real. . . . . . . . . . . . . . . . . . 62
7.1.4 Operadores lógicos. . . . . . . . . . . . . . . . . . . . . 65
7.1.5 Expresiones lógicas. . . . . . . . . . . . . . . . . . . . . 68
7.1.6 Manipulación de bits. . . . . . . . . . . . . . . . . . . . 70
7.2 Sentencias de control. . . . . . . . . . . . . . . . . . . . . . . . 74
7.3 Sentencias de repetición. . . . . . . . . . . . . . . . . . . . . . 79
7.4 Manipulación de los datos STRING. . . . . . . . . . . . . . . 85
8 Modularidad 87
8.1 Dividir para vencer . . . . . . . . . . . . . . . . . . . . . . . . 87
8.2 Procedimientos . . . . . . . . . . . . . . . . . . . . . . . . . . 88
8.3 Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.4 Ámbito de definición de las variables . . . . . . . . . . . . . . 91
8.5 Paso de valores por contenido o dirección . . . . . . . . . . . . 92
8.6 Definición diferida . . . . . . . . . . . . . . . . . . . . . . . . . 96
8.7 Módulos y submódulos . . . . . . . . . . . . . . . . . . . . . . 97
8.8 Recursividad . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
10 Ficheros 125
10.1 Ficheros con Tipo . . . . . . . . . . . . . . . . . . . . . . . . . 125
10.2 Procesamiento secuencial y aleatorio . . . . . . . . . . . . . . 131
10.3 Ficheros de Texto . . . . . . . . . . . . . . . . . . . . . . . . . 136
11 Punteros 141
11.1 Contenidos, direcciones e identificadores . . . . . . . . . . . . 141
11.2 Punteros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
11.3 Asignación dinámica de memoria. . . . . . . . . . . . . . . . . 145
11.4 Declaraciones recursivas de tipos de datos . . . . . . . . . . . 147
6 ÍNDICE GENERAL
Capı́tulo 1
7
8 CAPÍTULO 1. ESQUEMAS BÁSICOS
Unidad
Unidad de
central de
memoria
procesos
A 2 4 1 J 3 3 u u u
1 2 3 4 5 6 7
1.3. TRÁFICO DE INFORMACIÓN 9
unidad de
memoria
6
?
unidad
unidad - aritmético
de
–
control
lógica
51 52 53
51 52 53
La segunda,
b := 5;
que en 52 almacene un 5,
3 5 0
51 52 53
51 52 53
1.3. TRÁFICO DE INFORMACIÓN 11
51 52 53
Lenguajes de programación
z =x+y .
El modo en que esta frase puede traducirse en una orden precisa para que la
realice un ordenador ha cambiado con el tiempo según variaban los diseños de
los ordenadores. Primitivamente en ordenadores como el MARK I se trataba
de una secuencia de tripletes de perforaciones en un cinta. Hoy en dı́a se
trata de las secuencias de ceros y unos del código binario. En el futuro los
programas podrı́an parecerse a los pentagramas de música actuales.
Una lectura parcial de la expresión matemática anterior puede ser la
siguiente:
13
14 CAPÍTULO 2. LENGUAJES
z := x + y ;
X Y Z
@
@
R
@
LOAD X
ADD Y
STORE Z
Datos Programa
? ?
ordenador ordenador
? ?
Resultado Programa
• Las aplicaciones.
. . .
hijo(X,Y) <- padre(Y,X) , varon (X).
hija(X,Y) <- padre(Y,X) , hembra (X).
abuelo(X,Z) <- padre(X,Y) , padre (Y,Z).
. . .
estableciendo relaciones lógicas que determinan una base de verdades con las
que han de ser coherentes las respuestas del programa.
Exite una diferencia grande en la programación con un lenguaje u otro
según sea interpretado o compilado, si bien esta distinción puede no ser inhe-
rente al lenguaje sino a su puesta en práctica en un determinado ordenador.
Un lenguaje es interpretado cuando la transformación de las instrucciones de
alto nivel a lenguaje máquina se realiza sentencia a sentencia según se van
ejecutando. Un lenguaje es compilado cuando esta trasformación se realiza
en bloque antes de que ninguna instrucción sea ejecutada. Por ejemplo, el
BASIC en general se suele interpretar y el LISP siempre. En un lenguaje
interpretado la puesta a punto de un programa ha de realizarse secuencial-
mente puesto que las distintas partes del programa no se pueden verificar
hasta que entran en ejecución.
En el caso más común de lenguajes compilados, son varios los subprocesos
implicados en la transformación del código de alto nivel en instrucciones
ejecutables por la UCP.
2.5. TIPOS DE LENGUAJES 21
Programa
COMPILADOR
Leng. maquina
H
HH
HH
L. maquina
HH
H
HH
HH
MONTADOR
Codigo UCP
datos que comparten todos los programas y asigna las direcciones comunes
donde cada uno deberá procesar esos datos. Esta unificación de direcciones
será imposible si algún procedimiento supuestamente existente en otro sub-
programa no aparece o aparece de un modo no unı́voco. También será causa
de error que algún dato compartido por subprogramas esté declarado de mo-
do distinto en cada programa. Estos errores son poco comunes y fácilmente
detectable con los mensajes de error proporcionados por el montador. Sin
embargo, los errores más comunes y más tediosos de eliminar son aquellos
de programación que dan lugar a sentencias sintácticamente correctas pero
que corresponde a acciones distintas a las deseadas. Desgraciadamente sólo
se detectan en la ejecución del programa.
En la actualidad existe la posibilidad de utilizar depuradores de progra-
mas (llamados en inglés debuggers por el origen de los errores en los or-
denadores primitivos ) que permiten seguir la ejecución paso a paso de un
programa aunque se obtenga el código máquina por compilación. Esta he-
rramienta facilita enormemente la depuración de los programas pues permite
conocer o modificar el valor de los datos manipulados en el programa durante
la ejecución.
Capı́tulo 3
Algoritmos y resolución de
problemas con el ordenador
23
24 CAPÍTULO 3. ALGORITMOS
• Captura de datos.
• Generación de las estructuras de datos adecuadas para el algorit-
mo que se va a utilizar.
• Especificación de los algoritmos.
• Presentación de los resultados.
(a) DISEÑO.
(b) ESCRITURA.
(c) VERIFICACIÓN.
3 2
'$
4 -1
&%
5 6
• Captura de datos.
3.3. EL EJEMPLO DE JOSEFO 27
end; {endwhile}
• Presentación de los resultados.
{Se comunica el orden del ultimo en el circulo }
writeln (individuo^.numero);
nodo = record
numero: integer;
siguiente: enlace
end;
var
j , n : integer;
individuo , temporal: enlace;
begin { Josefo }
end; {endwhile}
end. { Josefo }
• Verificación.
La verificación a menudo debe incluir pruebas para detectar el mal uso
del programa por parte de un usuario que no esta familiarizado con el
programa o con el problema.
En el programa Josefo la captura de datos de datos podrı́a incluirse
una especificación del dato requerido y una verificación del valor.
• Modularidad.
• Documentación.
• Claridad de estilo.
El programa Josefo si se acompaña de la adecuada documentación
externa permite su utilización para distintos datos y en tiempos futuros.
Su modificación para variantes del mismo problema es sencilla. Ima-
ginemos que el problema se modifica y se eliminan elementos saltando
cada vez M individuos en vez de 2. Aparte de la modificación en la
entrada de datos , la modificación del algoritmo es mı́nima y sencilla
de localizar:
se modificarı́a a:
Esta modificación serı́a igual de fácil para el autor original del programa
como para cualquier otro programador.
Capı́tulo 4
4.1 Caracterı́sticas
El PASCAL es un lenguaje relativamente moderno, desarrollado por Niklaus
Wirth y su grupo de Zurich en 1971. Se trata de un lenguaje de propósito
general, esto quiere decir que se puede emplear para construir todo tipo de
aplicaciones. En la práctica también quiere decir que se trata de un lenguaje
no diseñado para desarrollar ningún tipo especı́fico de aplicaciones. Pero el
PASCAL es especialmente útil para algo: para la enseñanza de buenos modos
de programación. El PASCAL es hoy en dı́a el lenguaje más usado para la
enseñanza de la programación por varios motivos:
El hecho de que tenga una estructuración muy marcada permite que los pro-
gramas sean fáciles de leer e interpretar, y facilita la escritura de programas
del modo que hoy en dı́a se estima correcto.
El compilador de PASCAL es relativamente sencillo de realizar, por lo
que se ha extendido a muchos tipos de plataformas, desde los ordenadores
personales a los grandes ordenadores corporativos. Cuando una aplicación
se escribe en PASCAL estandard puede compilarse en cualquier máquina en
la que exista compilador de PASCAL , que son la mayorı́a.
33
34 CAPÍTULO 4. PASCAL
Existen varios dialectos locales del PASCAL , entre los que se encuentra el
TURBO PASCAL , que admiten todas las instrucciones del PASCAL estan-
dard más un subconjunto especı́fico de instrucciones normalmente pensadas
para aumentar las capacidades del lenguaje en un ordenador particular.
El TURBO PASCAL , de la compañı́a Borland (Scotts Valley, Califor-
nia) es un dialecto del PASCAL que incluye además de las instrucciones del
PASCAL estandard una serie de instrucciones que permiten desarrollar apli-
caciones especı́ficas para ordenadores IBM PC o IBM PS y compatibles. No
es la única de las versiones de PASCAL existente para estos ordenadores,
pero sin duda la más extendida y probada. En la actualidad la versión 6.0 de
este lenguaje incluye además del compilador un entorno integrado de desa-
rrollo (IDE) que permite compilar, visualizar errores y depurar los programas
desde un mismo entorno.
y es equivalente a:
Program nombre ;
Program nulo;
{ Programa ejemplo de la estructura
más simple de un programa PASCAL }
Begin
End.
{ Este es un comentario
(* sintácticamente *)
correcto en PASCAL }
{5} Const
{6} nombre constante = valor ;
. . .
{7} Type
{8} nombre tipo = def tipo ;
. . .
{9} Var
{10} nombre variable : tipo dato ;
. . .
{11} Begin
. . .
Instrucción sencilla J
J
- J -
E
E
E
E
E
E
E
E
E
Begin Instruc. senc. End
;
{4} Begin
{5} b := a * a ;
{6} b := b * a ;
{7} End;
Datos
3.14159 contenido
6
nombre
PI - 7161 dirección
Las primeras instrucciones de un programa han de ser las que indican los
tipos de datos que se van a utilizar. Cuando un nombre se utiliza para un
dato que no va a modificarse se trata de un a constante. Si por el contrario
se permite que el contenido de las posiciones de memoria referidas por un
determinado nombre varı́en durante la ejecución del programa, se trata de
una variable.
Program Uno;
Const
39
40 CAPÍTULO 5. DATOS
PI = 3.14159;
UNIDADES = ’ radianes ’;
Var
n , m : Integer;
z : Real;
Begin
. . . .
5.2 Identificadores
Los nombres que se pueden utilizar para referirse tanto a las variables como
a las constantes son todos aquellos que no establezcan conflicto con las pala-
bras reservadas en PASCAL para especificar datos o acciones. NO pueden
utilizarse:
• Palabras reservadas
1YA 2ABC
• Números enteros:
42 CAPÍTULO 5. DATOS
– Integer
– Byte
– ShortInt
– Word
– LongInt
• Números reales:
– Real
– Double
– Single
– Extended
2. Caracteres y alfanuméricos.
• Char
• String
3. Valores de la lógica de Boole
• Boolean
• Integer
Es el tipo de variable que se usa para números enteros ( sin parte
decimal ) con signo. Para una variable Integer se reservan dos bytes
(16 bits) en memoria y puede almacenar números enteros en el rango
entre
• Word
En este tipo de datos se pueden almacenar enteros sin signo. Al igual
que para el tipo Integer, para el tipo Word se reservan 2 bytes en
memoria y puede admitir números enteros entre 0 y 65, 535.
• Byte
En PASCAL es posible utilizar un tipo de dato llamado Byte, para el
que , como su nombre indica, sólo se reserva 1 byte de memoria. En
las variables tipo Byte se pueden almacenar números enteros sin signo
y por tanto tendrán que estar limitados entre 0 y 255(28 − 1).
• Real.
Para almacenar números reales ( con parte decimal ) o enteros que
excedan el lı́mite permitido por LongInt , se ha de utilizar el tipo de
variable Real . A este tipo de datos también se le conoce con el nombre
de coma flotante por el uso que se hace de los 6 bytes que se reservan
en memoria para este tipo de datos. Con los 6 bytes y una forma de
representar el número algo rebuscada que estudiaremos con los erro-
res numéricos, se pueden almacenar números entre 2, 910−39 y 1, 71038
tanto positivos como negativos. Debido a la representación interna
utilizada, se almacenan con igual precisión (7 u 8 cifras significativas)
todos los números reales en el rango permitido.
Las operaciones con números en la representación en coma flotante
son mucho más lentas que entre números enteros representados direc-
tamente con su valor en base 2. Un coprocesador matemático (como
los 80X87) se dedica especı́ficamente a estas operaciones. El TURBO
PASCAL permite una colección de datos para tratar eficientemente con
números reales cuando se dispone del coprocesador matemático. Cuan-
do no se dispone de él, las operaciones se pueden emular por software
aunque son más lentas. Esta colección de tipos de datos son:
– Single
El tipo de datos Single es un Real más corto (4 bytes) con el
mismo rango de variación que el Real , pero con menos cifras
significativas.
– Double
44 CAPÍTULO 5. DATOS
• Boolean
Los valores que puede tomar una variable lógica, dentro de la lógica
Booleana (George Boole, Inglaterra 1815 – 1864), son Verdadero o Fal-
so. En PASCAL se suelen utilizar este tipo de variables para almacenar
el resultado comparaciones o el establecimiento de condiciones. Su dos
valores posibles son True y False.
Var
mayor , menor : Boolean;
{ ...... }
begin
{ ...... }
mayor := True;
menor := False;
{ ...... }
• Char
Para un dato del tipo Char se reserva un solo byte de memoria. En
ese byte se puede almacenar información de un carácter alfanumérico.
Si bien en la memoria del ordenador se está almacenando un número
entero entre 0 y 255, este número no puede entrar a formar parte de
operaciones aritméticas con números enteros pues se entiende que se
trata de un carácter ASCII. El numero almacenado es el ordinal del
carácter en la tabla ASCII.
• String
Cuando se quieren manipular grupos de caracteres ordenados, como
por ejemplo en texto, se dispone del tipo de datos String. En una
5.3. TIPOS DE DATOS 45
Program Dos;
Const
Lugar = ’modulo’;
Var
facultad : Char;
modulo , clase : String[6];
begin
{ ...... }
facultad := ’C’;
modulo := ’-XVI’;
clase := facultad + modulo;
writeln(’ Sera en el ’,Lugar,’ ’,clase);
{ ....... }
end.
4 - X V I % A
Program Tres;
Const
lugar : String[13] = ’modulo’;
begin
{ ...... }
lugar := lugar + ’ C’+ ’-XVI’;
writeln(’ Sera en el ’,lugar);
{ ....... }
end.
Const
lugar = ’modulo’;
En este caso, lugar es una constante del tipo String por que le asigna un
valor que es un conjunto de caracteres separados por comas.
Const
facultad = ’C’;
Cuando entre comas se sitúa un sólo carácter, se trata del valor de una
constante Char . También es sencillo reconocer los datos Boolean porque
se les asigna el indicador True o False . En el caso de los números, la
distinción se realiza entre enteros y reales. Para las constantes asignadas
con números reales, el compilador elige el tipo Real, y para los enteros el
Integer. La distinción entre números enteros y reales se hace por existencia
de punto decimal en el valor. Para los números reales existe también la
posibilidad de notación cientı́fica.
Const
Pi = 3.14159;
PiMedios = 1570.8e-3;
PiGrados = 180 ;
El compilador PASCAL interpreta que PiGrados es una constante Integer
, y las otras dos constantes del tipo Real .
Program Cuatro;
const
Calle = ’ Paloma Blanca ’;
48 CAPÍTULO 5. DATOS
Direccion = 11 ;
Puerta = ’B’ ;
var
nombre : String[40];
numero : Integer;
letra : Char;
begin
{ Asignaciones incorrectas }
(* Asignaciones ilegales
{1} nombre := Direccion;
{2} numero := Calle;
{3} numero := Puerta;
{4} letra := Calle;
{5} letra := Direccion ;
{6} nombre := 98;
{7} numero := ’ Paloma Negra ’;
{8} numero := ’A’ ;
{9} letra := ’ Paloma Negra ’;
{10} letra := 97 ;
*)
(* Asignaciones legales *)
{11} nombre := Puerta;
{12} nombre := ’C’;
{ Asignaciones correctas }
{13} nombre := Calle;
{14} nombre := ’ Paloma Negra ’;
{15} numero := Direccion;
{16} numero := 97;
{17} letra := Puerta;
{18} letra := ’A’;
end.
Las instrucciones {11} y {12} son incorrectas porque asignan a una variable
del tipo String una constante del tipo Char. No obstante, estas instruc-
ciones no dan lugar a error en PASCAL porque el compilador interpreta las
variables Char como un subconjunto de las String (El espacio reservado en
5.7. ASIGNACIÓN DE LOS DISTINTOS TIPOS DE VARIABLES 49
Program Cinco;
const
Doce = 12.0;
Once = 11;
var
i : Integer;
z : Real;
begin
{ Asignaciones incorrectas }
(* Asignaciones ilegales
{1} i := Doce ;
{2} i := 24 ;
*)
(* Asignaciones legales *)
{3} z := Once ;
{4} z := 22 ;
{ Asignaciones correctas }
{5} i := Once ;
{6} i := 24 ;
{7} z := Doce ;
{8} z := 22. ;
end.
51
52 CAPÍTULO 6. ENTRADA Y SALIDA
Program Uno;
{ Cuadrado de un numero entero }
Var
base , resultado : integer;
Begin
{1} Read(base);
{2} resultado := base * base;
{3} Write(resultado);
End.
2 7 3 1 ←
2 7 ← ← 3 1 ←
← 2 7 ← 3 1 ←
• ’Area del cuadrado :’ es una constante del tipo String cuyo valor
es la ordenación de los 19 caracteres entre las comillas ’.
6.3 Formatos
En un principio es deseable controlar exactamente el modo en el que se
escribe el valor de las variables en el dispositivo de salida. Esto puede ha-
cerse especificando el formato de escritura. En PASCAL cualquier variable o
constante que se incluya en el argumento del procedimiento Write() puede
acompañarse de una especificación del formato de salida del siguiente modo:
nombre:n:m
que han de ocupar la parte decimal (después del punto) cuando el tipo de
variable o constante lo permita.
Por ejemplo,
Program Tres;
var
resultado, base , altura : Integer;
Begin
{1} Read(base,altura);
{2} resultado := base * altura;
{3} Write(’Area del triangulo: ’:40,resultado:6);
end.
dará como resultado
Area del triangulo: 837
Los espacios que no ocupan el contenido de la variable o constante, se sitúan
a la izquierda. En el caso de tratarse de números reales, si no se especifica el
número de cifras decimales, se toma por defecto la notación cientı́fica. Estos
son algunos ejemplos de escritura de un número real:
Write(102030.40:8 ) 1.0E+0005
Write(102030.40:10) 1.0E+0005
Write(102030.40:12) 1.020E+0005
Write(102030.40:14) 1.02030E+0005
Write(102030.40:8:1) 102030.4
Write(102030.40:10:1) 102030.4
Write(102030.40:14:2) 102030.40
Program Cuatro;
var
resultado, base , altura : Integer;
Begin
{1} Read(base,altura);
{2} resultado := base * altura;
{3} Writeln(’ Resultado del calculo.’);
{4} Writeln(’Area del triangulo: ’:40,resultado:6);
end.
para los mismos datos suministrados al programa Tres será:
Resultado del calculo.
Area del triangulo: 837
Equivalentemente, existe el procedimiento Readln() que lee el valor de sus
argumentos siempre y cuando no encuentre la secuencia de control < EOL >.
Al programa Cinco se han de introducir los datos de modo distinto que
al Cuatro. Si se utiliza el teclado, hay que teclear el carácter de control
< CR > entre los dos números, puesto que < CR > actúa también como
indicador de fin de linea.
Program Cinco;
var
resultado, base , altura : Integer;
Begin
{1} Readln(base);
{2} Readln(altura);
{3} resultado := base * altura;
{4} Writeln(’ Resultado del calculo.’);
{5} Writeln(’Area del triangulo: ’:40,resultado:6);
end.
En un archivo, los saltos de carro están codificados con el carácter ASCII
correspondiente a la secuencia de control < EOL >.
Por ejemplo, un archivo que se imprime o aparece en pantalla del siguiente
modo:
3
4
es:
3 4
5
la salida será:
Acciones
a:= 3. + 5.;
b:= a - 2.;
b:= b * a * 6.;
c:= -b / 12.;
59
60 CAPÍTULO 7. ACCIONES
formato de instrucción,
+
−
variable1 := operando1 operando2;
∗
/
2. paréntesis.
3. multiplicación y división.
4. suma y resta.
y := F ( x ) ;
los tipos de datos que admiten como argumento, x, los tipos de datos que
proporcionan, y, y las funciones que realizan son:
F(x) x y
Abs ( x ) Real o Integer igual que x Valor absoluto
Arctan ( x ) Real o Integer Real Arco tangente
Cos ( x ) Real o Integer Real Coseno
Exp ( x ) Real o Integer Real Exponenciacion ( ex )
Frac ( x ) Real o Integer Real La parte decimal de x
Int ( x ) Real o Integer Real La parte entera de x
Ln ( x ) Real o Integer Real Logaritmo neperiano
Pred ( x ) Integer Integer x−1
Random Real Número aleatorio, y[0, 1]
Random(x) Integer Integer Número aleatorio, y[0, x]
Round ( x ) Real Integer x redondeado al entero más cercano
Sin ( x ) Real o Integer Real Seno
Sqr ( x ) Real o Integer Real Exponenciacion
√ ( x2 )
Sqrt( x ) Real o Integer Real x
Succ ( x ) Integer Integer x+1
Trunc ( x ) Real Integer x con la parte decimal eliminada
Las funciones trigonométricas que no están incluidas, se calculan fácilmente
a partir estas. Por ejemplo,
Program Uno;
Var
i,j : Integer;
z : Real;
Begin
{1} j := 8;
(*
{2} i := j / 4; Expresion aritmetica invalida
*)
{3} z := j / 4;
{4} Writeln(z:4:2);
end.
Program Dos;
Var
i,j : Integer;
z : Real;
Begin
{1} j := 2333;
{2} i := j * 23;
7.1. OPERACIONES BÁSICAS. 63
{3} Writeln(i:9);
(*
{4} i := 2333 * 23; Expresion aritmetica invalida
*)
{5} z := j * 23;
{6} Writeln(z:9:0);
{7} z := 1.0 * j * 23 ;
{8} Writeln(z:9:0);
{9} z := 2333 * 23;
{10} Writeln(z:9:0);
end.
es:
-11877
-11877
53659
53659
z := 3600 * i ;
z := 3600. * i ;
j Div i
Program Tres;
Var
i,j,k : Integer;
Begin
{1} i := 11; j := 6;
{2} k :=10 * ( (i+j) Div j );
{3} Writeln(k:9);
{4} k := 10 * Trunc ( (i+j) / j );
{5} Writeln(k:9);
{6} k := Trunc (10* ( (i+j) / j ) );
{7} Writeln(k:9);
end.
j M od i
Program Cuatro;
Var
i,j,k,m : Integer;
Begin
{1} i := 11; j := 6;
{2} k :=j mod i;
{3} Writeln(k:9);
{4} m := j * (i mod j) + k;
{5} Writeln(i:9,’ ’,m:9);
end.
2
14 14
El primero de estos tipos es muy útil para tomar decisiones como resultado
de la comparación de variables. La forma general en la que aparecen estos
66 CAPÍTULO 7. ACCIONES
operadores es:
=
<>
>
a b
<
<=
>=
Operador Condición
= a=b
<> a 6= b
> a>b
< a<b
<= a≤b
>= a≥b
En el caso de que de que a y b sean caracteres, las operaciones de comparación
se realizan sobre el valor entero del carácter ASCII correspondiente.
Ejemplos de utilización de estos operadores son:
Program Cinco;
Var
quizas : Boolean;
letra : Char;
i,j : Integer;
a,tan1,tan2,x : Real;
Begin
{1} i := -11; j := 6; letra := ’h’; x:= 1.3;
{2} quizas := i > j;
{3} Writeln(quizas); (* FALSE *)
{4} quizas := ’k’ <= letra ;
{5} Writeln(quizas); (* FALSE *)
{6} tan1 := Sin(x) / Cos(x);
7.1. OPERACIONES BÁSICAS. 67
{7} a := Sin(x);
{8} tan2 := a / Sqrt ( 1.0 - a * a ) ;
{10} quizas := ( tan1 = tan2 );
{11} Writeln(quizas); (* FALSE *)
end.
Merece la pena recordar una vez más que no se pueden trasladar directa-
mente las expresiones matemáticas a las sentencias de un programa. Por
ejemplo, en la instrucción {10} se asigna a quizás el valor FALSE , si bien
las expresiones utilizadas en las instrucciones {6} y {8} para calcular la
tangente son matemáticamente equivalentes. Debido a la utilización de una
representación finita de los números reales ambos valores serán ligeramente
distintos. La comparación para averiguar la similitud de números reales se
suele hacer utilizando la diferencia relativa:
Not operando
donde tanto operando como el resultado de la operación son datos del tipo
Boolean. El resultado, es la negación del operando:
a Not a
True False
False True
A B A And B
True False False
False True False
False False False
True True True
A B A Or B
True False True
False True True
True True True
False False False
A B A Xor B
True False True
False True True
True True False
False False False
Program Seis;
Const
(* Coordenadas cartesianas que definen los rectángulos *)
xa1 = 2; ya1 = 2; { Esquina inferior de A }
xa2 = 7; ya2 = 6; { Esquina superior de A }
xb1 = 5; yb1 = 4; { Esquina inferior de B }
xb2 = 10; yb2 = 8; { Esquina superior de B }
var
dentro1, dentro2, dentrox , dentroy , frontera : Boolean;
puntox,puntoy : Integer;
Begin
{1} Readln(puntox , puntoy); {Coordenadas del punto problema}
(* Sin considerar la frontera *)
{2} dentrox := ( puntox > xb1 ) And (puntox < xa2);
{3} dentroy := ( puntoy > yb1 ) And (puntoy < ya2);
{4} dentro1 := dentrox And dentroy;
{5} Writeln(’ Si no se considera el borde : ’,dentro1);
(* Considerando la frontera *)
{6} dentro2 := ( puntox >= xb1 ) And (puntox <= xa2) And
70 CAPÍTULO 7. ACCIONES
0 1 0 0 1 1 0 1
0 0 1 1 1 1 1 0
La operación And entre estos dos datos da como resultado el dato Byte :
0 0 0 0 1 1 0 0
cuyo valor decimal es 12. Si sobre los datos originales se realiza la operación
Or el resultado es:
0 1 1 1 1 1 1 1
0 1 1 1 0 0 1 1
72 CAPÍTULO 7. ACCIONES
cuyo valor decimal es 115. Estas tres operaciones son las que se realizan en
el programa Siete :
Program Siete;
Var
a , b , c: Byte;
Begin
a := 77;
b := 62;
c := a And b;
Writeln(c);
c := a Or b;
Writeln(c);
c := a Xor b;
Writeln(c);
End.
a1 a2 a3 a4 a5 a6 a7 a8
B, el resultado de
B := A Shl 3;
es,
a4 a5 a6 a7 a8 0 0 0
y, C, el resultado de
C := B Shr 7;
7.1. OPERACIONES BÁSICAS. 73
es,
0 0 0 0 0 0 0 a4
y el 32767 como
0111111111111111.
If datoBoolean
Then
accion1
o bien,
If datoBoolean
Then
accion1
Else
accion2
Boolean
?
HH
? H Cierto-
b ""
b
b" ?
Falso accion1
? ?
Continuar
Boolean
?
H?
" a
a
H
? ?
accion2 accion1
-
Continuar
Then
Writeln(’ Se trata de un numero positivo ’)
Else
Writeln(’ Se trata de un numero negativo ’);
positivo := ( n >= 0 ) ;
If positivo
Then
Writeln(’ Se trata de un numero positivo ’)
Else
Writeln(’ Se trata de un numero negativo ’);
End.
Program Diez;
Var
x , y : Real;
Begin { Diez }
{ Programa que calcula la raiz cuadrada de un numero }
Writeln(’ Calculo de la raiz cuadrada. Escriba el numero’);
Readln(x);
End. { Diez }
Con esta estructura If ... Then ... Else también se pueden realizar de-
cisiones múltiples. Un modo muy frecuente de utilización es la encadenación
de estructuras de la forma:
7.2. SENTENCIAS DE CONTROL. 77
If datoBoolean1
Then
accion1
Else
If datoBoolean2
Then
accion2
. . .
En el programa Once se utiliza una concatenación de estructuras para rea-
lizar una elección múltiple.
Program Once;
Var
n : Integer;
Begin { Once}
{ Programa que reescribe con letras un numero del 1 al 5 }
Writeln(’ Teclear un numero del 1 al 5’);
Readln(n);
If n = 1 then
Writeln(’ Uno ’)
Else If n = 2 Then
Writeln(’ Dos ’)
Else If n = 3 Then
Writeln(’ Tres ’)
Else If n = 4 Then
Writeln(’ Cuatro ’)
Else If n = 5 Then
Writeln(’ Cinco ’)
Else
Writeln(’ Numero fuera de rango’);
End. { Once }
Este tipo de bifurcación múltiple puede llegar a ser difı́cil de leer y el
PASCAL proporciona una estructura más legible para aquellos casos en los
que la bifurcación múltiple se realiza mediante comparación de datos sencillos
ordinales (por tanto ni Real, ni String). Esta es la estructura Case que
tiene la siguiente sintaxis:
78 CAPÍTULO 7. ACCIONES
Case variable Of
caso1 : accion1
caso2 : accion2
. . .
End;
o bien,
Case identificador Of
caso1 : accion1
caso2 : accion2
. . .
Else
acciond
End;
donde identificador es una variable del tipo Integer, Byte, o Char, las
acciones accion1,... son instrucciones sencillas o compuestas, y los casos
caso1, ... son la especificación de los valores. Esta especificación se puede
hacer separando valores con comas o bien mediante el rango, si se trata de
valores consecutivos. Un rango se especifica mediante el valor inicial y final
separados por dos puntos. El programa Doce es equivalente al Once pero
mucho más legible y eficiente.
Program Doce;
Var
n : Integer;
Begin { Doce}
{ Programa que reescribe con letras un numero del 1 al 5 }
Writeln(’ Teclear un numero del 1 al 5’);
Readln(n);
Case n Of
1 : Writeln(’ Uno ’);
2 : Writeln(’ Dos ’);
3 : Writeln(’ Tres ’);
4 : Writeln(’ Cuatro ’);
5 : Writeln(’ Cinco ’);
Else
7.3. SENTENCIAS DE REPETICIÓN. 79
End. { Doce }
Program Trece;
Var
c : Char;
n : Byte;
Begin { Trece}
{ Programa que identifica un caracter }
Writeln(’ Teclear el caracter’);
Readln(c);
Case c Of
’a’..’z’, ’A’..’Z’ : Writeln(’Letra’);
’0’..’9’ : Writeln(’Numero’);
’*’,’/’,’+’,’-’ : Writeln(’Operador aritmetico’);
’>’,’<’,’=’ : Writeln(’Operador logico’);
Else
Begin
n := Ord(c);
Writeln(’Simbolo ASCII ’,n)
end;
End;
End. { Trece }
donde la función intrı́nseca del PASCAL Ord() es una función que devuelve
el valor ordinal de cualquier argumento escalar, incluyendo los Char.
puede programarse en una instrucción simple para que sea el ordenador quien
lo haga repetidas veces. De hecho, las sentencias de repetición son general-
mente las responsables de la utilidad del ordenador. Se trata de instrucciones
que gobiernan la realización de tareas repetitivas mientras no sea cierta la
condición que se imponga para la finalización.
En PASCAL existen tres estructuras de repetición que son las construc-
ciones For – Do, Repeat – Until, y While – Do.
La primera de ellas, la construcción For – Do, tiene la siguiente sintaxis:
Program Catorce;
Var
z : Real;
n ,i : Integer;
Begin
Writeln(’Calculo del factorial (introducir el numero)’);
Readln(z);
n := Round(z);
If n > 33
7.3. SENTENCIAS DE REPETICIÓN. 81
Then
Writeln(’ Solo se puede calcular hasta 33!’)
Else
Begin
z := 1.;
For i:=1 to n do
z:= z * i;
Writeln(’El Factorial de ’,n:2,’ es : ’);
Writeln(z:40:0)
End;
End.
Program Quince;
Var
i : Char;
Begin
(* Programa que escribe el alfabeto al reves *)
Writeln(’’);
For i:=’Z’ Downto ’A’ do
Write(’ ’,i);
End.
i,n : Integer;
Begin
Writeln(’Escribo los numeros de dos en dos’);
Writeln(’Empezando en 1 y acabando en ?’);
Readln(n);
n := n - (n Mod 3) ;
For i:=1 to n do
Begin
Writeln(i);
i := i +2
End;
End.
Repeat
accion1;
accion2;
. . .
Until DatoBoolean
Program Diecisiete;
Var
n ,i : Integer;
Begin
Writeln(’Adivina el numero que he generado ( del 1 al 9 )’);
Writeln(’ Teclea 0 para terminar ’);
7.3. SENTENCIAS DE REPETICIÓN. 83
Randomize;
Repeat
i := Random(8);
Writeln(’Dime un numero ’);
Readln(n);
If i+1 <> n
Then
Writeln(’ No acertaste, era el ’,i+1)
Else
Writeln(’ Si ’);
Until n = 0 ;
End.
While DatoBoolean Do
accion
Program Dieciocho;
Var
n ,i : Integer;
Begin
Writeln(’Adivina el numero que he generado ( del 1 al 9 )’);
Writeln(’ Teclea 0 para terminar ’);
Randomize;
Writeln(’Dime un numero ’);
Readln(n);
While n <>0 do
84 CAPÍTULO 7. ACCIONES
Begin
i := Random(8);
If i+1 <> n
Then
Writeln(’ No acertaste, era el ’,i+1)
Else
Writeln(’ Si ’);
Writeln(’Dime un numero ’);
Readln(n);
End; {endwhile}
End.
Cuando se ha de programar un procedimiento repetitivo, la elección de una
de las tres estructuras se hará siempre considerando la claridad y facilidad
de programación.
En PASCAL también existe la sentencia de control no estructurado Goto,
pero no la consideraremos pues en este curso se pretende que el alumno
ejercite la programación estructurada. Sin embargo, si que consideramos la
función Exit cuya efecto es interrumpir la ejecución del bloque en la que
se encuentra. Si se trata del programa principal, producirá la interrupción
de la ejecución del programa. En el programa Diecinueve se modifica el
Diecisiete para interrumpir el juego haciendo uso de la función Exit.
Program Diecinueve;
Var
n ,i : Integer;
Begin
Writeln(’Adivina el numero que he generado ( del 1 al 9 )’);
Writeln(’ Teclea 0 para terminar ’);
Randomize;
Repeat
i := Random(8);
Writeln(’Dime un numero ’);
Readln(n);
If n = 0 Then Exit;
If i+1 <> n
Then
Writeln(’ No acertaste, era el ’,i+1)
7.4. MANIPULACIÓN DE LOS DATOS STRING. 85
Else
Writeln(’ Si ’);
Until n = 0 ;
End.
Program Veinte;
Var
s : String[10];
longitud, i : Integer;
Begin
s := ’ABCDEF’;
longitud := Ord(s[0]) ;
Writeln(’La longitud original es : ’,longitud);
For i:=1 to longitud Do
writeln(’Componente ’,i:2,’ : ’,s[i]);
s[0]:= Char(3);
s[2] := ’b’;
Writeln(’Despues de truncada y modificada: ’, s);
End.
86 CAPÍTULO 7. ACCIONES
La longitud original es : 6
Componente 1 : A
Componente 2 : B
Componente 3 : C
Componente 4 : D
Componente 5 : E
Componente 6 : F
Despues de truncada y modificada: AbC
Capı́tulo 8
Modularidad
i=0 1−r
y el esquema que podemos trazar para el programa es el siguiente:
Suma de la progresión:
(1) Lectura de datos
(2) Cálculo de la expresión
(3) Salida de resultados
A su vez, el cálculo de la expresión matemática no es inmediato puesto que
es necesario calcular rn donde r es real y n entero. También podemos des-
componer la tarea (2) en:
87
88 CAPÍTULO 8. MODULARIDAD
Program SumaProgresion;
Var
n : Integer;
r,a,suma : Real;
(* Declaracion de procedimientos y funciones *)
. . . . . . . . . . . . . . . . . . . .
(* Fin de la parte declarativa *)
Begin { SumaProgesion }
{ Se utiliza la expresion: suma = a (1-r**n) / (1-r) }
LeerDatos(n,a,r);
CalcularExpresion;
SacarResultados(suma);
End. { SumaProgresion}
8.2 Procedimientos
La sintaxis con la que se especifican estos procedimientos es similar a la de
un programa PASCAL pero se usa la palabra reservada Procedure para
indicar que se trata de un procedimiento parcial:
Parte declarativa
Begin
Bloque de sentencias del procedimiento
End;
8.3 Funciones
Muy parecida a la estructura Procedure es la estructura Function y se
utiliza para aquellos casos en los que se desea que el dato que se calcula en el
módulo independiente pueda aparecer en cualquier instrucción PASCAL en
el mismo lugar en el que aparecerı́a el dato. Este es el caso de las funciones
intrı́nsecas del PASCAL que ya se han visto. La sintaxis de la estructura
Function es:
En el argumento se especifican las dos variables con las que nos vamos a
referir al exponente y a la base, el exponente ha de ser un valor entero y
la base puede ser real. A continuación, se especifica que el valor que ha de
devolver la función al bloque donde ha sido llamada es Real. Para realizar
el cálculo se necesitan otras dos variables y se definen en la parte declarativa.
En las instrucciones {2}, {5} y {11}, aparece el nombre de la función en
la parte izquierda de una asignación y es en ellas donde se especifica el valor
que puede devolver la función. La llamada a Poten desde el procedimiento
CalcularExpresión :
End; { CalcularExpresion }
Program SumaProgresion;
Var
n : Integer;
r,a,suma : Real;
{ Lectura de datos }
Procedure Leerdatos( Var numero: Integer;
Var primero , razon : Real );
Begin {Leerdatos}
Writeln (’ Primer termino de la serie? ’);
Readln (primero);
Writeln (’ numero de terminos? ’);
Readln (numero);
Writeln (’ Razon de la serie? ’);
Readln (razon);
End; {Leerdatos}
z := base;
For i := 2 to exponente Do
z := z * base;
Poten := z
End;
End; { Poten }
End; { CalcularExpresion }
Begin { SumaProgesion }
{ Se utiliza la expresion: suma = a (1-r**n) / (1-r) }
LeerDatos(n,a,r);
CalcularExpresion;
SacarResultados(suma);
End. { SumaProgresion}
Program Uno;
Var
a , b ,c : Integer;
8.5. PASO DE VALORES POR CONTENIDO O DIRECCIÓN 95
Begin
{1} a := 3; b := 5; c:= 7;
{2} Writeln(’ Antes : ’, a:4 , b:4 , c:4 );
{3} Escribe(’Durante: ’, a , b );
{4} Escribe(’Durante: ’, a , b );
{5} Writeln(’Despues: ’, a:4 , b:4 , c:4 );
End.
Program Dos;
Procedure A ( c : Char);
Begin { A }
If c < ’Z’ Then B (c);
Write ( c )
End; { A }
Procedure B ( c : Char);
Begin { B }
A ( Succ (c) )
End; { B }
8.7. MÓDULOS Y SUBMÓDULOS 97
Begin { Dos }
A ( ’A’ );
End. { Dos }
Procedure Eco;
Var
s : String;
Begin { Tres }
{1}
{2} Eco;
End. { Tres }
If Final Exit;
que se haya escrito un programa que realice un bucle infinito. Esta posibilidad
existe puesto que el PASCAL permite la recursividad en la programación:
algo que bien utilizado puede aumentar la legibilidad de los programas.
8.8 Recursividad
La definición de muchos objetos abstractos se realiza mediante recursión. La
recursión aparece generalmente o bien en la definición de estructuras con
autosemejanza o en la descripción de procedimientos de cálculo matemático.
Se dice que una definición es recursiva cuando el objeto definido aparece
en la recursión. Este es un modo de definir objetos muy común y útil. Por
ejemplo, cuando estudiamos el problema de Josefo, se definı́an los nodos
que componı́an el cı́rculo como componentes que se identificaban por un
número y tenı́an un enlace con otro nodo. Como veremos posteriormente, la
recursividad es muy útil para definir estructuras de datos.
La recursión también se utiliza para definir procedimientos de cálculo.
En este caso, hay que llevar cuidado en transformar la definición recursiva
en un algoritmo que se realice en un número finito de pasos. Por ejemplo,
consideremos la definición del factorial de un número que se deriva de la
siguiente expresión:
n! = n(n − 1)!
Esta igualdad matemática no es un procedimiento de cálculo. Para que ası́
lo sea, hay que añadir algo más. En este caso, se trata de algo tan sencillo
como una condición de principio o fin. Si consideramos las dos igualdades:
n! = n(n − 1)!
1! = 1
veremos que ya disponemos de un procedimiento para calcular el factorial.
Para calcular, por ejemplo, 4! utilizarı́amos la secuencia de igualdades:
4! = 4 × 3! = 4 × 3 × 2! = 4 × 3 × 2 × 1! = 4 × 3 × 2 × 1 = 24
• La condición de finalización.
El PASCAL , como cualquier lenguaje moderno de programación permi-
te la programación recursiva: en la definición de un módulo, Procedure
o Function, puede aparecer una llamada a él mismo. El programa para
calcular el factorial podrı́a ser:
Program Factoriales;
Var
m :Integer;
Begin
Writeln(’Calculo de factorial. Introducir el numero:’);
Read( m );
If m > 7 Then
Writeln(’El numero es demasiado grande.’)
Else
Writeln (’El factorial de’, m:2 , ’ es ’, Fac (m) )
End.
Como se utilizan datos Integer este programa sólo será capaz de calcular
hasta el factorial de números pequeños pues crece muy rápidamente y a partir
de 7! se desborda la capacidad de almacenamiento de ese dato. Por lo demás,
se trata de un programa de fácil lectura. En la instrucción {2} consideramos
el valor de terminación de las llamadas recursivas. Sin ella, el programa no
acabarı́a nunca. En la instrucción {4} estamos diciendo que en esa llamada
se asigne a la función Fac el valor que se obtiene multiplicando el valor actual
8.8. RECURSIVIDAD 101
Type
Indentificador1 = Untipo1;
Indentificador2 = Untipo2;
. . .
103
104 CAPÍTULO 9. DATOS CON ESTRUCTURA
Program Uno;
Type
Entero = Integer;
Var
i,n : Entero;
. . . . . .
Program Uno;
Type
Nota = 0..10;
Var
i : Nota;
Begin
Writeln(’Teclear la nota (0 a 10):’);
Readln(i);
Case i Of
0..4 : Writeln(’Suspenso’);
5..10 : Writeln(’Aprobado’)
End;
End.
del programa. Con esta opción, si se teclea un dato fuera del rango definido
para Nota aparecer? un mensaje de error Run time. Sin esa opción del
compilador, no aparecerı́a ningún mensaje de error.
9.2 Enumeraciones
Los tipos de datos Integer, Char y Byte son ejemplos de tipos de datos
en los que se puede almacenar un número limitado de datos. En el tipo
Byte, por ejemplo, números entre el 0 y el 255. Si el programador necesita
utilizar un conjunto limitado de datos puede referirse a ellos estableciendo
explı́citamente una relación entre cada dato y uno de los valores que pue-
de tomar un tipo de dato limitado. Por ejemplo, si queremos referirnos a
los meses de año en un programa se puede establecer una relación entre un
número y el mes, empezando con el 1 para Enero y siguiendo hasta 12 con
el orden del calendario. Dado el uso cotidiano de esta relación resultarı́a
muy fácil escribir y leer programas en los que se utilizara una variable mes
del tipo Byte. Siempre que mes tomara el valor 2 el programador inme-
diatamente interpretarı́a ese valor como el mes de Febrero. Sin embargo, en
otras muchas ocasiones no existirá tal correlación cotidiana entre ordinales
y objetos. Por ejemplo, si en un programa se quiere operar con datos del
tipo color, considerando las posibilidades Rojo , Amarillo , Naranja, Verde
, y Azul, no es fácil elegir una ordenación entre ellos que permita establecer
una relación fácilmente comprensible entre un número, por ejemplo del 0 al
4, y cada color. Para estos casos el PASCAL permite establecer esa relación
en la definición de un tipo y el programador puede olvidarse de ella durante
el programa. Un tipo de dato enumerado se especifica con el conjunto de
posibilidades entre paréntesis y separadas por comas. En el programa Dos
tenemos un ejemplo de su utilización:
Program Dos;
Type
Color = (Rojo , Amarillo , Naranja, Verde , Azul);
Var
i : Color;
Begin
i := Amarillo;
Case Succ(i) Of
Amarillo : Writeln(’Se trata de Amarillo’);
106 CAPÍTULO 9. DATOS CON ESTRUCTURA
Writeln(Ord(i));
End.
i:= Color(1);
9.3 Conjuntos
Un conjunto de datos del tipo Cualquiera se define con la siguiente sintaxis:
Type identificador Set Of Cualquiera
donde identificador es el nombre elegido para el nuevo tipo de dato, y cual-
quiera es el tipo de dato de los elementos que forman el conjunto. Los
elementos pueden ser cualquier tipo de dato ordenado, y entre ellos los enu-
merados.
9.3. CONJUNTOS 107
End.
El operador In se utiliza para determinar si un elemento se encuentra dentro
de un conjunto, con la siguiente sintaxis:
108 CAPÍTULO 9. DATOS CON ESTRUCTURA
NomElemento In NomConjunto
donde NomElemento es el nombre del elemento sobre el que se inquiere y
NomConjunto el conjunto. El resultado de esta operación es un dato Boo-
lean, y se evalúa a True sólo si el elemento pertenece al conjunto.
En el programa Tres también se ilustra la asignación de valores a los
conjuntos, si bien falta añadir que también se puede asignar el conjunto
vacı́o ([] ).
Los operadores aritméticos y lógicos cuando actúan entre conjuntos tienen
un significado nuevo. Si A, B y C son conjuntos de elementos del mismo tipo,
las operaciones permitidas son :
C := A + B {C : conjunto union de A y B}
C := A * B {C : conjunto interseccion de A y B}
C := A - B {C : conjunto diferencia de A y B}
También se pueden comparar los conjuntos con los operadores lógicos dando
lugar a un dato Boolean. Si A y B son dos conjuntos de elementos del
mismo tipo y verdad un dato Boolean, las comparaciones siguientes son
posibles:
verdad := A = B {verdad es True si A y B son iguales}
verdad := A <> B {verdad es True si A y B son distintos}
verdad := A <= B {verdad es True si A es subconjunto de B}
verdad := A => B {verdad es True si B es subconjunto de A}
teniendo en cuenta que el conjunto vacı́o es subconjunto de todo conjunto.
También hay que tener en cuenta que el número de elementos que pueden
formar un conjunto en PASCAL está limitado a un máximo de 256.
9.4 Arrays
Cuando se tiene que seguir la pista a un grupo o de datos es muy útil re-
ferirse a todos ellos con un mismo nombre y distinguir entre los elementos
mediante el lugar que ocupan en el grupo. En realidad de trata de ampliar la
conveniencia de los conjuntos estudiados anteriormente a grupos de datos de
cualquier tipo. En el Array los elementos del grupo se ordenan asignándose
a cada elemento un número de orden o dirección. El tipo de dato Array (
tabla ) es uno de los datos con estructura más importantes de un lenguaje.
Esto es ası́, porque corresponde a una ordenación de datos similar a la que se
9.4. ARRAYS 109
Type
vector = Array [1..30] Of Real;
Var
texto : Array [0..3000] Of Char;
Program Primos;
Const
MAX = 1000;
{ Calculo de los numeros primos entre 1 y MAX
utilizando el algoritmo de la Criba de Eratostenes }
110 CAPÍTULO 9. DATOS CON ESTRUCTURA
Var
esPrimo : Array [1..MAX] of Boolean;
i,j : Integer;
Begin { primos }
{Se inicializa la tabla}
esPrimo[1] := False;
For i := 2 to MAX Do esPrimo[i] := True;
{En la criba de Eratostenes se parte de todos los numeros
y se van eliminando todos los multiplos de los primos
elegidos. Seran primos elegidos aquellos que , en orden
ascendente, no hayan sido marcados como multiplos }
estas tablas múltiples se puede realizar separando con comas los ı́ndices de
cada una de las dimensiones.
El siguiente procedimiento MultMatriz se puede utilizar para multipli-
car matrices.
Program Cuatro;
Const
MAXDIM = 20;
Type
Numeros = Real;
Matriz = Array[1..MAXDIM,1..MAXDIM] Of Numeros;
Var
n : Integer;
A,B,C : Matriz;
Procedure Leematriz ( Var X : Matriz); FORWARD;
Procedure Escribematriz ( X : Matriz); FORWARD;
Procedure MultMatriz ( dim : Integer;
Var
A1 , A2 , M : Matriz );
Var
i,j,k : Integer;
x : Numeros;
Begin { MultMatriz }
For i := 1 To dim Do
For j := 1 To dim Do
Begin
x:= 0.0;
For k := 1 To dim Do
x := x + A1 [i,k] * A2 [k,j];
M[i,j] := x;
End; {End del doble For}
End; { MultMatriz }
{ Aqui se encontrarian las definiciones de los }
{ dos procedimientos que se han omitido }
Begin
Writeln(’Dimension de las matrices: ’);
Readln(n);
Leematriz(A); Leematriz(B);
112 CAPÍTULO 9. DATOS CON ESTRUCTURA
MultMatriz(n,A,B,C);
Writeln(’La Matriz producto es:’);
Escribematriz(C);
End.
x := x + A1 [i][k] * A2 [k][j];
Program Cinco;
Const
MAXDIM = 300;
{ Los caracteres se guardan en enteros como su ordinal }
Type
Cadena = Array[0..MAXDIM] Of Integer;
Var
A,B : Cadena;
Procedure LeeCadena (Var x : Cadena);
9.4. ARRAYS 113
Var
i : Integer;
c : Char;
Begin { LeeCadena }
i:= 1;
Repeat
Read(c);
x[i] := Ord(c);
i := i+1;
Until ( EOLN );
x[0] := i - 1;
{ Lee los caracteres ASCII 13 (CR) y 10 (LF)
que delimitan el fin de linea }
Read(c);Read(c);
End; { LeeCadena }
Var
dim1 , i : Integer;
Begin
dim1 := A1[0];
For i := 1 To A2[0] Do
A1[ dim1 + i ] := A2[i];
A1[0] := dim1 + A2[0];
End;
Begin
Writeln(’’);
114 CAPÍTULO 9. DATOS CON ESTRUCTURA
LeeCadena(A);
LeeCadena(B);
Concatena(A,B);
Writeln(’’);
EscribeCadena(A);
End.
9.5 Registros
La situación encontrada en el problema planteado anteriormente de manipu-
lación de cadenas es muy común. Lo más frecuente es encontrarse en una
situación en la que se quiere representar en un tipo de dato una información
que posee estructura interna y es heterogénea, es decir, los campos en los que
se subdivide el dato no son todos del mismo tipo. Para ello el PASCAL, como
otros lenguajes de programación actuales, suministra los datos tipo registro
(en inglés records).
Un registro es un tipo de dato definido por el programador en el que
puede especificar su estructura interna.
El programador da nombre al nuevo tipo de dato y a cada uno de los
campos que lo componen, y especifica el tipo de dato que puede ocupar cada
uno de los campos. La sintaxis para estas especificaciones es:
Type
nombre =
Record
NombreCampo1 : TipoDato1 ;
NombreCampo2 : TipoDato2 ;
. . .
End;
Program Seis;
Type
Fecha =
Record
mes : 0 .. 12; { 0 seria para indicar que no se conoce la fecha}
dia : 1 .. 31;
agno : Integer ;
End;
Var
alta , baja : Fecha;
Begin
With alta Do
Begin
dia := 27 ;
mes := 2 ;
agno := 1992;
baja.mes := mes + 2;
End;
....
La elección del uso de la estructura With se suele hacer en cada caso par-
ticular según la legibilidad que añada al programa.
Ya hemos dicho que los campos de los registros pueden contener datos que
son del tipo registro. En ese caso, como siempre, habrá que llevar cuidado en
definir los tipos de datos en el orden adecuado para que nunca aparezca en
una declaración un tipo de dato que no ha sido declarado en pasajes anteriores
del programa. Si ampliamos el ejemplo anterior hacia la construcción de una
base de datos con los alumnos y sus notas, un programa de captación de
datos podrı́a empezar ası́:
Program Siete;
Type
Fecha =
Record
mes : 0 .. 12; { 0 seria para indicar que no se conoce la fecha}
dia : 1 .. 31;
agno : Integer ;
End;
Alumno =
Record
nombre : String;
apellidos : String;
9.5. REGISTROS 117
nacimiento : Fecha;
nota : Real;
End;
Var
uno,otro : Alumno ;
Begin
Writeln(’Nombre : ’) ; Readln(uno.nombre);
Writeln(’Apellidos : ’); Readln(uno.apellidos);
Writeln(’Agnno de nacimiento : ’); Readln(uno.nacimiento.agno);
Writeln(’Mes de nacimiento: ’); Readln(uno.nacimiento.mes);
Writeln(’Dia de nacimiento: ’); Readln(uno.nacimiento.dia);
Writeln(’Nota del examen: ’); Readln(uno.nota);
. . . . . . . . . . . . . .
y vemos que la referencia a los campos de registros que son a su vez campos
de un registro se realiza concatenando con puntos los identificadores de los
campos.
Para crear una base de datos que contuviera información de los alumnos
de una clase lo lógico serı́a ordenar los alumnos en una lista. Para ello, se
puede crear una estructura Array cuyos elementos sean los registros defini-
dos para almacenar la información de los alumnos. Se podrı́a por ejemplo
añadir en la parte declarativa del programa Siete el siguiente tipo de dato:
{ Type }
Lista =
Array[1..100] of alumno;
{ Var }
primero : Lista;
primero[1] := uno;
If (Primero[1].nacimiento.mes = 12 ) Then ......
118 CAPÍTULO 9. DATOS CON ESTRUCTURA
Program Ocho;
Const
MAXDIM = 300;
Type
Ristra = Array [1..MAXDIM] of Char;
Cadena =
Record
longitud : Integer;
contenido : Ristra;
End;
Var
A,B : Cadena;
Procedure LeeCadena (Var x : Cadena);
Var
i : Integer;
c : Char;
Begin { LeeCadena }
i:= 1;
With x Do
Begin
Repeat
Read(c);
contenido[i] := c;
i := i+1;
9.5. REGISTROS 119
Until ( EOLN );
longitud := i - 1;
End;
{ Lee los caracteres ASCII 13 (CR) y 10 (LF)
que delimitan el fin de linea }
Read(c);Read(c);
End; { LeeCadena }
Var
dim1 , i : Integer;
Begin
dim1 := A1.longitud;
For i := 1 To A2.longitud Do
A1.contenido[ dim1 + i ] := A2.contenido[i];
A1.longitud := dim1 + A2.longitud;
End;
Begin
Writeln(’’);
LeeCadena(A);
LeeCadena(B);
Concatena(A,B);
Writeln(’’);
EscribeCadena(A);
End.
debe estar mucho más claro el sentido de los conceptos tipo de dato y va-
riable. Una variable, es un identificador que utiliza el programador para
referirse a un dato y poder realizar operaciones con él. El tipo de dato ha de
especificarse para que el compilador pueda generar código UCP en el que se
utilice una cantidad de memoria suficiente para ese dato y estructurada del
modo adecuado. Cuando el programador se enfrenta a la resolución de un
problema puede pensar en variables para cualquier concepto abstracto que
piense que sea útil para resolver el problema de un modo claro y comunica-
ble, lo que muchas veces quiere decir de un modo lo más próximo posible al
lenguaje natural. La restricción obvia es poder explicitar sin ambigüedades
la gestión de la memoria del ordenador que ha de realizar el compilador para
almacenar y manipular ese dato. Mediante la estructura Record y Array
el PASCAL ofrece la posibilidad de definir tipos de datos muy próximos a
los utilizados en el lenguaje natural y que son una organización precisa de
tipos de datos más sencillos. En última instancia, los átomos que van a for-
mar esas estructuras más complejas son los tipos de datos fundamentales del
PASCAL : Byte , Integer , .... Al final, para una variable, el compilador
reservará lugar en memoria para almacenar un número determinado de bits
de información (una sucesión de ceros o unos). El tipo de dato definido para
esa variable va a determinar el modo en el que esos bits van a intervenir en
las operaciones y también el modo con en el que el programador se podrá
referir a todos esos bits de golpe o a subconjuntos de ellos.
9.6 Uniones
Comprendido lo anterior no debe resultar difı́cil entender dos posibilidades
avanzadas que permite el PASCAL en la manipulación de registros, y que
son los registros con variante ( o uniones con discriminación) y las uniones
libres. En PASCAL es posible dar una definición dinámica de la composición
de un registro. Es decir, que los campos que lo componen varı́en según el
valor de un parámetro. Para ello se utiliza la siguiente modificación de la
estructura Case dentro de la definición del registro:
Case
nombre : TipodeDato Of
caso1 : ( Especificacion1 );
caso2 : ( Especificacion2 );
. . .
9.6. UNIONES 121
Program Nueve;
Type
Fecha =
Record
mes : 0 .. 12; { 0 seria para indicar que no se conoce la fecha}
dia : 1 .. 31;
agno : Integer ;
End;
Alumno =
Record
nombre : String;
apellidos : String;
nacimiento : Fecha;
Case final : Boolean Of
False : ( nota : Real );
True : ( notaFinal : Real;
calificacion : String[14] );
End;
Var
uno,otro : Alumno ;
Begin
.........................................
122 CAPÍTULO 9. DATOS CON ESTRUCTURA
uno.nota:= 6.8 ;
como,
uno.calificacion := ’Notable’;
Case
TipodeDato Of
caso1 : ( Especificacion1 );
caso2 : ( Especificacion2 );
. . .
donde caso1, caso2,... son valores posibles del tipo de dato especificado Ti-
podeDato. Es equivalente a un Registro con variante en el que se omite el
identificador de la variable que gobierna las distintas alternativas.
Esta posibilidad de acceso variable al contenido de un registro es coherente
con lo resumido anteriormente sobre el sentido de variables y tipos de datos.
El compilador reserva para el dato en la memoria un espacio suficiente para
almacenar aquella de las variantes del registro de mayor tamaño. Se rellenará
el espacio de memoria del modo que en cada momento desee el programador y
la elección se realiza usando un campo u otro. Igualmente, la interpretación
de los bits almacenados en esas posiciones de memoria también depende
del campo del registro que se utilice, en el caso de que distintos campos
correspondan a distintos tipos de datos.
9.6. UNIONES 123
Las Uniones Libres han de usarse con precaución para evitar confusio-
nes en la lectura de los programas, pero a veces son las adecuadas para hacer
un programa legible. En el siguiente ejemplo la unión entre el tipo de dato
Char y Byte se utiliza para escribir una función que convierte un carácter
en el correspondiente número de orden ASCII.
Program Diez;
Var
dato : Char;
Begin { Diez }
Readln (dato);
Writeln (’ El caracter ’,dato , ’ corresponde al ASCII numero : ’,
ElAscii(dato) );
End. { Diez }
Ficheros
125
126 CAPÍTULO 10. FICHEROS
Program Uno;
Var
almacen : File of Byte;
num1,num2,num3,num4 : Byte;
Begin
{1} num1 := 72; num2 := 79;
{2} num3 := 76; num4 := 65;
{3} Assign(almacen,’uno.sal’);
{4} Rewrite(almacen);
{5} Write(almacen,num1,num2);
{6} Write(almacen,num3,num4);
{7} Close(almacen)
End.
Program Dos;
Var
almacen : File of Char;
num1,num2,num3,num4 : Char;
Begin
Assign(almacen,’uno.sal’);
Reset(almacen);
Read(almacen,num1,num2);
Read(almacen,num3,num4);
Close(almacen);
Writeln(num1,num2,num3,num4);
End.
HOLA
Program Tres;
10.1. FICHEROS CON TIPO 129
Begin { Tres }
nomArchi := ’Archi.dat’;
Writeln(’Nombre : ’) ; Readln(uno.nombre);
Writeln(’Apellidos : ’); Readln(uno.apellidos);
Writeln(’A~
no de nacimiento : ’); Readln(uno.nacimiento.agno);
Writeln(’Mes de nacimiento: ’); Readln(uno.nacimiento.mes);
Writeln(’Dia de nacimiento: ’); Readln(uno.nacimiento.dia);
End; {endif}
End. { Tres }
Program Cuatro;
{ Utilidad para listar el archivo de alumnos }
Type
Fecha = Record
mes : 0 .. 12;
dia : 1 .. 31;
agno : Integer ;
End;
Alumno = Record
nombre : String;
apellidos : String;
nacimiento : Fecha;
End;
Var
carpeta : File of Alumno;
uno : Alumno ;
nombreCarpeta : String;
Begin { Cuatro }
Writeln(’ Nombre del archivo donde se almacenan : ’);
Readln(nombreCarpeta);
Assign(carpeta,nombreCarpeta);
Reset(carpeta);
While Not Eof(carpeta) do begin
Read(carpeta,uno);
With uno Do
Begin
Write(apellidos,’, ’,nombre);
10.2. PROCESAMIENTO SECUENCIAL Y ALEATORIO 131
Begin { IniciaLista }
Writeln(’Inicialización de un archivo de alumnos’);
Writeln(’Nombre del archivo: ’); Readln(NomArchi);
Assign(carpeta,nomArchi);
Rewrite(carpeta); {Se crea el archivo}
otro.numeroTotal := 0; {Se inicializa a 0 el numero de orden }
Write(carpeta,otro);
Close(carpeta);
End. { IniciaLista }
En el programa IniciaLista se procede a inicializar la base de datos: se
crea el archivo con el nombre indicado por el usuario y se escribe en el
primer registro el Integer 0 para indicar que no hay todavı́a ningún alumno
incluido. Como almacen se tiene que definir como un File Of alumno para
poder escribir un entero en el primer registro tenemos que recurrir a una
unión libre del registro.
El programa que puede añadir un alumno en la base de datos es :
Program AumentaLista;
10.2. PROCESAMIENTO SECUENCIAL Y ALEATORIO 133
Writeln(’Nombre : ’) ; Readln(uno.nombre);
Writeln(’Apellidos : ’); Readln(uno.apellidos);
Writeln(’A~
no de nacimiento : ’); Readln(uno.nacimiento.agno);
Writeln(’Mes de nacimiento: ’); Readln(uno.nacimiento.mes);
Writeln(’Dia de nacimiento: ’); Readln(uno.nacimiento.dia);
Seek(carpeta,0); { Al principio }
otro.numeroTotal := otro.numeroTotal + 1;
Write(carpeta,otro);
Close(carpeta);
End; {EndIf}
End. {AumentaLista}
En este programa, para llegar al final del fichero simplemente se saltan los
registros indicados al principio, y se escribe el nuevo. Después, se vuelve al
principio para aumentar en 1 el contador de registros almacenados.
El listado de los alumnos en la base de datos serı́a :
Program ListaLista;
{ Utilidad para escribir el archivo de alumnos }
Type
Fecha =
Record
mes : 0 .. 12; dia : 1 .. 31; agno : Integer ;
End;
Alumno =
Record
Case Boolean of
True : ( nombre : String;
apellidos : String;
nacimiento : Fecha );
False :
( numeroTotal : Integer );
End;
Var
i : Integer;
carpeta : File of Alumno;
uno,n : Alumno ;
nombreCarpeta : String;
Begin { ListaLista }
Writeln(’ Nombre del archivo donde se almacenan : ’);
Readln(nombreCarpeta);
Assign(carpeta,nombreCarpeta);
Reset(carpeta);
Read(carpeta,n);
10.2. PROCESAMIENTO SECUENCIAL Y ALEATORIO 135
For i := 1 To n.numeroTotal Do
Begin
Read(carpeta,uno);
With uno Do
Begin
Write(i:3,’ ’,apellidos,’, ’,nombre);
If nacimiento.mes <> 0 Then
Writeln(’ (’,nacimiento.dia,’/’,nacimiento.mes,’/’,
nacimiento.agno,’)’);
End
End; {endfor}
Close(carpeta);
End. { ListaLista }
Con esta nueva definición de la base de datos de alumnos resulta muy sen-
cillo escribir un programa para corregir errores en alguno de los registros
almacenados.
Program ModificaLista;
{ Utilidad para modificar un alumno en la lista }
Type
Fecha =
Record
mes : 0 .. 12; dia : 1 .. 31; agno : Integer ;
End;
Alumno =
Record
Case Boolean of
True : ( nombre : String;
apellidos : String;
nacimiento : Fecha );
False : ( numeroTotal : Integer );
End;
Var
elemento :Integer;
carpeta : File of Alumno;
uno,otro : Alumno ;
136 CAPÍTULO 10. FICHEROS
Respuesta : Char;
nomArchi : String;
Begin {ModificaLista}
Writeln(’Nombre del archivo: ’); Readln(NomArchi);
Writeln(’Numero de orden: ’); Readln(elemento);
Writeln(’Nombre : ’) ; Readln(uno.nombre);
Writeln(’Apellidos : ’); Readln(uno.apellidos);
Writeln(’A~
no de nacimiento : ’); Readln(uno.nacimiento.agno);
Writeln(’Mes de nacimiento: ’); Readln(uno.nacimiento.mes);
Writeln(’Dia de nacimiento: ’); Readln(uno.nacimiento.dia);
Program siete;
Uses Dos;
Var
almacen : Text;
x : Real;
i : Integer;
h1,m1,s1,c1,h2,m2,s2,c2 : Word;
Begin
Assign(almacen,’siete.sal’);
Rewrite(almacen);
GetTime(h1,m1,s1,c1);
10.3. FICHEROS DE TEXTO 139
Writeln(h1,’:’,m1,’:’,s1,’:’,c1);
For i := 1 to 10000 Do Begin
x := Random;
Writeln(almacen,x);
End; {endfor}
GetTime(h2,m2,s2,c2);
Writeln(h2,’:’,m2,’:’,s2,’:’,c2);
Close(almacen)
End.
Program Uno;
Var
a , b : Integer;
Begin { Uno }
{1} Readln(a);
{2} b := a;
{3} Writeln(a:4,’ ’,b:4);
End. { Uno }
en el que se definen las variables a y b para almacenar datos del tipo In-
teger. En la instrucción {3} se especifica que el dato almacenado en la
141
142 CAPÍTULO 11. PUNTEROS
11.2 Punteros
En ningún momento se ha hecho explicito en la sintaxis del lenguaje que un
dato está identificado internamente por una posición de memoria. Sin em-
bargo, es muy útil poder manipular los datos realizando algoritmos en los que
también interviene la dirección de los datos. Para ello el PASCAL permite
que en los programas aparezca un tipo de dato que son las direcciones de los
datos. Estas direcciones se llaman normalmente punteros, y en un programa
PASCAL pueden intervenir las direcciones de datos que estén definidos. Se
especifica que una variable es un puntero a un tipo de dato con la ayuda del
calificador ˆ que se antepone a un identificador.
El dato ^tipodato es el puntero a un dato del tipo tipodato. Por
ejemplo en el segmento de programa :
Type
Fecha =
Record
dia : Integer;
mes : Integer;
End;
Var
a: Integer;
px : ^Real;
pa : ^Integer;
pHoy,pAyer : ^Fecha;
. . .
. . .
pHoy^ := pAyer^;
. . .
implica que se almacene en el lugar de memoria indicado por pHoy el dato
almacenado en el registro al que apunta pAyer. Para completar la herra-
mienta es necesario un operador que sea capaz de extraer de una variable su
dirección, y este es el operador que se representa por @. La asignación:
pa := @a;
es correcta porque pa es el puntero a un Integer y el resultado de operar @
sobre a (que es un Integer ) es también el puntero a un Integer.
Una versión sofisticada del programa Uno es la siguiente:
Program Dos;
Var
a ,b : Integer;
pb : ^Integer;
Begin { Dos }
{1} a := 10 ;
{2} pb := @a ;
{3} b := pb^ ;
{4} Writeln(a:4,’ ’,b:4);
End. { Dos }
Program Tres;
Var
a : String;
pa,pb : ^String;
Begin { Tres }
a := ’Hola’; { en a se almacena ’Hola’ }
pa := @a; { pa apunta a}
pb:= pa; { pb apunta a}
writeln(a);
pb^ := ’Adios’;
Writeln(a); { el contenido de a es ’Adios’ }
End. { Tres }
Program Cuatro;
Type pinte = ^Integer;
Var
a ,b ,c: Integer;
11.3. ASIGNACIÓN DINÁMICA DE MEMORIA. 145
Begin { Cuatro }
a := 2 ;
b := 3 ;
c := 4 ;
Cuacua(@a,b,c);
Writeln(a:6,’ ’,b:6,’ ’,c:6);
End. { Cuatro }
es,
4 3 16
Program Cinco;
Var
pa,pb : ^String;
Begin { Cinco }
New(pa);
pa^ := ’Hola’;
pb:= pa;
writeln(pa^);
pb^ := ’Adios’;
Writeln(pa^);
Dispose(pb);
End. { Cinco }
Program CincoIncorrecto;
Var
pa,pb : ^String;
Begin { Incorrecto }
New(pa);
pa^ := ’Hola’;
New(pb);
pb:= pa;
writeln(pa^);
pb^ := ’Adios’;
Writeln(pa^);
Dispose(pb);
Dispose(pa);
End. { Incorrecto }
Primero, el programa darı́a un error en la ejecución. La última instrucción
intenta liberar un lugar de memoria que ya ha sido liberado en la llamada an-
terior a Dispose. Por otra parte, es un ejemplo claro de mal uso de la gestión
dinámica de memoria. La memoria reservada para el programa mediante la
tercera instrucción (256 bytes) no se puede liberar puesto que hemos perdido
la pista de cuál era. Es una práctica poco recomendable escribir programas
que cuando acaban dejan sin liberar memoria que reservaron del montón.
Enlace = ^Nodo;
Nodo =
Record
clave : Integer;
siguiente : Enlace
End;
Nil
Program Seis;
Type
enlace = ^Nodo;
Nodo =
Record
clave : Integer;
siguiente : Enlace
End;
Var
y,z : enlace;
i : Integer;
Begin
{ Se inicializa la lista }
New(z);
z^.siguiente := Nil; {El ultimo elemento apunta a Nil}
y^.siguiente := z;
z := y;
Readln(i)
End;
{Se escribe la lista}
While (y^.siguiente <> Nil ) Do
Begin
Writeln(y^.clave) ;
z := y^.siguiente;
Dispose(y);
y := z;
End;
Dispose(z)
End.
y la eliminación de un nodo :