Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Intro Ducci On Pascal
Intro Ducci On Pascal
on a la Programaci
on.
Pascal.
Vicente L
opez
Escuela T
ecnica Superior de Inform
atica
Universidad Aut
onoma de Madrid
( vicente.lopez@ii.uam.es )
Indice General
1 Esquemas B
asicos
1.1 Ordenacion temporal . . . . . . . . . . . . . . . . . . . . . . .
1.2 Componentes basicos . . . . . . . . . . . . . . . . . . . . . . .
1.3 Trafico de informacion . . . . . . . . . . . . . . . . . . . . . .
2 Lenguajes
2.1 Procesamiento de informacion:
2.2 Formalizacion de los lenguajes
2.3 Las maquinas de Von Neuman
2.4 Breve historia de los lenguajes
2.5 Tipos de lenguajes . . . . . .
hombre y ordenador
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
8
9
13
13
15
16
17
20
3 Algoritmos
23
3.1 Pasos en la resolucion . . . . . . . . . . . . . . . . . . . . . . . 23
3.2 Uso m
ultiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.3 El ejemplo de Josefo . . . . . . . . . . . . . . . . . . . . . . . 25
4 Pascal
4.1 Caractersticas . . . . . . . . . . .
4.2 El programa Pascal . . . . . . . . .
4.3 Palabras reservadas y estructuras .
4.4 Instrucciones sencillas y compuestas
4.5 Diagramas de sintaxis . . . . . . .
.
.
.
.
.
33
33
34
35
37
38
5 Datos
5.1 Variables, datos y direcciones . . . . . . . . . . . . . . . . . .
5.2 Identificadores . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . . .
39
39
40
41
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
INDICE GENERAL
4
5.4
5.5
5.6
5.7
. . . . . . .
. . . . . . .
. . . . . . .
de variables
.
.
.
.
.
.
.
.
.
.
.
.
6 Entrada y salida
6.1 Dispositivos de entrada, salida y almacenamiento
6.2 Las funciones Read y Write . . . . . . . . . . . .
6.3 Formatos . . . . . . . . . . . . . . . . . . . . . . .
6.4 Las funciones WriteLn y ReadLn . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
46
46
46
47
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
51
51
52
54
55
7 Acciones
7.1 Operaciones basicas. . . . . . . . . . . . . . . . . . . . .
7.1.1 Operadores aritmeticos y expresiones aritmeticas.
7.1.2 Funciones aritmeticas. . . . . . . . . . . . . . . .
7.1.3 Aritmetica entera y real. . . . . . . . . . . . . . .
7.1.4 Operadores logicos. . . . . . . . . . . . . . . . . .
7.1.5 Expresiones logicas. . . . . . . . . . . . . . . . . .
7.1.6 Manipulacion de bits. . . . . . . . . . . . . . . . .
7.2 Sentencias de control. . . . . . . . . . . . . . . . . . . . .
7.3 Sentencias de repeticion. . . . . . . . . . . . . . . . . . .
7.4 Manipulacion de los datos STRING. . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
59
59
59
61
62
65
68
70
74
79
85
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
87
87
88
90
91
92
96
97
99
.
.
.
.
103
. 103
. 105
. 106
. 108
8 Modularidad
8.1 Dividir para vencer . . . . . . . . . . . .
8.2 Procedimientos . . . . . . . . . . . . . .
8.3 Funciones . . . . . . . . . . . . . . . . .
8.4 Ambito
de definicion de las variables . .
8.5 Paso de valores por contenido o direccion
8.6 Definicion diferida . . . . . . . . . . . . .
8.7 Modulos y submodulos . . . . . . . . . .
8.8 Recursividad . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
INDICE GENERAL
9.5
9.6
Registros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Uniones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
10 Ficheros
125
10.1 Ficheros con Tipo . . . . . . . . . . . . . . . . . . . . . . . . . 125
10.2 Procesamiento secuencial y aleatorio . . . . . . . . . . . . . . 131
10.3 Ficheros de Texto . . . . . . . . . . . . . . . . . . . . . . . . . 136
11 Punteros
11.1 Contenidos, direcciones e identificadores .
11.2 Punteros . . . . . . . . . . . . . . . . . . .
11.3 Asignacion dinamica de memoria. . . . . .
11.4 Declaraciones recursivas de tipos de datos
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
141
. 141
. 142
. 145
. 147
INDICE GENERAL
Captulo 1
Esquemas b
asicos del
ordenador
1.1
Ordenaci
on temporal
Entrada
- Computadora
Salida
CAPITULO 1. ESQUEMAS BASICOS
- Computadora
Entrada
Salida
Tiempo
y los componentes se definen exclusivamente a partir de la secuencia de operaciones realizadas.
1.2
Componentes b
asicos
Unidad de
memoria
1.3. TRAFICO
DE INFORMACION
de
6
?
unidad
de
control
unidad
aritmetico
logica
1.3
Tr
afico de informaci
on
a := 3;
b := 5;
c := a + b;
c := c + 2;
if (c > 9) then writeln(c);
CAPITULO 1. ESQUEMAS BASICOS
10
51
52
53
52
53
La segunda,
b := 5;
que en 52 almacene un 5,
3
51
52
53
51
52
53
1.3. TRAFICO
DE INFORMACION
11
52
53
12
Captulo 2
Lenguajes de programaci
on
2.1
Procesamiento de informaci
on: hombre y
ordenador
CAPITULO 2. LENGUAJES
14
@
@
R
@
Z
LOAD
ADD
STORE
X
Y
Z
DE LOS LENGUAJES
2.2. FORMALIZACION
15
lenguaje de programaci
on de bajo nivel y el PASCAL es un lenguaje
de programaci
on de alto nivel. A la secuencia binaria que acepta la UCP
del ordenador se le denomina lenguaje m
aquina.
La desventaja obvia de un lenguaje de bajo nivel es lo costoso que resulta
la programacion de un ordenador con el. A medida que un lenguaje se acerca
mas al lenguaje natural, mas sencillo es programar con el y mas accesible a
personas no especializadas. Pero existe otra desventaja: los lenguajes de
bajo nivel dependen del ordenador. Dado que se han de ce
nir al dise
no
logico del ordenador, un lenguaje ensamblador solo es valido para familias
de ordenadores con el mismo dise
no logico.
2.2
Formalizaci
on de los lenguajes
Los lenguajes de alto nivel que vamos a estudiar en este curso son el resultado
de investigaciones realizadas desde dos enfoques distintos. Por una parte, un
lenguaje de programacion es un caso particular de un lenguaje formal; por
otra, una solucion al problema de ingeniera que surge en la construccion de
maquinas procesadoras de informacion.
La formalizacion de los lenguajes es un tema de investigacion desde los
antiguos griegos. Aristoteles (384332 A.C.) se puede considerar el padre
de la logica formal. Leibniz en el siglo XVII, y Frege en el XIX, intentaron construir lenguajes formales sin la imprecision y ambig
uedad de lenguaje
ordinario. Gorge Boole en 1854 proporciono un nuevo intento de formalizacion con la introduccion de smbolos, formulas y axiomas. El metodo
logico de Boole permitio construir maquinas logicas que poda resolver automaticamente problemas logicos. Mas tarde, el espa
nol Leonardo Torres
y Quevedo (18521939), entre otros dise
nos mecanicos automaticos, construyo el Ajedrecista, un automata capaz de jugar al ajedrez. A finales del
siglo XIX y en el XX, los lenguajes formales se investigaron con el intento
de formalizar las matematicas de un modo similar a como Euclides haba
formalizado la geometra. Las ideas fundamentales de Russel, Whitehead,
Hilbert, Church, y finalmente Goedel, permitieron establecer la imposibilidad de ese proyecto. Turing y Post en 1936 introdujeron un formalismo de
manipulacion de smbolos ( la denominada maquina de Turing ) con el que se
puede realizar cualquier computo que hasta ahora podemos imaginar. Esta
fue una va de comunicacion entre los problemas formales de la computacion
y de la matematica. La union permitio demostrar que no existe ninguna
16
CAPITULO 2. LENGUAJES
maquina de Turing que pueda reconocer si una sentencia es o no un teorema de un sistema logico formal; pero tambien permitio demostrar que si un
calculo puede explicitarse sin ambig
uedad en lenguaje natural, con ayuda
de smbolos matematicos, es siempre posible programar un ordenador digital
capaz de realizar el calculo, siempre que la capacidad de almacenamiento de
informacion sea la adecuada.
Desde el punto de vista de la ingeniera, los progresos en lenguajes de programacion han sido paralelos a los dise
nos de los nuevos ordenadores. Babbage ya escribio programas para sus maquinas, pero los desarrollos importantes
tuvieron lugar, igual que en los ordenadores, alrededor de la segunda guerra
mundial. Fue en esa epoca (justo despues de finalizada la guerra) cuando
Zuse publico su libro Calculo y programacion. En el aparece por primera vez
el concepto de operacion de asignacion. Zuse se planteo el problema siguiente: la expresion z = z + 1 es incorrecta para significar El nuevo valor de z
se obtiene sumando 1 al antiguo , e introdujo la expresion z + 1 z. Esta
sentencia de asignacion nunca se haba utilizado antes pues siempre se introduca una nueva variable cuando se proceda a una asignacion ( por ejemplo
y = z + 1). Este nuevo enfoque es fundamental puesto que el uso sistematico
de las asignaciones es lo que distingue la forma de pensar en ciencias de la
computacion y en matematicas.
2.3
Las m
aquinas de Von Neuman
Originalmente la programacion de un ordenador era directamente la reordenacion de los componentes del ordenador. La idea de producir un programa
de ordenador que se pudiera almacenarse en la memoria del ordenador se
debe a Von Neuman y aparecio en un informe que hizo sobre el ordenador
EDVAC. Von Neuman considero la posibilidad de que una palabra formada
por 32 bit fuera o bien un n
umero o bien una instruccion. Una instruccion se
codificaba por un grupo de bits adyacentes y considero sumas, multiplicaciones, transferencia de contenidos de memoria a registros, test, e instrucciones
de bifurcacion. As, un programa consistira en una secuencia de palabras en
forma binaria.
Necesidades practicas muy obvias llevaron a la utilizacion de mnemotecnicos
para programar las instrucciones, y posteriormente otro programador traduca los mnemotecnicos a lenguaje maquina. El paso siguiente deba ser
conseguir que fuera el ordenador el que tradujera esas codificaciones y tam-
17
Datos
ordenador
Resultado
Programa
ordenador
Programa
El ordenador deba considerarse como un procesador de informacion capaz de transformar un programa escrito en un lenguaje de alto nivel en un
programa en lenguaje maquina. A su vez, deba programarse el compilador
capaz de realizar esta transformacion.
2.4
En los a
nos 50 se realizaron varios compiladores primitivos y fue en 1957
cuando aparecio el primer compilador de FORTRAN. El compilador de FORTRAN (FORmula TRANslator) estaba dise
nado para traducir a lenguaje
maquina expresiones y operaciones matematica, e incluso permita la manipulacion de matrices. La aparicion del FORTRAN fue un gran cambio para
CAPITULO 2. LENGUAJES
18
19
Lenguajes
Lenguajes ensamblador
Lenguajes experimentales
de alto nivel
FORTRAN
ALGOL 58 y 60
COBOL
LISP
FORTRAN IV
COBOL 61 Extendido
ALGOL 60 Revisado
SNOBOL
APL ( como notacion solo)
1966 70 Ordenadores de diferentes
PL/I
tama
nos, velocidades, costes FORTRAN 66 (estandard)
Sistemas de almacenamiento COBOL 65 (estandard)
masivo de datos (caros)
ALGOL 68
S.O. multitarea e
SNOBOL4
interactivos
SIMULA 67
Compil. con optimizacion
BASIC
Leng. estandard ,
APL/360
flexibles y generales
1971 75 Micro ordenadores
Sistemas de almacenamiento PASCAL
masivo de datos peque
nos
COBOL 74
y baratos
PL /I
Progr. estructurada
Ingeniera del software
Leng. sencillos
1976 80 Ord. baratos y potentes
ADA
Sistemas distribuidos
FORTRAN 77
Prog. tiemporeal
PROLOG
Prog. interactiva
C
Abstraccion de datos
Prog. con fiabilidad
y facil mantenimiento
CAPITULO 2. LENGUAJES
20
2.5
Tipos de lenguajes
. . .
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 logicas que determinan una base de verdades con las
que han de ser coherentes las respuestas del programa.
Exite una diferencia grande en la programacion con un lenguaje u otro
seg
un sea interpretado o compilado, si bien esta distincion puede no ser inherente al lenguaje sino a su puesta en practica en un determinado ordenador.
Un lenguaje es interpretado cuando la transformacion de las instrucciones de
alto nivel a lenguaje maquina se realiza sentencia a sentencia seg
un se van
ejecutando. Un lenguaje es compilado cuando esta trasformacion se realiza
en bloque antes de que ninguna instruccion 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 secuencialmente puesto que las distintas partes del programa no se pueden verificar
hasta que entran en ejecucion.
En el caso mas com
un de lenguajes compilados, son varios los subprocesos
implicados en la transformacion del codigo de alto nivel en instrucciones
ejecutables por la UCP.
21
Programa
COMPILADOR
Leng. maquina
H
HH
HH
L. maquina
HH
H
HH
HH
MONTADOR
Codigo UCP
22
CAPITULO 2. LENGUAJES
datos que comparten todos los programas y asigna las direcciones comunes
donde cada uno debera procesar esos datos. Esta unificacion de direcciones
sera imposible si alg
un procedimiento supuestamente existente en otro subprograma no aparece o aparece de un modo no unvoco. Tambien sera causa
de error que alg
un dato compartido por subprogramas este declarado de modo distinto en cada programa. Estos errores son poco comunes y facilmente
detectable con los mensajes de error proporcionados por el montador. Sin
embargo, los errores mas comunes y mas tediosos de eliminar son aquellos
de programacion que dan lugar a sentencias sintacticamente correctas pero
que corresponde a acciones distintas a las deseadas. Desgraciadamente solo
se detectan en la ejecucion del programa.
En la actualidad existe la posibilidad de utilizar depuradores de programas (llamados en ingles debuggers por el origen de los errores en los ordenadores primitivos ) que permiten seguir la ejecucion paso a paso de un
programa aunque se obtenga el codigo maquina por compilacion. Esta herramienta facilita enormemente la depuracion de los programas pues permite
conocer o modificar el valor de los datos manipulados en el programa durante
la ejecucion.
Captulo 3
Algoritmos y resoluci
on de
problemas con el ordenador
3.1
Pasos en la resoluci
on
CAPITULO 3. ALGORITMOS
24
Dise
no del esquema del algoritmo que satisface las restricciones
del problema.
ALGORITMO: Procedimiento para resolver un problema paso a paso.
ALGORITMO: Conjunto de operaciones
que secuencialmente conducen a la respuesta
a una pregunta en un n
umero finito de pasos.
Especificacion del modo de proporcionar la respuesta al problema
planteado
2. Realizaci
on de la estrategia ideada para su soluci
on.
Captura de datos.
Generacion de las estructuras de datos adecuadas para el algoritmo que se va a utilizar.
Especificacion de los algoritmos.
Presentacion de los resultados.
Cuando la herramienta que se utiliza es el ordenador, la estrategia se
ha de realizar en tres pasos:
(a) DISENO.
(b) ESCRITURA.
(c) VERIFICACION.
3. Verificaci
on y an
alisis del rendimiento del procedimiento.
Prueba con casos sencillos.
Prueba con casos complejos.
Prueba con casos extremos.
Analisis del rendimiento en casos poco favorables y en casos tpicos.
Refinamiento de los algoritmos.
Refinamiento de la escritura de los algoritmos.
3.2. USO MULTIPLE
3.2
25
Uso m
ultiple
El uso m
ultiple de los procedimientos para la resolucion de problemas con
el ordenador implica que los procedimientos han de cumplir los siguientes
requisitos:
La resolucion de un mismo problema con distintos datos y en periodos
largos de tiempo obliga a:
1. Realizacion de procedimientos muy bien verificados.
2. Realizacion de procedimientos muy bien documentados y escritos
con un estilo claro.
La resolucion de un mismo tipo generico de problemas o variantes del
mismo, con reutilizacion de las herramientas desarrolladas, obliga a:
1. Realizacion de procedimientos modulares.
2. Realizacion de procedimientos muy bien documentados y escritos
con un estilo claro.
El uso del procedimiento dentro de un equipo por distintas personas
para resolver un mismo problema o variantes de el, obliga a:
1. Realizacion de procedimientos muy bien verificados.
2. Realizacion de procedimientos modulares.
3. Realizacion de procedimientos muy bien documentados y escritos
con un estilo claro.
3.3
El ejemplo de Josefo
CAPITULO 3. ALGORITMOS
26
'$
-1
&%
27
}
}
CAPITULO 3. ALGORITMOS
28
29
nodo = record
numero: integer;
siguiente: enlace
end;
var
j , n : integer;
individuo , temporal: enlace;
begin { Josefo }
{ Lectura del numero de personas en el circulo }
Readln(n);
{Se construye la lista circular }
{ Se genera el nodo de cabeza y se guarda en TEMPORAL
{ luego poder cerrar el circulo
new(individuo);
individuo^.numero := 1;
temporal := individuo;
para }
}
CAPITULO 3. ALGORITMOS
30
31
Si se descompone N de la forma N = 2m + l el u
ltimo elemento
que se elimina es el 2l + 1.
Refinamiento de la escritura de los algoritmos.
Uso m
ultiple del programa.
Verificacion.
La verificacion 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 podra incluirse
una especificacion del dato requerido y una verificacion del valor.
{ Lectura del numero de personas en el circulo }
writeln( Teclee el n
umero de elementos en el c
rculo );
Readln(n);
if (n <1) then begin
writeln( Ha de ser un numero mayor que cero);
Halt;
end; {endif}
Modularidad.
Documentacion.
Claridad de estilo.
El programa Josefo si se acompa
na de la adecuada documentacion
externa permite su utilizacion para distintos datos y en tiempos futuros.
Su modificacion para variantes del mismo problema es sencilla. Imaginemos que el problema se modifica y se eliminan elementos saltando
cada vez M individuos en vez de 2. Aparte de la modificacion en la
entrada de datos , la modificacion del algoritmo es mnima y sencilla
de localizar:
{se salta al ejecutor }
individuo:= individuo^.siguiente;
CAPITULO 3. ALGORITMOS
32
se modificara a:
Captulo 4
Pascal y Turbo Pascal
4.1
Caractersticas
CAPITULO 4. PASCAL
34
Existen varios dialectos locales del PASCAL , entre los que se encuentra el
TURBO PASCAL , que admiten todas las instrucciones del PASCAL estandard mas un subconjunto especfico de instrucciones normalmente pensadas
para aumentar las capacidades del lenguaje en un ordenador particular.
El TURBO PASCAL , de la compa
na Borland (Scotts Valley, California) es un dialecto del PASCAL que incluye ademas de las instrucciones del
PASCAL estandard una serie de instrucciones que permiten desarrollar aplicaciones especficas para ordenadores IBM PC o IBM PS y compatibles. No
es la u
nica de las versiones de PASCAL existente para estos ordenadores,
pero sin duda la mas extendida y probada. En la actualidad la version 6.0 de
este lenguaje incluye ademas del compilador un entorno integrado de desarrollo (IDE) que permite compilar, visualizar errores y depurar los programas
desde un mismo entorno.
4.2
El programa Pascal
35
y es equivalente a:
Program nombre ;
La primera lnea del programa es una instruccion PASCAL y como todas
ellas termina con el signo de puntuacion ; .
Despues de la identificacion del programa se han de situar las instrucciones declarativas del programa que sirven para especificar sin ambig
uedad el
significado de los terminos que se utilizaran en el programa. A continuacion
han de aparecer las instrucciones correspondientes al procedimiento que se
quiere realizar. Esta instrucciones estan encabezadas por Begin y terminan
con End y un punto. El programa mas peque
no y mas in
util que cumple las
reglas de estructuracion del PASCAL es:
Program nulo;
{ Programa ejemplo de la estructura
mas simple de un programa PASCAL }
Begin
(* No hace falta ninguna instruccion
para no hacer nada
*)
End.
En la parte reservada a declaraciones no se incluye nada pues nada se
necesita declarar. Todos los smbolos que se encuentren entre los parentesis
{ } son comentarios que sirven para hacer mas legible el programa. Tambien
los smbolos compuestos (* y *) sirven para delimitar el principio y fin de un
comentario. Al existir dos tipos de delimitadores de comentarios, es posible
realizar anidacion de comentarios. Por ejemplo,
{ Este es un comentario
(* sintacticamente *)
correcto en PASCAL }
4.3
Las palabras Program, Begin, End, Input, y Output, y otras que veremos mas adelante, son identificadores que permiten al compilador PASCAL
CAPITULO 4. PASCAL
36
Program nombre ;
(* Este es un ejemplo de la estructura de la
parte declarativa de un programa PASCAL *)
{4}
{5}
{6}
Const
nombre constante = valor ;
. . .
Type
nombre tipo = def tipo ;
. . .
Var
nombre variable : tipo dato ;
. . .
Begin
. . .
{7}
{8}
{9}
{10}
{11}
37
4.4
If (a > 0) Then
b := a *
a * a ;
If (a > 0) Then
Begin
b := a * a ;
b := b * a
End;
CAPITULO 4. PASCAL
38
4.5
Diagramas de sintaxis
-
E
E
E
E
E
E
E
E
E
Begin
Instruc. senc.
J
J
J
End
;
Begin
b := a * a ;
b := b * a ;
End;
Captulo 5
Datos
5.1
En este tema vamos a ver las instrucciones necesarias en un programa PASCAL para especificar los tipos de datos que se van a manejar. Los datos se
almacenaran en la memoria del ordenador en una determinada posicion, pero
para referirnos a ellos se utilizan nombres que el programador elige libremente. El lenguaje PASCAL permite utilizar comodamente una gran variedad
de tipos de datos, pero en este tema solo vamos a ver los mas sencillos.
3.14159
6
nombre
PI
contenido
7161
direccion
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 varen durante la ejecucion del programa, se trata de
una variable.
Program Uno;
Const
39
CAPITULO 5. DATOS
40
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 palabras reservadas en PASCAL para especificar datos o acciones. NO pueden
utilizarse:
Palabras reservadas
Begin
1.23E2
123
While
Cos
2ABC
precio/calidad
signo*valor
41
coco
xxx2
pero se deben utilizar nombre que tengan relacion con el dato que van a
contener. Por ejemplo,
angulo
lado
vertice
CaraOpuesta
Nombre_Compuesto
En el ejemplo Uno podemos ver que el tipo de datos que van a contener
las constantes se especifica por los valores que se asignan.
Program Uno;
Const
PI = 3.14159;
UNIDADES = radianes ;
Var
n , m : Integer;
z
: Real;
Begin
. . . .
Sin embargo, el tipo de las variables ha de indicarse explcitamente con indicadores PASCAL tales como Integer, o Real. Estos se refieren a dos tipos
de datos numericos entre los posibles en PASCAL .
5.3
Tipos de datos
CAPITULO 5. DATOS
42
Integer
Byte
ShortInt
Word
LongInt
N
umeros reales:
Real
Double
Single
Extended
2. Caracteres y alfanumericos.
Char
String
3. Valores de la logica de Boole
Boolean
Integer
Es el tipo de variable que se usa para n
umeros enteros ( sin parte
decimal ) con signo. Para una variable Integer se reservan dos bytes
(16 bits) en memoria y puede almacenar n
umeros enteros en el rango
entre
32, 768(215 )
+ 32, 767(215 1)
43
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
umeros 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, solo se reserva 1 byte de memoria. En
las variables tipo Byte se pueden almacenar n
umeros enteros sin signo
y por tanto tendran que estar limitados entre 0 y 255(28 1).
Real.
Para almacenar n
umeros reales ( con parte decimal ) o enteros que
excedan el lmite permitido por LongInt , se ha de utilizar el tipo de
variable Real . A este tipo de datos tambien 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
umero algo rebuscada que estudiaremos con los errores numericos, se pueden almacenar n
umeros entre 2, 91039 y 1, 71038
tanto positivos como negativos. Debido a la representacion interna
utilizada, se almacenan con igual precision (7 u 8 cifras significativas)
todos los n
umeros reales en el rango permitido.
Las operaciones con n
umeros en la representacion en coma flotante
son mucho mas lentas que entre n
umeros enteros representados directamente con su valor en base 2. Un coprocesador matematico (como
los 80X87) se dedica especficamente a estas operaciones. El TURBO
PASCAL permite una coleccion de datos para tratar eficientemente con
n
umeros reales cuando se dispone del coprocesador matematico. Cuando no se dispone de el, las operaciones se pueden emular por software
aunque son mas lentas. Esta coleccion de tipos de datos son:
Single
El tipo de datos Single es un Real mas corto (4 bytes) con el
mismo rango de variacion que el Real , pero con menos cifras
significativas.
Double
CAPITULO 5. DATOS
44
45
CAPITULO 5. DATOS
46
5.4
5.5
Inicializaci
on de los datos
5.6
Asignaci
on de las constantes
47
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;
5.7
Asignaci
on de los distintos tipos de variables
CAPITULO 5. DATOS
48
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
{13} nombre
{14} nombre
{15} numero
{16} numero
{17} letra
{18} letra
end.
correctas }
:= Calle;
:= Paloma Negra ;
:= Direccion;
:= 97;
:= Puerta;
:= A;
Las instrucciones {11} y {12} son incorrectas porque asignan a una variable
del tipo String una constante del tipo Char. No obstante, estas instrucciones no dan lugar a error en PASCAL porque el compilador interpreta las
variables Char como un subconjunto de las String (El espacio reservado en
49
50
CAPITULO 5. DATOS
Captulo 6
Intercambio b
asico de datos y
resultados
6.1
52
6.2
{1}
{2}
{3}
Program Uno;
{ Cuadrado de un numero entero }
Var
base , resultado : integer;
Begin
Read(base);
resultado := base * base;
Write(resultado);
End.
53
{1}
{2}
{3}
Program Dos;
Var
resultado, base , altura : Integer;
Begin
Read(base,altura);
resultado := base * altura;
Write(Area del cuadrado: ,resultado);
End.
54
6.3
Formatos
55
que han de ocupar la parte decimal (despues 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.
dara como resultado
Area del triangulo:
837
6.4
1.0E+0005
1.0E+0005
1.020E+0005
1.02030E+0005
102030.4
102030.4
102030.40
56
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 sera:
Resultado del calculo.
Area del triangulo:
837
57
12
la salida sera:
Resultado del calculo.
Area del triangulo:
15
58
Captulo 7
Acciones
7.1
Operaciones b
asicas.
Una vez conocidos los modos basicos que existen en PASCAL para almacenar
datos en la memoria del ordenador y conocido el modo basico de comunicacion con el usuario del programa, pasamos a estudiar que operaciones se
pueden realizar con los datos.
7.1.1
Operadores aritm
eticos y expresiones aritm
eticas.
3. + 5.;
a - 2.;
b * a * 6.;
-b / 12.;
CAPITULO 7. ACCIONES
60
formato de instruccion,
variable1 := operando1
operando2;
se asigna a la variable variable1 el resultado de la operacion aritmetica correspondiente con las convenciones usuales de la aritmetica. Tanto operando1
como operando2, pueden ser constantes o variables. Cuando se desea operar
con mas de dos datos hay que especificar claramente y sin ambig
uedad el
orden en que se quieren realizar las operaciones. Para ello, podemos ayudarnos de los parentesis con el mismo fin con el que se usan en las expresiones
aritmeticas. Por ejemplo, la siguiente instruccion
b:= ( -37.0 * (a - 2.) ) / (a + 5.);
carece de ambig
uedad. No obstante, el PASCAL tiene una prioridad establecida para el orden de las operaciones:
1. mas y menos monarios.
2. parentesis.
3. multiplicacion y division.
4. suma y resta.
Las siguientes instrucciones son equivalentes:
b:= -27.0 * c + 35. / a + b + c;
b:= ( (-27.0) * c ) + ( 35. / a ) + b + c ;
b:= ( -27.0 * c ) + ( 35. / a ) + b + c ;
y la forma concreta en la que el programador debe escribirla es aquella que
resulte menos confusa. Un error com
un entre principiantes es escribir la
instruccion {i} queriendo escribir la {ii} :
{i}
{ii}
{iii}
b:= a * 27.0 / b + c ;
b:= a * 27.0 / ( b + c ) ;
b:= ( a * 27.0 / b ) + c ;
7.1. OPERACIONES BASICAS.
7.1.2
61
Funciones aritm
eticas.
En PASCAL estan definidas funciones que permiten realizar calculos matematicos muy frecuentes u operaciones numericas muy u
tiles para transformar expresiones aritmeticas en sentencias PASCAL . En PASCAL las
funciones son llamadas a procedimientos de calculo que devuelven un valor.
Si aparecen en una expresion aritmetica, las operacion se realiza con el resultado de evaluar la funcion. Si suponemos que se utiliza la funcion para una
asignacion,
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
x1
Random
Real
N
umero aleatorio, y[0, 1]
Random(x)
Integer
Integer
N
umero aleatorio, y[0, x]
Round ( x )
Real
Integer
x redondeado al entero mas 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 trigonometricas que no estan incluidas, se calculan facilmente
a partir estas. Por ejemplo,
tan1 := Sin(x) / Cos(x);
a := Sin(x);
tan2 := a / Sqrt ( 1.0 - a * a ) ;
CAPITULO 7. ACCIONES
62
7.1.3
Aritm
etica entera y real.
Integer;
Real;
j := 2333;
i := j * 23;
7.1. OPERACIONES BASICAS.
{3}
(*
{4}
*)
{5}
{6}
{7}
{8}
{9}
{10}
end.
63
Writeln(i:9);
i := 2333 * 23;
z := j * 23;
Writeln(z:9:0);
z := 1.0 * j * 23 ;
Writeln(z:9:0);
z := 2333 * 23;
Writeln(z:9:0);
es:
-11877
-11877
53659
53659
La instruccion {2} es aparentemente correcta, pero como el resultado de
la multiplicacion excede la capacidad de un Integer (32767), el resultado
de la operacion es un n
umero entero, pero absurdo. Sin embargo, la {4} es
claramente incorrecta y el compilador PASCAL lo detecta al intentar almacenar en el lugar de memoria reservado para i el producto, en vez de generar
el codigo para realizar la multiplicacion durante la ejecucion.
La {5} es solo aparentemente correcta, puesto que es similar a la {2}. Si
bien el resultado de la operacion se quiere almacenar en una variable Real , el
compilador interpreta que la expresion aritmetica se puede realizar con datos
enteros y genera codigo tal que los resultados intermedios se almacenaran en
registros de 2 bytes. El resultado : un desastre, el dato que se almacena
finalmente en la variable real es identico al anterior. Sin embargo, si en la
expresion se incluye cualquier operando Real , el compilador asume que se
trata de una operacion que ha de realizarse con aritmetica real, y utilizara
registros apropiados para esa aritmetica. La instruccion {7} es correcta, y
solo difiere de la {5} en la multiplicacion por 1.0, algo matematicamente
irrelevante pero no computacionalmente. Hay que tener siempre presente
que el modo con el que se van a realizar las operaciones de una expresion
CAPITULO 7. ACCIONES
64
Div
es j/i cuando j es m
ultiplo de i, y la parte de entera de j/i en el caso
contrario.
En el programa Tres ,
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.
las instrucciones {2} y {4} generan el mismo resultado, pero distinto al de la
{6}. La expresion aritmetica en {6} es el argumento de la funcion Trunc()
y la presencia del operador / indica que se ha de realizar aritmetica de
n
umeros reales.
Cuando se quieren utilizar datos Real en expresiones con aritmetica de
n
umeros enteros, lo mas apropiado es utilizar la funciones de transformacion
de tipo, Round() o Trunc() , para homogeneizar el tipo de los operandos.
7.1. OPERACIONES BASICAS.
65
M od i
es 0 cuando j es m
ultiplo de i, y el resto de la division j/i en el caso contrario.
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.
La salida del programa Cuatro es:
2
14
14
7.1.4
Operadores l
ogicos.
CAPITULO 7. ACCIONES
66
operadores es:
<>
>
<
<=
>=
Operador Condicion
=
a=b
<>
a 6= b
>
a>b
<
a<b
<=
ab
>=
ab
En el caso de que de que a y b sean caracteres, las operaciones de comparacion
se realizan sobre el valor entero del caracter ASCII correspondiente.
Ejemplos de utilizacion 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 BASICAS.
{7}
{8}
{10}
{11}
end.
67
a := Sin(x);
tan2 := a / Sqrt ( 1.0 - a * a ) ;
quizas := ( tan1 = tan2 );
Writeln(quizas);
(* FALSE *)
Merece la pena recordar una vez mas que no se pueden trasladar directamente las expresiones matematicas a las sentencias de un programa. Por
ejemplo, en la instruccion {10} se asigna a quiz
as el valor FALSE , si bien
las expresiones utilizadas en las instrucciones {6} y {8} para calcular la
tangente son matematicamente equivalentes. Debido a la utilizacion de una
representacion finita de los n
umeros reales ambos valores seran ligeramente
distintos. La comparacion para averiguar la similitud de n
umeros reales se
suele hacer utilizando la diferencia relativa:
quizas :=
<=
0.000001;
operando
donde tanto operando como el resultado de la operacion son datos del tipo
Boolean. El resultado, es la negacion del operando:
a
Not a
True False
False True
El resto de los operadores se utilizan seg
un la forma:
A
And
Or
Xor
CAPITULO 7. ACCIONES
68
True False
False True
False False
True True
True False
False True
True True
False False
True False
False True
True True
False False
7.1.5
A And B
False
False
False
True
A Or B
True
True
True
False
A Xor B
True
True
False
False
Expresiones l
ogicas.
Denominamos Expresiones logicas a las operaciones que se realizan con datos Boolean. Estas operaciones pueden encadenarse de un modo bastante
complejo. Un ejemplo de utilizacion de estas expresiones es el siguiente:
Supongamos que tenemos que escribir un programa para determinar si
un punto se encuentra en la interseccion de dos rectangulos,
7.1. OPERACIONES BASICAS.
69
CAPITULO 7. ACCIONES
70
{7}
{8}
{9}
end.
Las instrucciones {2} y {3} se podran haber condensado en una sola instruccion similar a la {6}.
Cuando en una expresion se combinan operadores logicos y aritmeticos
hay que utilizar generosamente los parentesis o llevar mucho cuidado con el
orden de prioridad establecido por el PASCAL para la aplicacion de operadores:
Los operadores aritmeticos se aplican siempre antes que los logicos.
Por ejemplo, la expresion
(37 * 4
se eval
ua a True y los parentesis son estrictamente necesarios. De no existir
el primer juego de parentesis el operador And tendra a su izquierda un dato
Integer y a su derecha un dato Boolean, lo que es incorrecto. De no
existir el segundo juego de parentesis habra tambien una disparidad de tipos
de datos algo mas compleja que se analizara mas adelante.
Como en el caso de los operadores aritmeticos, en los logicos tambien los
monarios se aplican primero, y en esta expresion el operador Not se aplica
antes que el And.
El uso generoso de los parentesis en las expresiones que mezclan operadores logicos y aritmeticos esta recomendado por otra razon mas:
Los operadores And, Or , y Xor pueden ser aritmeticos o logicos
seg
un el tipo de operandos sobre los que act
uen.
Esto es as porque como veremos a continuacion tambien estan pensados para
realizar manipulacion de bits.
7.1.6
Manipulaci
on de bits.
7.1. OPERACIONES BASICAS.
71
And
Or
Xor
La operacion And entre estos dos datos da como resultado el dato Byte :
0
cuyo valor decimal es 12. Si sobre los datos originales se realiza la operacion
Or el resultado es:
0
CAPITULO 7. ACCIONES
72
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.
Existen otros dos operadores de manipulacion de bits : Shl (Shift left) y
Shr (Shift right). El resultado de
(
Shl
Shr
a2
a3
a4
a5
a6
a7
a8
B, el resultado de
B :=
A Shl 3;
es,
a4
a5
a6
a7
a8
y, C, el resultado de
C :=
B Shr 7;
7.1. OPERACIONES BASICAS.
73
es,
0
a4
CAPITULO 7. ACCIONES
74
y el 32767 como
0111111111111111.
7.2
Sentencias de control.
If datoBoolean
Then
accion1
o bien,
If datoBoolean
Then
accion1
Else
accion2
donde datoBoolean es una variable Boolean o una operacion cuyo resultado
es una dato Boolean, accion1 y accion2 son instrucciones PASCAL que
pueden ser tanto simples como compuestas.
El efecto de esta sentencia de control es el siguiente: si datoBoolean es
True se procede a realizar la instruccion accion1; en el caso de que sea False
y este presente la parte Else, se procede a realizar la instruccion accion2.
En el primero de los casos el esquema de la bifurcacion sera:
75
Boolean
?
HH
? H
b
b ""
b"
Cierto?
accion1
Falso
?
Continuar
accion2
accion1
Continuar
?
En el programa Nueve tenemos un ejemplo de utilizacion de esta construccion. Ambas son equivalentes: en la primera se realiza la comparacion en la
construccion If, mientras que en la segunda se utiliza una variable Boolean
auxiliar.
Program Nueve;
Var
positivo : Boolean;
n : Integer;
Begin
Readln (n);
If n >= 0
CAPITULO 7. ACCIONES
76
Then
Writeln( Se trata
Else
Writeln( Se trata
positivo := ( n >= 0 ) ;
If positivo
Then
Writeln( Se trata
Else
Writeln( Se trata
de un numero positivo )
de un numero negativo );
de un numero positivo )
de un numero negativo );
End.
Las acciones que se ejecutan despues de la comprobacion del dato Boolean
pueden ser instrucciones sencillas o compuestas. En el programa Diez podemos ver un ejemplo de utilizacion con una instruccion compuesta:
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);
If x > 0.0 then
begin
Writeln( Raiz cuadrada: );
y := Sqrt(x);
Write(y)
end
Else
Writeln( Numero negativo.);
End. { Diez }
Con esta estructura If ... Then ... Else tambien se pueden realizar decisiones m
ultiples. Un modo muy frecuente de utilizacion es la encadenacion
de estructuras de la forma:
77
If datoBoolean1
Then
accion1
Else
If datoBoolean2
Then
accion2
. . .
En el programa Once se utiliza una concatenacion de estructuras para realizar una eleccion m
ultiple.
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 bifurcacion m
ultiple puede llegar a ser difcil de leer y el
PASCAL proporciona una estructura mas legible para aquellos casos en los
que la bifurcacion m
ultiple se realiza mediante comparacion de datos sencillos
ordinales (por tanto ni Real, ni String). Esta es la estructura Case que
tiene la siguiente sintaxis:
CAPITULO 7. ACCIONES
78
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 especificacion de los valores. Esta especificacion 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 mas 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
1 :
2 :
3 :
4 :
5 :
Else
Of
Writeln(
Writeln(
Writeln(
Writeln(
Writeln(
Uno );
Dos );
Tres );
Cuatro );
Cinco );
7.3. SENTENCIAS DE REPETICION.
79
7.3
Sentencias de repetici
on.
Hay quien opina que la programacion es una actividad que nunca puede resultar tediosa o repetitiva, ya que todo aquello que ha de hacerse repetidamente
CAPITULO 7. ACCIONES
80
puede programarse en una instruccion simple para que sea el ordenador quien
lo haga repetidas veces. De hecho, las sentencias de repeticion son generalmente las responsables de la utilidad del ordenador. Se trata de instrucciones
que gobiernan la realizacion de tareas repetitivas mientras no sea cierta la
condicion que se imponga para la finalizacion.
En PASCAL existen tres estructuras de repeticion que son las construcciones For Do, Repeat Until, y While Do.
La primera de ellas, la construccion For Do, tiene la siguiente sintaxis:
For identificador := principio To final Do
accion
donde identificador es una variable que puede almacenar un dato ordinal,
principio es el valor que se le asigna a esa variable antes de realizar la accion,
final es el valor maximo que puede alcanzar la variable antes de finalizar la
accion, y accion es la instruccion, simple o compuesta, del PASCAL que se
repetira incrementando en uno cada vez el valor de identificador. Si se trata
de una sentencia compuesta, tendra que utilizarse la estructura Begin-End
para identificar el principio y el fin.
Existe tambien la opcion equivalente
For identificador := principio Downto final Do
accion
en la que el valor del identificador se decrementa en uno cada vez que se
realiza la accion.
En el programa Catorce tenemos la aplicacion de esta estructura para
el calculo del factorial.
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 REPETICION.
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.
La limitacion basica de la estructura For-Do es que la accion que implcitamente
se realiza cada vez es simplemente el aumento o decremento de una variable ordinal. No obstante, hay que tener presente que variables ordinales no
son solamente los Integer. En el programa Quince vemos como se puede
utilizar la estructura con una variable Char.
Program Quince;
Var
i : Char;
Begin
(* Programa que escribe el alfabeto al reves *)
Writeln();
For i:=Z Downto A do
Write( ,i);
End.
La variable que se utiliza como contador en la estructura For-Do puede
modificarse tambien en la accion que se repite, pero hay que ser extremadamente cuidadoso porque de lo contrario podemos generar un bucle infinito.
Si en el siguiente programa no se realizara la modificacion a un m
ultiplo de
tres, se podra caer en un bucle infinito (con probabilidad 0.33333).
Program Dieciseis;
Var
CAPITULO 7. ACCIONES
82
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.
Aceptando que el programa anterior es siempre correcto, es facil deducir
si la comprobacion sobre el estado del ndice se realiza antes o despues de
incrementar el ndice.
Una estructura muy similar a la For-Do pero mas versatil es la RepeatUntil. Su sintaxis es:
Repeat
accion1;
accion2;
. . .
Until DatoBoolean
y con ella se especifica que se repita el conjunto de acciones situado entre
el Repeat y el Until mientras que no sea True el valor de DatoBoolean .
Las acciones se realizan al menos una vez porque la verificacion sobre el dato
Boolean se hace despues que las acciones. As, en el siguiente programa
el juego no se interrumpe inmediatamente despues de teclear el 0. Por el
contrario la jugada se repite y luego se termina.
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 REPETICION.
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.
Sin embargo, en la estructura While-Do se realiza la comprobacion de
la condicion que ha de finalizar la repeticion antes de ejecutarse la accion.
Su sintaxis es:
While DatoBoolean Do
accion
donde DatoBoolean es una expresion cuyo resultado es un dato Boolean,
y accion es una instruccion PASCAL (sencilla o compuesta) que se repetira
mientras DatoBoolean se eval
ue a True.
El programa Dieciocho es una modificacion del Diecisiete en el que
con el uso de la estructura While-Do se verifica la condicion de fin del juego
antes de sortear el n
umero.
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
CAPITULO 7. ACCIONES
84
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 eleccion de una
de las tres estructuras se hara siempre considerando la claridad y facilidad
de programacion.
En PASCAL tambien existe la sentencia de control no estructurado Goto,
pero no la consideraremos pues en este curso se pretende que el alumno
ejercite la programacion estructurada. Sin embargo, si que consideramos la
funcion Exit cuya efecto es interrumpir la ejecucion del bloque en la que
se encuentra. Si se trata del programa principal, producira la interrupcion
de la ejecucion del programa. En el programa Diecinueve se modifica el
Diecisiete para interrumpir el juego haciendo uso de la funcion 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)
85
Else
Writeln( Si );
Until n = 0 ;
End.
7.4
Manipulaci
on de los datos STRING.
CAPITULO 7. ACCIONES
86
y la salida que produce es:
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
Captulo 8
Modularidad
8.1
Con las estructuras vistas hasta ahora del PASCAL se podran construir
programas que realizaran tareas muy complejas pero con escasa legibilidad.
Un modo muy com
un, y generalmente muy efectivo, de resolver un problema
es desmenuzarlo en una serie de problemas mas sencillos y resolver despues
cada uno de ellos. Es la estrategia que ha recibido el nombre dividir y vencer
o dise
no Top-Down. Desde el punto de vista de la legibilidad es deseable
que un programa de ordenador pueda estructurarse siguiendo lo mas posible
el esquema conceptual que se ha pensado utilizar para resolver el problema.
Por ejemplo, supongamos que se trata de escribir un programa que calcule
la suma de los n primeros terminos de una sucesion geometrica de razon r y
cuyo primer termino es a. Para ello pensamos utilizar la expresion:
n1
X
i=0
ari =
a(1 rn )
1r
CAPITULO 8. MODULARIDAD
88
8.2
Procedimientos
8.2. PROCEDIMIENTOS
89
Parte declarativa
Begin
Bloque de sentencias del procedimiento
End;
La parte declarativa del procedimiento tiene el mismo fin que en un programa y en ella se definen tipos de datos, variables y constantes como en un
programa y tambien, si as se requiere, procedimientos y funciones que sean
necesarios para la realizacion de este Procedure. En el bloque principal
del procedimiento se escriben las sentencias PASCAL que constituyen el algoritmo que ha de realizar, y en el se pueden utilizar datos definidos en su
parte declarativa, en la parte declarativa del programa principal o bien que
aparecen como argumentos del procedimiento. Estos argumentos se utilizan
para comunicar valores de datos al procedimiento desde el bloque donde ha
sido llamado. Cuando se llama al procedimiento, estos argumentos van separados por comas. En la declaracion del procedimiento los argumentos se
especifican de un modo muy parecido a como se especifica el tipo de datos
en la declaracion de las variables de un programa. Los datos de un mismo
tipo van separados por coma y se utiliza el punto y coma para separar datos
de distinto tipo. A continuacion de los argumentos se especifica el tipo de
variable. Por ejemplo, al procedimiento SacarResultados se le llama con el
argumento suma que es un dato Real. Este procedimiento se puede escribir
as:
En el argumento se especifica el nombre que se va a utilizar en el procedimiento y tambien de que tipo de dato se trata. El nombre no ha de coincidir
con el utilizado en el bloque original, puesto que la identificacion de datos la
realiza el compilador por el orden en el que aparecen en el argumento y no
por el nombre.
CAPITULO 8. MODULARIDAD
90
8.3
Funciones
DE LAS VARIABLES
8.4. AMBITO
DE DEFINICION
91
{9}
For i := 2 to exponente Do
{10}
z := z * base;
{11}
Poten := z
{12}
End;
End; { Poten }
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 continuacion, se especifica que el valor que ha de
devolver la funcion al bloque donde ha sido llamada es Real. Para realizar
el calculo se necesitan otras dos variables y se definen en la parte declarativa.
En las instrucciones {2}, {5} y {11}, aparece el nombre de la funcion en
la parte izquierda de una asignacion y es en ellas donde se especifica el valor
que puede devolver la funcion. La llamada a Poten desde el procedimiento
CalcularExpresi
on :
{Calculo de la expresion para la suma de la serie }
Procedure CalcularExpresion ;
Begin { CalcularExpresion }
suma := a * ( 1.0 - Poten(r,n) ) / ( 1.0 - r) ;
End; { CalcularExpresion }
se realiza dentro de una expresion aritmetica.
8.4
Ambito
de definici
on de las variables
CAPITULO 8. MODULARIDAD
92
8.5
8.5. PASO DE VALORES POR CONTENIDO O DIRECCION
93
CAPITULO 8. MODULARIDAD
94
z := base;
For i := 2 to exponente Do
z := z * base;
Poten := z
End;
End; { Poten }
{Calculo de la expresion para la suma de la serie }
Procedure CalcularExpresion ;
Begin { CalcularExpresion }
suma := a * ( 1.0 - Poten(r,n) ) / ( 1.0 - r) ;
End; { CalcularExpresion }
Procedure SacarResultados(resultado : Real);
Begin { SacarResultados }
Writeln();
Writeln(La suma de la series es: , resultado:10:6);
End; { SacarResultados }
Begin { SumaProgesion }
{ Se utiliza la expresion:
LeerDatos(n,a,r);
CalcularExpresion;
SacarResultados(suma);
End. { SumaProgresion}
El ambito de las variables y la diferencia entre el paso de argumentos por
referencia o contenido se puede apreciar bien con el siguiente programa Uno:
Program Uno;
Var
a , b ,c : Integer;
8.5. PASO DE VALORES POR CONTENIDO O DIRECCION
95
{1}
{2}
{3}
{4}
{5}
Begin
a := 3;
b := 5;
Writeln( Antes :
Escribe(Durante:
Escribe(Durante:
Writeln(Despues:
End.
,
,
,
,
c:=
a:4
a ,
a ,
a:4
7;
, b:4 , c:4 );
b );
b );
, b:4 , c:4 );
3
6
12
12
5
10
10
5
7
7
7
7
CAPITULO 8. MODULARIDAD
96
: String;
: Integer;
: Integer );
8.6
Definici
on diferida
El compilador transforma las ordenes PASCAL a lenguaje maquina empezando por el principio del programa y acabando por el End. Por tanto,
cualquier procedimiento o funcion ha de declarase antes de ser utilizado para
que el compilador cuando llegue al identificador correspondiente sepa interpretar que instrucciones de la Unidad Central de Proceso debe generar. En
general esto implica un orden mnimo a la hora de escribir el programa y llevar cuidado de no definir modulos en lneas posteriores a las que los utilizan.
Sin embargo, puede haber ocasiones en las que se requiera que un modulo
llame a otro modulo y que a su vez llame al primero. En este caso sera imposible definir los dos antes de referirlos y por tanto PASCAL proporciona la
palabra reservada FORWARD para seguir al nombre y argumentos de un
procedimiento o funcion cuyo contenido se especificara en lineas posteriores.
En el programa Dos se ilustra el uso de FORWARD :
Program Dos;
Procedure B ( C : Char); FORWARD;
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. MODULOS
Y SUBMODULOS
97
Begin { Dos }
A ( A );
End. { Dos }
El procedimiento B es necesario para definir el contenido de A, y a su vez
A es necesario para definir el algoritmo siniestro que se explicita en B. El
circulo vicioso se rompe adelantando al compilador que B es un Procedure
que toma como argumento un dato Char. Cuando el compilador luego
analiza el procedimiento A reconoce el identificador B y el hecho de que
tome un argumento Char. Entonces, podra generar codigo de la UCP en el
que redireccione el calculo a la direccion de memoria que ya tiene reservada
para el modulo B. Posteriormente, cuando analice la especificacion de los
pasos a realizar en el modulo B generara el codigo UCP que constituira
el calculo que se ha de realizar en el procedimiento B. Si todo esto parece
enrevesado mas lo es el modo en que se ha programado el algoritmo que
realiza el programa Dos. Ademas, carece de ning
un comentario para que
se pueda calificar como un claro ejemplo de mala programacion. El alumno,
realizando las instrucciones del programa a mano tardara alg
un minuto en
conocer cual es la salida del programa.
8.7
M
odulos y subm
odulos
Procedure Eco;
Var
s : String;
Function Final : Boolean;
Var
c : Char;
Begin { Final }
CAPITULO 8. MODULARIDAD
98
8.8. RECURSIVIDAD
99
que se haya escrito un programa que realice un bucle infinito. Esta posibilidad
existe puesto que el PASCAL permite la recursividad en la programacion:
algo que bien utilizado puede aumentar la legibilidad de los programas.
8.8
Recursividad
CAPITULO 8. MODULARIDAD
100
* Fac ( n - 1 )
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 solo sera capaz de calcular
hasta el factorial de n
umeros peque
nos pues crece muy rapidamente y a partir
de 7! se desborda la capacidad de almacenamiento de ese dato. Por lo demas,
se trata de un programa de facil lectura. En la instruccion {2} consideramos
el valor de terminacion de las llamadas recursivas. Sin ella, el programa no
acabara nunca. En la instruccion {4} estamos diciendo que en esa llamada
se asigne a la funcion Fac el valor que se obtiene multiplicando el valor actual
8.8. RECURSIVIDAD
101
102
CAPITULO 8. MODULARIDAD
Captulo 9
Datos con estructura
Un programa de ordenador esta constituido por algoritmos que manejan la
informacion almacenada en la memoria del ordenador. El modo en el que
esta informacion puede ser referenciada por el programador es esencial para
la eficacia y legibilidad de los algoritmos. Hasta ahora hemos visto tipos de
datos muy elementales. En este tema se consideran opciones mas avanzadas
al estudiar los tipos de datos definidos por el programador y datos que poseen
estructura interna.
9.1
104
donde Indentificador1,Indentificador2, etc., son los nombres que se han asignado a los nuevos tipos de datos , y Untipo1,Untipo2, etc., es la especificacion
de que tipo de dato se trata.
La utilizacion mas trivial que se puede pensar para esta posibilidad es la
de renombrar la denominacion de los tipos de datos estandard. Por ejemplo,
Program Uno;
Type
Entero = Integer;
Var
i,n : Entero;
. . . . . .
con estas declaraciones se informa al compilador de que cuando se definen las
variables i,n como Enteros , nos referimos a datos Integer. Obviamente,
la posibilidad de definicion de tipos de datos existe para realizar cosas mas
u
tiles que simplemente renombrar. Por ejemplo, se puede utilizar para definir
variables enteras con un rango acotado. En el programa Uno se utiliza esta
posibilidad:
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.
Se define el tipo de dato Nota que es un entero en el rango entre 0
y 10. La primera de las instrucciones del programa es una orden para el
compilador de TURBO PASCAL , que le indica que genere codigo de UCP
en el que se realice comprobacion de rangos de variables durante la ejecucion
9.2. ENUMERACIONES
105
del programa. Con esta opcion, si se teclea un dato fuera del rango definido
para Nota aparecer? un mensaje de error Run time. Sin esa opcion del
compilador, no aparecera ning
un 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
umero limitado de datos. En el tipo
Byte, por ejemplo, n
umeros entre el 0 y el 255. Si el programador necesita
utilizar un conjunto limitado de datos puede referirse a ellos estableciendo
explcitamente una relacion entre cada dato y uno de los valores que puede tomar un tipo de dato limitado. Por ejemplo, si queremos referirnos a
los meses de a
no en un programa se puede establecer una relacion entre un
n
umero y el mes, empezando con el 1 para Enero y siguiendo hasta 12 con
el orden del calendario. Dado el uso cotidiano de esta relacion resultara
muy facil escribir y leer programas en los que se utilizara una variable mes
del tipo Byte. Siempre que mes tomara el valor 2 el programador inmediatamente interpretara ese valor como el mes de Febrero. Sin embargo, en
otras muchas ocasiones no existira tal correlacion 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 facil elegir una ordenacion entre ellos que permita establecer
una relacion facilmente comprensible entre un n
umero, por ejemplo del 0 al
4, y cada color. Para estos casos el PASCAL permite establecer esa relacion
en la definicion 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 parentesis y separadas por comas. En el programa Dos
tenemos un ejemplo de su utilizacion:
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
Naranja
End;
Writeln(Ord(i));
End.
El tipo de dato Color se define como la enumeracion de esos cinco colores.
La variable i se define como un Color y por tanto puede tomar el valor
Amarillo. El compilador establece una relacion unvoca entre cada uno de
los posibles valores y un n
umero. Por tanto sobre este tipo de dato se puede
operar con las funciones que admiten argumentos ordinales, entre otras Succ
y Pred. Este programa escribira primero : Se trata de Naranja porque el
sucesor del valor Amarillo es Naranja. De hecho, la relacion que establece
el compilador entre valores y n
umeros es sencillamente el n
umero de orden,
empezando por 0, en el que aparece cada valor en la enumeracion que se
utiliza para declarar el tipo. Por tanto, el programa acabara su ejecucion
escribiendo el n
umero 1.
Este tipo de datos enumerado se suele utilizar para facilitar la tarea de
programar (escritura y lectura), y no se pueden leer o escribir. Por ejemplo,
la instruccion Readln(i); no sera valida en el programa Dos. Sin embargo,
se puede establecer la relacion entre un ordinal y el valor de un tipo de dato
enumerado que aparece en ese lugar en la definicion. Por ejemplo, la primera
instruccion del programa Dos se podra reemplazar por
i:= Color(1);
Otra utilidad de los tipos de datos enumerados es la formacion de conjuntos con la posibilidad que ofrece el PASCAL de operaciones entre conjuntos.
9.3
Conjuntos
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
NomElemento In NomConjunto
donde NomElemento es el nombre del elemento sobre el que se inquiere y
NomConjunto el conjunto. El resultado de esta operacion es un dato Boolean, y se eval
ua a True solo si el elemento pertenece al conjunto.
En el programa Tres tambien se ilustra la asignacion de valores a los
conjuntos, si bien falta a
nadir que tambien se puede asignar el conjunto
vaco ([] ).
Los operadores aritmeticos y logicos cuando act
uan 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 := A * B
C := A - B
{C : conjunto
{C : conjunto
{C : conjunto
union de A y B}
interseccion de A y B}
diferencia de A y B}
Tambien se pueden comparar los conjuntos con los operadores logicos 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
verdad
verdad
verdad
:=
:=
:=
:=
A
A
A
A
=
B
<> B
<= B
=> B
{verdad es True si A y
{verdad es True si A y
{verdad es True si A es
{verdad es True si B es
B son iguales}
B son distintos}
subconjunto de B}
subconjunto de A}
9.4
Arrays
9.4. ARRAYS
109
110
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 }
For i := 2 To MAX Div 2 Do
For j := 2 To MAX Div i Do
esPrimo[i*j] := False;
{Se cuenta el numero de primos encontrados }
j:= 0; For i := 1 To MAX Do If esPrimo[i] Then j := j + 1;
Writeln(Entre 1 y ,MAX:5, se han encontrado , j:3, primos);
For i := 1 To MAX Do If esPrimo[i] Then Write(i:4);
End. { primos }
Se define el Array esPrimo para almacenar datos Boolean que permiten
seguir la pista de los n
umeros que son m
ultiplos de otros. En este programa
se hace un uso apropiado de la ventaja ofrecida por la estructura de dato
Array. Se utiliza un tiempo constante para acceder a cualquier elemento de
la tabla, independientemente de que se trate del primero o el u
ltimo. Ademas
se puede incluir en el programa una relacion ventajosa entre la posicion de
un elemento en la tabla y su significado.
La estructura Array se usa muy a menudo en el calculo cientfico, pues
se trata de la realizacion de un vector, si cada elemento de la tabla se interpreta como un componente del vector. Igualmente, se pueden definir tablas
de tablas (Array bidimensional) para manipular matrices, y Array multidimensionales para los tensores.
La especificacion del rango, cuando se declaran, en los Array multidimensionales se puede realizar separando con comas los rangos de cada una
de las dimensiones. Igualmente, el acceso al contenido de una posicion de
9.4. ARRAYS
111
estas tablas m
ultiples se puede realizar separando con comas los ndices de
cada una de las dimensiones.
El siguiente procedimiento MultMatriz se puede utilizar para multiplicar 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
MultMatriz(n,A,B,C);
Writeln(La Matriz producto es:);
Escribematriz(C);
End.
Pero la definicion de los Array miltidimensionales tambien se puede hacer
como una tabla de tablas. Por ejemplo, el tipo de dato Matriz se podra
haber definido del siguiente modo:
Matriz = Array[1..MAXDIM] Of Array [1..MAXDIM] Of Numeros;
e igualmente los componentes de este tipo de datos se pueden referir como:
x := x + A1 [i][k] *
A2 [k][j];
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 }
Procedure EscribeCadena ( x : Cadena);
Var
i: Integer;
Begin { EscribeCadena }
For i := 1 to x[0] Do Write(Chr( x[i] ));
End; { EscribeCadena }
{ Procedimiento para unir a la cadena A1 la cadena A2 }
Procedure Concatena ( Var
A1 , A2 : Cadena );
Var
dim1 , i : Integer;
Begin
dim1 := A1[0];
For i := 1 To A2[0] Do
A1[ dim1 + i ]
A1[0] := dim1 + A2[0];
End;
Begin
Writeln();
:= A2[i];
114
LeeCadena(A);
LeeCadena(B);
Concatena(A,B);
Writeln();
EscribeCadena(A);
End.
9.5
Registros
9.5. REGISTROS
115
116
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 informacion de los alumnos
de una clase lo logico sera ordenar los alumnos en una lista. Para ello, se
puede crear una estructura Array cuyos elementos sean los registros definidos para almacenar la informacion de los alumnos. Se podra por ejemplo
a
nadir en la parte declarativa del programa Siete el siguiente tipo de dato:
{
Type }
Lista =
Array[1..100] of alumno;
118
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 }
Procedure EscribeCadena ( x : Cadena);
Var
i: Integer;
Begin { EscribeCadena }
For i := 1 to x.longitud Do Write(x.contenido[i] );
End; { EscribeCadena }
{ Procedimiento para unir a la cadena A1 la cadena A2 }
Procedure Concatena ( Var
A1 , A2 : Cadena );
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.
Despues de estudiar todos estos tipos de datos definidos por el usuario
120
debe estar mucho mas claro el sentido de los conceptos tipo de dato y variable. Una variable, es un identificador que utiliza el programador para
referirse a un dato y poder realizar operaciones con el. El tipo de dato ha de
especificarse para que el compilador pueda generar codigo 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 resolucion de un
problema puede pensar en variables para cualquier concepto abstracto que
piense que sea u
til para resolver el problema de un modo claro y comunicable, lo que muchas veces quiere decir de un modo lo mas proximo posible al
lenguaje natural. La restriccion obvia es poder explicitar sin ambig
uedades
la gestion 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 proximos a
los utilizados en el lenguaje natural y que son una organizacion precisa de
tipos de datos mas sencillos. En u
ltima instancia, los atomos que van a formar esas estructuras mas complejas son los tipos de datos fundamentales del
PASCAL : Byte , Integer , .... Al final, para una variable, el compilador
reservara lugar en memoria para almacenar un n
umero determinado de bits
de informacion (una sucesion 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 tambien el modo con en el que el programador se podra
referir a todos esos bits de golpe o a subconjuntos de ellos.
9.6
Uniones
9.6. UNIONES
121
donde nombre es el identificador elegido para la variable cuyo valor determina la composicion del registro, TipodeDato el tipo de dato de la variable
nombre, caso1,caso2, ... los valores o rango de valores que daran lugar a las
distintas especificaciones del contenido del registro Especificacion1, Especificacion2,... La enumeracion de las opciones no acaba con un End; por que
existe la restriccion de que las variantes se han de colocar en la u
ltima parte
de la definicion de un registro y por tanto acaban con el End; del fin de la
definicion del registro.
Como ejemplo de la utilizacion de los registros con variante vamos a considerar el caso visto anteriormente de la base de datos de alumnos. Supongamos que en el campo de la nota podemos querer guardar en alguna ocasion
en vez de un dato Real una calificacion global como Aprobado y elegimos
para ello un dato String. Una posibilidad es la siguiente modificacion del
caso anterior:
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
9.6. UNIONES
123
Las Uniones Libres han de usarse con precaucion para evitar confusiones en la lectura de los programas, pero a veces son las adecuadas para hacer
un programa legible. En el siguiente ejemplo la union entre el tipo de dato
Char y Byte se utiliza para escribir una funcion que convierte un caracter
en el correspondiente n
umero de orden ASCII.
Program Diez;
Var
dato : Char;
Function ElAscii ( x : Char ) : Byte;
Type
Atomo =
{ Union libre de un Char con un Byte }
Record
Case Integer Of
1 : ( car : Char);
2 : ( num : Byte );
End;
Var
y : Atomo;
Begin
y.car := x;
ElAscii := y.num
End;
Begin { Diez }
Readln (dato);
Writeln ( El caracter ,dato , corresponde al ASCII numero : ,
ElAscii(dato) );
End. { Diez }
En la funcion ElAscii el tipo de dato Atomo se define como la union libre
de un Char y un Byte. En este caso, ambos tipos de datos ocupan el
mismo espacio en memoria ( un byte ). La variable y ocupa pues un byte
124
Captulo 10
Ficheros
La entrada y salida de datos desde un programa no tiene porque realizarse
utilizando los dispositivos estandard de entrada y salida (teclado y terminal),
sino que puede realizarse a traves de cualquier periferico. Tambien es posible,
y de hecho es lo mas frecuente, utilizar los dispositivos de almacenamiento
intermedio de datos. Estos dispositivos de almacenamiento de datos reciben
el nombre de archivos o ficheros. Se trata generalmente de porciones de discos
magneticos donde se guarda informacion y se identifican con un nombre cuyo
formato depende del sistema operativo.
10.1
Para poder referir todas las entradas y salidas, el PASCAL utiliza un tipo de
dato que se denomina File. Con este tipo de dato se pueden direccionar las
entradas y salidas de los programas a impresoras, dispositivos auxiliares,...
y tambien a archivos. El valor de un dato del tipo File es esencialmente
una direccion a donde se debe dirigir la UCP para transferir datos. El valor concreto es irrelevante para el programador puesto que las instrucciones
que a el se refieren nunca requieren conocerlo. El PASCAL provee un procedimiento que permite asignar a una variable del tipo File la direccion del
dispositivo de entrada o salida que el programador pretende utilizar. Este es
el procedimiento Assign que tiene dos argumentos. El primero es el nombre
de la variable definida del tipo File y el segundo es un dato tipo String que
contiene el nombre con el que el sistema operativo identifica el fichero que se
quiere utilizar. En la instruccion {3} del programa Uno se especifica que
125
126
127
128
para verificar que no se procede a la lectura o escritura de datos de tipos distintos al anunciado en la declaracion. Por supuesto, es responsabilidad del
programador leer apropiadamente los bits almacenados en un archivo. Por
ejemplo, si la informacion escrita en una archivo declarado como File Of
Byte se lee en otro programa distinto declarando el archivo como File Of
Char se obtendra una traduccion de n
umeros enteros a los caracteres ASCII
correspondientes. Exactamente lo contrario se consigue si el programa dos
utiliza el mismo archivo uno.sal escrito con el programa Uno como entrada
de datos.
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.
La salida del programa dos es :
HOLA
Exactamente el mismo saludo es el que se puede leer en el fichero uno.sal
cuando se edita con un editor de ficheros ASCII como el del Entorno Integrado
de Desarrollo del TURBO PASCAL .
Un dispositivo de entrada-salida se puede definir como File Of cualquier
tipo de dato, incluyendo los definidos por el usuario. Son especialmente u
tiles
los archivos del tipo registro, pues en ellos se pueden almacenar facilmente
datos con la estructura interna requerida por el usuario. Por ejemplo, en el
problema esbozado en el tema anterior sobre una base de datos con informacion sobre alumnos, el mantenimiento de dicha base podra proceder del
siguiente modo:
Program Tres;
129
130
End; {endif}
End. { Tres }
En este programa se utiliza la funcion Eof que tiene como argumento la
variable del tipo File carpeta. Esta es una funcion del tipo Boolean que
devuelve el valor True si se alcanzado el fin del fichero al que apunta su
argumento. La funcion se utiliza en el programa Tres para recorrer todo el
archivo hasta el final y despues a
nadir el nuevo registro.
El listado de todos los alumnos incluidos en la base de datos se podra
realizar mediante el siguiente programa:
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);
131
10.2
Tanto en el programa Tres como en el Cuatro se esta realizando un procesamiento secuencial de los archivos. Se inicia la lectura por el primer registro
y se procede hasta llegar al deseado o al final. En el caso del programa
Tres este tipo de procesamiento ha obligado, para llegar hasta el u
ltimo de
los registros, a transferir a memoria el contenido de todos los registros. La
estructura interna de un archivo es lineal y muy parecida a la estructura
Array del PASCAL . Por tanto, debera ser posible acceder a los diferentes
registros sin necesidad de leerlos a la memoria RAM. Esta posibilidad es la
que permite el procedimiento del PASCAL Seek que tiene dos argumentos:
el primero un dato tipo File, y el segundo LongInt. El efecto de esta funcion es preparar el archivo identificado por el dato File para la lectura o
escritura a partir del n
umero de registro que contiene la variable LongInt.
De hecho, dado que los registros se empiezan a contar con el 0, se colocara
pasado el registro indicado por el n
umero LongInt. Por ejemplo, si fichero
se define como File Of Integer, la llamada Seek (fichero, 23) hara que
la siguiente lectura realizada sobre fichero transfiera a la memoria del ordenador el dato Integer con el n
umero de orden 24; se han saltado 46 bytes
del fichero.
Con la posibilidad brindada por el procedimiento Seek se puede realizar
lo que se llama procesamiento aleatorio de ficheros. A pesar del nombre,
esto no tiene nada que ver con el azar, sino que implica leer o escribir en
archivos en un orden distinto que el secuencial. Para explicar la utilidad y
servidumbres de este tipo de procesamiento, vamos a modificar el dise
no de
la base de datos de alumnos sugerida anteriormente. El objetivo es colocar
al principio del fichero un n
umero que nos indique la cantidad de alumnos
incluidos en la lista.
Program IniciaLista;
132
133
134
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. Despues, se vuelve al
principio para aumentar en 1 el contador de registros almacenados.
El listado de los alumnos en la base de datos sera :
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);
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 definicion de la base de datos de alumnos resulta muy sencillo 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
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);
Writeln(Desea incorporalo a la base de datos ? (s/n) :);
Read(respuesta);
If (respuesta = s) Or (respuesta = S) Then
Begin
Assign(carpeta,nomArchi);
Reset(carpeta);
Read(carpeta,otro);
Seek(carpeta,elemento);
Write(carpeta,uno);
Close(carpeta);
End; {EndIf}
End. {ModificaLista}
En este programa se accede directamente al registro que se quiere modificar
y el usuario lo identifica con el n
umero de orden que aparece en el listado.
Esta labor hubiera sido mucho mas difcil de realizar con un procesamiento
meramente secuencial del archivo.
10.3
Ficheros de Texto
Como se menciono anteriormente, el uso de ficheros de un tipo de dato definido, permite que la informacion se almacene en los archivos del mismo
modo que se escribe en la memoria del ordenador. Por tanto, no es necesario
ninguna traduccion para pasarlos a la memoria RAM. La ventaja de usar
este tipo de archivos es la rapidez en la transferencia de informacion entre
memoria RAM y dispositivos de almacenamiento. El inconveniente es la falta
137
138
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.
se puede comprobar la diferencia entre los dos tipos de transferencia de informacion. En el Seis se escriben los datos Real en un fichero File Of
Real y en el Siete en un fichero Text. El procedimiento GetTime, que se
encuentra en la unidad Dos, devuelve el tiempo en horas, minutos, segundos
y centesimas. Este procedimiento es el que se utiliza en ambos casos para
detectar el tiempo que se emplea en escribir 1000 datos Real. Con la salida
de estos dos programas se puede comprobar que el segundo programa emplea
casi el doble de tiempo que el primero en escribirlos. As mismo, el archivo
Siete.sal que se crea ocupa casi tres veces el espacio ocupado por el fichero
Seis.sal. Este u
ltimo, solo ocupa 60000 bytes puesto que cada Real esta
formado por 6 bytes, y Siete.sal ocupa 190000 bytes puesto que se necesitan
19 caracteres ASCII para describir con el formato estandard cada dato Real
(17 para el n
umero y 2 para el salto de lnea).
Otra desventaja adicional de los ficheros de texto es que solo aceptan
procesamiento secuencial y NO aleatorio.
140
Captulo 11
Punteros y asignaci
on din
amica
de memoria
11.1
{1}
{2}
{3}
Program Uno;
Var
a , b : Integer;
Begin { Uno }
Readln(a);
b := a;
Writeln(a:4, ,b:4);
End. { Uno }
en el que se definen las variables a y b para almacenar datos del tipo Integer. En la instruccion {3} se especifica que el dato almacenado en la
141
142
posicion de memoria a la que nos referimos con la variable a ha de almacenarse tambien en la posicion de memoria a la que nos referimos con la
variable b.
11.2
Punteros
En ning
un momento se ha hecho explicito en la sintaxis del lenguaje que un
dato esta identificado internamente por una posicion de memoria. Sin embargo, es muy u
til poder manipular los datos realizando algoritmos en los que
tambien interviene la direccion 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 esten 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;
.
.
.
se esta declarando que px es un puntero a un dato Real, pa un puntero
a un Integer, y pHoy y pAyer punteros a registros de Fecha. El mismo
calificador sirve para especificar que queremos utilizar el dato almacenado
en la direccion de memoria especificada por el puntero, pero esta vez se a
nade
al final del identificador. Por ejemplo, cuando aparece en una parte posterior
del programa citado anteriormente pHoy^
estamos indicando el contenido
del registro del tipo fecha apuntado por el puntero pHoy. La asignacion
11.2. PUNTEROS
143
.
.
pHoy^ := pAyer^;
.
.
.
.
{1}
{2}
{3}
{4}
Program Dos;
Var
a ,b : Integer;
pb : ^Integer;
Begin { Dos }
a := 10 ;
pb := @a ;
b := pb^ ;
Writeln(a:4, ,b:4);
End. { Dos }
144
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 }
en el que se modifica el valor del String a indirectamente a traves del contenido del puntero pb. Las direcciones de memoria que se almacenan en
los datos del tipo puntero, dependeran de cada tipo de ordenador, y en general, el programador puede olvidarse de esos detalles, pues solo utilizara
los punteros para manipular los datos a los que apuntan y evitara asignar
directamente valores numericos a los punteros. Generalmente se asigna a un
puntero el contenido de otro. Hay una excepcion: se trata del valor Nil, ya
que no corresponde a un lugar de memoria y se utiliza para identificar que un
puntero no apunta a ning
un lugar de la memoria. A un puntero, apuntando
a cualquier tipo de dato, siempre se le puede asignar el valor Nil.
Las operaciones que se pueden realizar con los punteros, son asignar y
comparar por igualdad o desigualdad. Con estas comparaciones se puede
discernir la equivalencia de direcciones. Sin embargo, no se pueden comparar
los punteros con los operadores > y <.
Vamos a verificar el motivo de llamar argumentos por referencia o direccion a los argumentos antecedidos por Var en las funciones y procedimientos.
La salida del programa Cuatro,
Program Cuatro;
Type pinte = ^Integer;
Var
a ,b ,c: Integer;
DINAMICA
11.3. ASIGNACION
DE MEMORIA.
145
Procedure Cuacua (
x : pinte;
y : Integer;
Var z : Integer
);
Begin
x^ := x^ * x^;
y := y * y ;
z := z * z ;
End;
Begin { Cuatro }
a := 2 ;
b := 3 ;
c := 4 ;
Cuacua(@a,b,c);
Writeln(a:6, ,b:6,
End. { Cuatro }
,c:6);
es,
4
16
11.3
Asignaci
on din
amica de memoria.
Una utilidad de los punteros es poder crear programas que ocupen la cantidad de memoria del ordenador adecuada a cada caso seg
un se determina
durante la ejecucion del programa. Cuando un programa se va a ejecutar, se
carga en la memoria del ordenador y la memoria ocupada por el programa
esta estructurada en varias partes o segmentos. El codigo para la UCP se
carga en memoria en el llamado segmento de codigo. Los datos definidos
en el programa se cargan en el llamado segmento de datos, y hay un tercer
segmento llamado pila (stack) que se reserva para los datos que se han de
146
147
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 dara un error en la ejecucion. La u
ltima instruccion
intenta liberar un lugar de memoria que ya ha sido liberado en la llamada anterior a Dispose. Por otra parte, es un ejemplo claro de mal uso de la gestion
dinamica de memoria. La memoria reservada para el programa mediante la
tercera instruccion (256 bytes) no se puede liberar puesto que hemos perdido
la pista de cual era. Es una practica poco recomendable escribir programas
que cuando acaban dejan sin liberar memoria que reservaron del monton.
11.4
148
Enlace = ^Nodo;
Nodo =
Record
clave : Integer;
siguiente : Enlace
End;
-Nodo
-Nodo
HH
HH
j
Nil
149
Begin
{ Se inicializa la lista }
New(z);
z^.siguiente := Nil;
{El ultimo
150
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.
Para detectar el final de la lista, recurrimos a la direccion Nil. Cuando recorremos la lista para escribir el contenido, nos detenemos cuando un nodo (el
u
ltimo) apunta a esa constante. No hay que olvidar nunca reservar memoria
del Heap para cada elemento nuevo de la lista. De lo contrario, se pueden
obtener resultados impredecibles. Cuando se escribe informacion en la direccion de memoria dictada por un puntero que no ha sido convenientemente
inicializado estaremos escribiendo en un lugar descontrolado y los resultados
son imprevisibles. Dado que los n
umeros tecleados por el usuario se van incorporando a la lista seg
un se teclean, y no guardamos la pista sobre donde esta
el primer elemento almacenado en memoria, solo podemos listar los n
umeros
en el orden inverso al que fueron tecleados. Para listar los n
umeros en el
mismo orden en el que fueron tecleados existen varias posibilidades pero su
analisis queda fuera de los objetivos de este curso. Sin ahondar mucho mas
en las estructuras de datos que se pueden generar con los punteros merece la
pena resaltar la simplicidad y eficiencia de cierta operaciones que se realizan
com
unmente sobre listas unidas. El insertar un nuevo elemento en el lugar
elegido de la lista puede ser algo tan sencillo como :
{un nuevo nodo se crea a continuacion del apuntado por y}
New(z);
z^.clave := i;
z^.siguiente := y^.siguiente;
y^.siguiente := z;
151
y la eliminacion de un nodo :
{Se elimina el nodo a continuacion del apuntado por y}
z:= y^siguiente;
y^.siguiente := y^.siguiente^.siguiente ;
Dispose(z);
Estructuras de datos como listas doblemente unidas, circulares y arboles, son
muy comunes en la realizacion de algoritmos eficientes.
A estas alturas del curso podemos entender perfectamente el programa
llamado Josefo que se estudio en el Tema 3. No obstante, el alumno no
debe esperar que con los conocimientos sobre programacion adquiridos hasta
ahora debera haber dise
nado un programa similar a Josefo para resolver
el problema. Tales dise
nos no aparecen generalmente por intuicion sino como resultado del estudio de las estructuras de datos y algoritmos que se
han desarrollado para diferentes problemas tipo planteados a la ciencia de
la computacion. El objetivo de esta parte del curso era que el alumno comprendiera un programa como el citado y sobre todo que en los programas que
escriba, sean los problemas que resuelvan mas o menos sencillos, utilice la
herramientas aprendidas siguiendo las normas de claridad y estilo referidas
continuamente.