Introducción al Lenguaje Pascal
Introducción al Lenguaje Pascal
Con poco más que lo visto hasta ahora ya se podría escribir un pequeño programa que hiciera
aparecer el mensaje "Hola" en la pantalla:
program Saludo;
begin
write('Hola');
end.
(para indicar que el programa iba a manejar los dispositivos de entrada y salida). Por ejemplo,
como este programa escribe en la pantalla, si se usa el Pascal de GNU, deberá poner:
program Saludo(output);
Aunque para nosotros no sea necesaria la línea de "program", su empleo puede resultar cómodo
si se quiere poder recordar el objetivo del programa con sólo un vistazo rápido a su cabecera.
Saludo es un identificador que nos va a servir para indicar el nombre del programa. Los
"identificadores" son palabras que usaremos para referirnos a una variable, una constante, el
nombre de una función o de un procedimiento, etc.
Una variable equivale a la clásica incógnita "x" que todos hemos usado en matemáticas, que
puede ser cualquier número. Ahora nuestras "incógnitas" podrán tener cualquier valor (no sólo
un número: también podremos guardar textos, fichas sobre personas o libros, etc.) y nombres
más largos (y que expliquen mejor su contenido).
Estos nombres de "identificadores" serán combinaciones de letras y números, junto con algunos
(pocos) símbolos especiales, como el de subrayado (_). No podrán empezar con un número, sino
por un carácter alfabético (A a Z, sin Ñ ni acentos) o un subrayado, y no podrán contener
espacios.
Así, serían identificadores correctos: Nombre_De_Programa, programa2, _SegundoPrograma
pero no serían admisibles 2programa, 2ºprog, tal&tal, Prueba de programa, ProgramaParaMí
(unos por empezar por números, otros por tener caracteres no aceptados, y otros por las dos
cosas).
Las palabras "begin" y "end" marcan el principio y el final del programa, que esta vez sólo se
compone de una línea. Nótese que, como se dijo, el último "end" debe terminar con un punto.
"Write " es la orden que permite escribir un texto en pantalla. El conjunto de todo lo que se
desee escribir se indica entre paréntesis.
Cuando se trata de un texto que queremos que aparezca "tal cual", éste se encierra entre comillas
(una comilla simple para el principio y otra para el final, como aparece en el ejemplo).
El punto y coma que sigue a la orden "write" no es necesario (va justo antes de un "end"), pero
tampoco es un error; así que podemos dejarlo, por si después añadimos otra orden entre "write"
y "end".
La orden "write" aparece algo más a la derecha que el resto. Esto se llama escritura indentada,
y consiste en escribir a la misma altura todos los comandos que se encuentran a un mismo nivel,
algo más a la derecha los que están en un nivel inferior, y así sucesivamente. Se irá viendo con
más detalle a medida que se avanza.
En un programa en Pascal no hay necesidad de conservar una estructura tal que aparezca cada
orden en una línea distinta. Se suele hacer así por claridad, pero realmente son los puntos y
coma (cuando son necesarios) lo que indica el final de una orden, por lo que el programa
anterior se podría haber escrito:
program Saludo; begin write('Hola') end.
Una última observación: si se compila este programa desde Turbo Pascal 5.0 o una versión
superior, aparentemente "no pasa nada". No es así, sino que se ejecuta y se vuelve al editor tan
rápido que no nos da tiempo a verlo. La solución es pulsar Alt+F5 para que nos muestre la
pantalla del DOS.
En el primer ejemplo que vimos, puede que no nos interese escribir siempre el mensaje "Hola",
sino uno más personalizado según quien ejecute el programa. Podríamos preguntar su nombre
al usuario, guardarlo en una variable y después escribirlo a continuación de la palabra "Hola",
con lo que el programa quedaría
program Saludo2;
var
nombre: string;
begin
writeln('Introduce tu nombre, por favor');
readln(nombre);
write('Hola ',nombre);
end.
Aquí ya aparecen más conceptos nuevos. En primer lugar, hemos definido una variable, para lo
que empleamos la palabra var, seguida del nombre que vamos a dar a la variable, y del tipo de
datos que va a almacenar esa variable.
Los nombres de las variables siguen las reglas que ya habíamos mencionado para los
identificadores en general.
Con la palabra string decimos que la variable nombre va a contener una cadena de caracteres
(letras o números). Un poco más adelante, comentamos los principales tipos de datos que vamos
a manejar.
Pasemos al cuerpo del programa. En él comenzamos escribiendo un mensaje de aviso. Esta vez
se ha empleado "writeln", que es exactamente igual que "write", con la única diferencia de que
después de visualizar el mensaje, el cursor (la posición en la que se seguiría escribiendo,
marcada normalmente por una rayita o un cuadrado que parpadea) pasa a la línea siguiente, en
vez de quedarse justo después del mensaje escrito.
Después se espera a que el usuario introduzca su nombre, que le asignamos a la variable
"nombre", es decir, lo guardamos en una posición de memoria cualquiera, que el compilador ha
reservado para nosotros, y que nosotros no necesitamos conocer (no nos hace falta saber que
está en la posición 7245 de la memoria, por ejemplo) porque siempre nos referiremos a ella
llamándola "nombre". De todo esto se encarga la orden "readln".
Finalmente, aparece en pantalla la palabra "Hola" seguida por el nombre que se ha introducido.
Como se ve en el ejemplo, "writeln" puede escribir más de un dato, pero eso se mostrará en
detalle más adelante.
• Record. La principal limitación de un array es que todos los datos que contiene
deben ser del mismo tipo. Pero a veces nos interesa agrupar datos de distinta naturaleza,
como pueden ser el nombre y la edad de una persona, que serían del tipo string y byte,
respectivamente. Entonces empleamos los records o registros, que se definen indicando
el nombre y el tipo de cada campo (cada dato que guardamos en el registro), y se accede
a estos campos indicando el nombre de la variable y el del campo separados por un
punto:
program Ejemplo_de_registro;
var
dato: record
nombre: string[20];
edad: byte;
end;
begin
dato.nombre:='José Ignacio';
dato.edad:=23;
write('El nombre es ', dato.nombre );
write(' y la edad ', dato.edad, ' años.');
end.
var
dato: record
nombre: string[20];
edad: byte;
end;
begin
with dato do
begin
nombre:='José Ignacio';
edad:=23;
write('El nombre es ',nombre);
write(' y la edad ',edad,' años.');
end;
end.
En este caso tenemos un nuevo bloque en el cuerpo del programa, delimitado por
el "begin" y el "end" situados más a la derecha, y equivale a decir "en toda esta
parte del programa me estoy refiriendo a la variable dato". Así, podemos nombrar
los campos que queremos modificar o escribir, sin necesidad de repetir a qué
variable pertenecen.
Ejemplos.
Ejemplo 1: Cambiar el valor de una variable.
program NuevoValor;
var
numero: integer;
begin
numero := 25;
writeln('La variable vale ', numero);
numero := 50;
writeln('Ahora vale ', numero);
numero := numero + 10;
writeln('Y ahora ', numero);
writeln('Introduce ahora tú el valor');
readln( numero );
writeln('Finalmente, ahora vale ', numero);
end.
var
numero1, numero2, suma: integer;
begin
writeln('Introduce el primer número');
readln( numero1 );
writeln('Introduce el segundo número');
readln( numero2 );
suma := numero1 + numero2;
writeln('La suma de los dos números es: ', suma);
end.
var
vector: array [1..5] of real;
suma, media: real;
begin
writeln('Media de un vector con 5 elementos.');
writeln;
writeln('Introduce el primer elemento');
readln(vector[1]);
writeln('Introduce el segundo elemento');
readln(vector[2]);
writeln('Introduce el tercer elemento');
readln(vector[3]);
writeln('Introduce el cuarto elemento');
readln(vector[4]);
Página 8 Lenguaje Pascal, Parte I - Jorge Dimarco (2004)
Facultad de Ciencias Exactas, Ingeniería y Agrimensura
Informática I
Como todavía llevamos pocos conocimientos acumulados, la cosa se queda aquí, pero con la
siguiente lección ya podremos realizar operaciones matemáticas algo más serias, y
comparaciones lógicas.
Cuando se desee escribir varias cosas en la misma línea, todas ellas se indican entre un mismo
paréntesis, y separadas por comas.
Se puede especificar la anchura de lo escrito, mediante el símbolo de dos puntos (:) y la cifra
que indique la anchura. Si se trata de un número real y queremos indicar también el número de
decimales, esto se hace también después de los dos puntos, con el formato
":anchura_total:decimales".
Como ejemplos:
write ('Hola, ',nombre,' ¿qué tal estás?');
writeln (resultado:5:2);
writeln('Hola,',nombre:10,'. Tu edad es:',edad:2);
En el caso de una cadena de texto, la anchura que se indica es la que se tomará como mínima: si
el texto es mayor no se "parte", pero si es menor, se rellena con espacios por la izquierda hasta
completar la anchura deseada.
Igual ocurre con los números: si es más grande que la anchura indicada, no se "parte", sino que
se escribe completo. Si es menor, se rellena con espacios por la izquierda. Los decimales sí que
se redondean al número de posiciones indicado:
var num: real;
begin
num := 1234567.89;
writeln(num);
(* La línea anterior lo escribe con el formato por defecto:
exponencial *)
writeln(num:20:3); (* Con tres decimales *)
writeln(num:7:2); (* Con dos decimales *)
writeln(num:4:1); (* Con un decimal *)
writeln(num:3:0); (* Sin decimales *)
writeln(num:5); (* ¿Qué hará ahora? *)
end.
En este programa ha aparecido también otra cosa nueva: los comentarios. Un comentario es
algo que no se va a ejecutar, y que nosotros incluimos dentro del programa para que nos resulte
más legible o para aclarar lo que hace una línea o un conjunto de líneas.
En Pascal, los comentarios se encierran entre (* y *). También está permitido usar { y }, tanto en
Turbo Pascal como en SURPAS. Como se ve en el ejemplo, pueden ocupar más de una línea.
En la práctica, es muy importante que un programa esté bien documentado.
Cuando se trabaja en grupo, la razón es evidente: a veces es la única forma de que los demás
entiendan nuestro trabajo. En estos casos, el tener que dar explicaciones "de palabra" es
contraproducente: Se pierde tiempo, las cosas se olvidan... Tampoco es cómodo distribuir las
indicaciones en ficheros aparte, que se suelen extraviar en el momento más inoportuno. Lo ideal
es que los comentarios aclaratorios estén siempre en el texto de nuestro programa.
Pero es que cuando trabajamos solos también es importante, porque si releemos un programa un
mes después de haberlo escrito, lo habitual es que ya no nos acordemos de lo que hacía la
variable X, de por qué la habíamos definido como "Record" y no como "Array", por qué
dejábamos en blanco la primera ficha o por qué empezábamos a ordenar desde atrás.
Para tomar datos del usuario, la forma más directa es empleando readln, que toma un texto o
un número y asigna este valor a una variable. No avisa de lo que está haciendo, así que
normalmente convendrá escribir antes en pantalla un mensaje que indique al usuario qué
esperamos que teclee:
writeln('Por favor, introduzca su nombre');
readln(nombre);
Más adelante, veremos que existen formas mucho más versátiles y cómodas de leer datos a
través del teclado, en el mismo tema en el que veamos cómo se maneja la pantalla en modo
texto desde Pascal.
En operaciones como +, - y * no debería haber ninguna duda. Los problemas pueden venir con
casos como el de 10/3. Si 10 y 3 son números enteros, ¿qué ocurre con su división? En otros
lenguajes como C, el resultado sería 3, la parte entera de la división. En Pascal no es así: el
resultado sería 3.333333, un número real. Si queremos la parte entera de la división, deberemos
utilizar div. Finalmente, mod nos indica cual es el resto de la división. El signo - se puede usar
también para indicar negación. Veamos unos ejemplos:
program operaciones;
var
e1, e2: integer; (* Números enteros *)
r1, r2, r3: real; (* Números reales *)
begin
e1:=17;
e2:=5;
r1:=1;
r2:=3.2;
writeln('Empezamos...');
r3:=r1+r2;
writeln('La suma de r1 y r2 es :', r3);
writeln(' o también ', r1+r2 :5:2); (* Indicando el formato *)
writeln('El producto de r1 y r2 es :', r1 * r2);
writeln('El valor de r1 dividido entre r2 es :', r1 / r2);
writeln('La diferencia de e2 y e1 es : ', e2 - e1);
writeln('La división de e1 entre e2 : ', e1 / e2);
writeln(' Su división entera : ', e1 div e2);
writeln(' Y el resto de la división : ', e1 mod e2);
writeln('El opuesto de e2 es :', -e2);
end.
El operador + (suma) se puede utilizar también para concatenar cadenas de texto, así:
var
texto1, texto2, texto3: string;
begin
texto1 := 'Hola ';
texto2 := '¿Cómo estás?';
texto3 := texto1 + texto2;
writeln(texto3); (* Escribirá "Hola ¿Cómo estás?" *)
end.
Cuando tratemos tipos de datos más avanzados, veremos que +, - y * también se pueden utilizar
para conjuntos, e indicarán la unión, diferencia e intersección.
Operadores lógicos
Vimos de pasada que en el tema que había unos tipos de datos llamados "boolean", y que podían
valer TRUE (verdadero) o FALSE (falso). En la próxima lección veremos cómo hacer
comparaciones del estilo de "si A es mayor que B y B es mayor que C", y empezaremos a
utilizar variables de este tipo, pero vamos a mencionar ya eso del "y".
Podremos encadenar proposiciones de ese tipo (si A y B entonces C) con: and (y), or (ó), not
(no) y los operadores relacionales, que se usan para comparar y son los siguientes:
Operador ¦ Operación
----------+----------------------------
= ¦ Igual a
<> ¦ No igual a (distinto de)
< ¦ Menor que
> ¦ Mayor que
<= ¦ Menor o igual que
>= ¦ Mayor o igual que
Igual que antes, algunos de ellos (>=, <=, in) se utilizarán también en los conjuntos, más
adelante.
Los operadores "and", "or" y "not", junto con otros, se pueden utilizar también para
operaciones entre bits de números enteros.
Operador ¦ Operación
---------+----------------------------
not ¦ Negación
and ¦ Producto lógico
or ¦ Suma lógica
xor ¦ Suma exclusiva
shl ¦ Desplazamiento hacia la izquierda
shr ¦ Desplazamiento a la derecha
Tema 5: Condiciones.
Vamos a ver cómo podemos evaluar condiciones desde Pascal. La primera construcción que
trataremos es if ... then. En español sería "si ... entonces", que expresa bastante bien lo que
podemos hacer con ella. El formato es "if condición then sentencia". Veamos un ejemplo breve
antes de seguir:
program if1;
begin
writeln('Escriba un número');
readln(numero);
if numero>0 then writeln('El número es positivo');
end.
La "condición" debe ser una expresión que devuelva un valor del tipo "boolean"
(verdadero/falso). La sentencia se ejecutará si ese valor es "cierto" (TRUE). Este valor puede ser
tanto el resultado de una comparación como la anterior, como una propia variable booleana.
Así, una forma más "rebuscada" (pero que a veces resultará más cómoda y más legible) de hacer
lo anterior sería:
program if2;
var
numero: integer;
esPositivo: boolean;
begin
writeln('Escriba un número');
readln(numero);
esPositivo := (numero>0);
if esPositivo then writeln('El número es positivo');
end.
Cuando veamos en el próximo tema las órdenes para controlar el flujo del programa,
seguiremos descubriendo aplicaciones de las variables booleanas, que muchas veces uno
considera "poco útiles" cuando está aprendiendo.
La "sentencia" puede ser una sentencia simple o una compuesta. Las sentencias compuestas
se forman agrupando varias simples entre un "begin" y un "end":
program if3;
var
numero: integer;
begin
writeln('Escriba un número');
readln(numero);
if numero<0 then
begin
writeln('El número es negativo. Pulse INTRO para seguir.');
readln
end;
end.
var
numero: integer;
begin
writeln('Escriba un número');
readln(numero);
if numero<0 then
writeln('El número es negativo.')
else
writeln('El número es positivo o cero.')
end.
Un detalle importante que conviene tener en cuenta es que antes del "else" no debe haber un
punto y coma, porque eso indicaría el final de la sentencia "if...", y el compilador nos avisaría
con un error.
var
numero: integer;
begin
writeln('Escriba un número');
readln(numero);
if numero<0 then
writeln('El número es negativo.')
Si se deben cumplir varias condiciones a la vez, podemos enlazarlas con "and" (y). Si se
pueden cumplir varias, usaremos "or" (o). Para negar, "not" (no):
if ( opcion = 1 ) and ( terminado = true ) then [...]
if ( opcion = 3 ) or ( teclaPulsada = true ) then [...]
if not ( preparado ) then [...]
if ( opcion = 2 ) and not ( nivelDeAcceso < 40 ) then [...]
Pero cuando queremos comprobar entre varios posibles valores, sería muy pesado tener que
hacerlo con muchos "if" seguidos o encadenar muchos con "and" u "or". Hay una alternativa
que resulta mucho más cómoda: la orden case. Su sintaxis es
case expresión of
caso1: sentencia1;
caso2: sentencia2;
...
casoN: sentenciaN;
end;
o bien, si queremos indicar lo que se debe hacer si no coincide con ninguno de los valores que
hemos enumerado, usamos else:
case expresión of
caso1: sentencia1;
caso2: sentencia2;
...
casoN: sentenciaN;
else
otraSentencia;
end;
En Pascal estándar, esta construcción se empleaba con otherwise en lugar de "else" para
significar "en caso contrario", así que si alguien no usa TP/BP, sino un compilador que protesta
con el "else", sólo tiene que probar con "otherwise".
Con un ejemplo se verá más claro cómo usar "case":
program case1;
var
letra: char;
begin
WriteLn('Escriba un letra');
ReadLn(letra);
case letra of
' ': WriteLn('Un espacio');
'A'..'Z', 'a'..'z': WriteLn('Una letra');
'0'..'9': WriteLn('Un dígito');
'+', '-', '*', '/': WriteLn('Un operador');
else
Página 15 Lenguaje Pascal, Parte I - Jorge Dimarco (2004)
Facultad de Ciencias Exactas, Ingeniería y Agrimensura
Informática I
Como último comentario: la "expresión" debe pertenecer a un tipo de datos con un número
finito de elementos, como "integer" o "char", pero no "real".
Y como se ve en el ejemplo, los "casos" posibles pueden ser valores únicos, varios valores
separados por comas, o un rango de valores separados por .. (como los puntos suspensivos, pero
sólo dos).
Tema 6: Bucles.
Vamos a ver cómo podemos crear bucles, es decir, partes del programa que se repitan un cierto
número de veces.
Según cómo queramos que se controle ese bucle, tenemos tres posibilidades, que vamos a
empezar a ver ya por encima:
• for..to: La orden se repite desde que una variable tiene un valor inicial hasta que
alcanza otro valor final (un cierto NUMERO de veces).
• while..do : Repite una sentencia MIENTRAS que sea cierta la condición que
indicamos.
• repeat..until: Repite un grupo de sentencias HASTA que se dé una condición.
La diferencia entre estos dos últimos es que "while" comprueba la condición antes de ejecutar
las otras sentencias, por lo que puede que estas sentencias ni siquiera se lleguen a ejecutar, si la
condición de entrada es falsa. En "repeat", la condición se comprueba al final, de modo que las
sentencias intermedias se ejecutarán al menos una vez.
Vamos a verlos con más detalle...
For.
El formato de "for" es
for variable := ValorInicial to ValorFinal do
Sentencia;
begin
for contador := 1 to 10 do
writeln( contador );
end.
Los bucles "for" se pueden enlazar uno dentro de otro, de modo que un segundo ejemplo que
escribiera las tablas de multiplicar del 1 al 5 podría ser
var
tabla, numero: integer;
begin
for tabla := 1 to 5 do
for numero := 1 to 10 do
writeln( tabla, 'por ', numero ,'es', tabla * numero );
end.
Hasta ahora hemos visto sólo casos en los que después de "for" había un única sentencia. ¿Qué
ocurre si queremos repetir más de una orden? Basta encerrarlas entre "begin" y "end" para
convertirlas en una sentencia compuesta.
Así, vamos a mejorar el ejemplo anterior haciendo que deje una línea en blanco entre tabla y
tabla:
var
tabla, numero: integer;
begin
for tabla := 1 to 5 do
begin
for numero := 1 to 10 do
writeln( tabla, 'por ', numero ,'es', tabla * numero );
writeln; (* Línea en blanco *)
end;
end.
Conviene recordar que es muy conveniente usar la escritura indentada, que en este caso ayuda
a ver dónde empieza y termina lo que hace cada "for".
begin
for letra := 'a' to 'z' do
write( letra );
end.
Como último comentario: con el bucle "for", tal y como lo hemos visto, sólo se puede contar en
forma creciente y de uno en uno. Para contar de forma decreciente, se usa "downto" en vez de
"to".
Para contar de dos en dos (por ejemplo), hay usar "trucos": multiplicar por dos o sumar uno
dentro del cuerpo del bucle, etc... Eso sí, sin modificar la variable que controla el bucle (usar
cosas como "write(x*2)" en vez de "x := x*2", que pueden dar problemas en algunos
compiladores).
Como ejercicios propuestos:
1. Un programa que escriba los números 2, 4, 6, 8 ... 16.
2. Otro que escriba 6, 5, 4,..., 1.
3. Otro que escriba 3, 5, 7,..., 21.
4. Otro que escriba 12, 10, 8,..., 0.
5. Otro que multiplique dos matrices.
6. Para los que conozcan el problema, uno de resolución de sistemas de ecuaciones por
Gauss.
While.
Vimos como podíamos crear estructuras repetitivas con la orden "for", y comentamos que se
podía hacer también con "while..do", comprobando una condición al principio, o con
"repeat..until", comprobando la condición al final de cada repetición. Vamos a verlas con más
detalle:
La sintaxis de "while"
while condición do
sentencia;
Se podría traducir como "MIENTRAS condición HAZ sentencia", o sea, que la sentencia se va
a repetir mientras la condición sea cierta.
Un ejemplo que nos diga la longitud de todas las frases que queramos es:
var
frase: string;
begin
writeln('Escribe frases, y deja una línea en blanco para salir');
write( '¿Primera frase?' );
readln( frase );
while frase <> '' do
begin
writeln( 'Su longitud es ', length(frase) );
write( '¿Siguiente frase?' );
readln( frase )
end
end.
Repeat .. Until.
Para "repeat..until", la sintaxis es
repeat
sentencia;
...
sentencia;
sentencia
until condición;
Es decir, REPITE un grupo de sentencias HASTA que la condición sea cierta. Cuidado con eso:
es un grupo de sentencias, no sólo una, como ocurría en "while", de modo que ahora no
necesitaremos "begin" y "end" para crear sentencias compuestas.
El conjunto de sentencias se ejecutará al menos una vez, porque la comprobación se realiza al
final.
Como último detalle, de menor importancia, no hace falta terminar con punto y coma la
sentencia que va justo antes de "until", al igual que ocurre con "end".
var
ClaveCorrecta, Intento: String;
begin
ClaveCorrecta := 'PascalForever';
repeat
WriteLn( 'Introduce la clave de acceso...' );
ReadLn( Intento )
until Intento = ClaveCorrecta
(* Aquí iría el resto del programa *)
end.
Por cierto, si alguien ha programado en Basic puede que se pregunte por la orden goto. Existe
en Pascal, pero su uso va a en contra de todos los principios de la Programación Estructurada,
solo está "medio-permitido" en casos muy concretos, así que lo veremos más adelante.
var i: integer;
begin
for i := 1 to 8 do
writeln( i*2 );
end.
var i: integer;
begin
for i := 6 downto 1 do
writeln( i );
end.
var i: integer;
begin
for i := 1 to 10 do
writeln( i*2 +1 );
end.
var i: integer;
begin
for i := 6 downto 0 do
writeln( i*2 );
end.
for i :=1 to 10 do
for j := 1 to 10 do
for k := 1 to 10 do
c[i,j] := c[i,j] + a[k,j] * b[i,k];
7.- Mejorar el programa de la clave de acceso para que avise de que la clave no es
correcta.
program ClaveDeAcceso2;
var
ClaveCorrecta, Intento: String;
begin
ClaveCorrecta := 'PascalForever';
repeat
WriteLn( 'Introduce la clave de acceso...' );
ReadLn( Intento )
if Intento <> ClaveCorrecta then
writeln( ' Esa no es la clave correcta! ');
until Intento = ClaveCorrecta
(* Aquí iría el resto del programa *)
end.
2.- Mejorar más todavía para que sólo haya tres intentos.
program ClaveDeAcceso3;
var
ClaveCorrecta, Intento: String;
NumIntento: integer; (* número de intento *)
begin
ClaveCorrecta := 'PascalForever';
NumIntento := 0; (* aún no hemos probado *)
repeat
NumIntento := NumIntento + 1; (* siguiente intento *)
WriteLn( 'Introduce la clave de acceso...' );
ReadLn( Intento )
if Intento <> ClaveCorrecta then
begin
writeln( ' Esa no es la clave correcta! ');
if NumIntentos = 3 then exit (* sale si es el 3º *)
end
until Intento = ClaveCorrecta
(* Aquí iría el resto del programa *)
end.
3.- Adaptar la primera versión (el ejemplo), la segunda (la mejorada) y la tercera (re -
mejorada) para que empleen "while" y no "repeat-until"
Sólo ponemos una de ellas, porque las demás son muy similares.
program ClaveDeAcceso4; (* equivale a ClaveDeAcceso2*)
var
ClaveCorrecta, Intento: String;
begin
ClaveCorrecta := 'PascalForever';
Intento := ''; (* cadena vacía *)
while Intento <> ClaveCorrecta do (* mientras no acertemos *)
begin
WriteLn( 'Introduce la clave de acceso...' );
ReadLn( Intento )
if Intento <> ClaveCorrecta then
writeln( ' Esa no es la clave correcta! ');
end; (* fin del "while" *)
(* Aquí iría el resto del programa *)
end.
Estas constantes se manejan igual que variables como las que habíamos visto hasta hora, sólo
que no se puede cambiar su valor. Así, es valido hacer
Writeln(MiNombre);
if Longitud > LongitudMaxima then ...
OtraVariable := MiNombre;
LongCircunf := 2 * PI * r;
Las constantes son mucho más prácticas de lo que puede parecer a primera vista (especialmente
para quien venga de lenguajes como Basic, en el que no existen -en el Basic "de siempre",
puede que sí exista en los últimas versiones del lenguaje).
La solución será definir todo ese tipo de datos como constantes al principio del programa, de
modo que con un vistazo a esta zona podemos hacer cambios globales:
const
Nombre = 'Nacho';
Prog = 'SuperAgenda en Pascal';
Versión = 1.95;
LongNombre = 40;
LongTelef = 9;
LongDirec = 60;
...
Las declaraciones de las constantes se hacen antes del cuerpo del programa principal, y
generalmente antes de las declaraciones de variables:
program MiniAgenda;
const
NumFichas = 50;
var
Datos: array[ 1..NumFichas ] of string;
begin
...
El identificador "const" tiene también en Turbo Pascal otro uso menos habitual: definir lo que se
llaman constantes con tipo, que son variables norma les y corrientes, pero a las que damos un
valor inicial antes de que comience a ejecutarse el programa. Se usa
const variable: tipo = valor;
Así, volviendo al ejemplo de la clave de acceso, podíamos tener una variables "intentos" que
dijese el número de intentos. Hasta ahora habríamos hecho
var
intentos: integer;
begin
intentos := 3;
...
Ahora ya sabemos que sería mejor hacer, si sabemos que el valor no va a cambiar:
const
intentos = 3;
begin
...
Pero si se nos da el caso de que vemos por el nombre que es alguien de confianza, que puede
haber olvidado su clave de acceso, quizá nos interese permitirle 5 o más intentos. Ya no
podemos usar "const" porque el valor puede variar, pero por otra parte, siempre comenzamos
concediendo 3 intentos, hasta comprobar si es alguien de fiar.
Podemos hacer
const intentos: integer = 3;
begin
...
Recordemos que una "constante con tipo" se manejará exactamente igual que una variable,
con las ventajas de que está más fácil de localizar si queremos cambiar su valor inicial y de que
el compilador optimiza un poco el código, haciendo el programa unos bytes más pequeño.
Definición de tipos.
El tipo de una variable es lo que indicamos cuando la declaramos:
var PrimerNumero: integer;
indica que vamos a usar una variable que se va a llamar PrimerNumero y que almacenará
valores de tipo entero. Si queremos definir una de las fichas de lo que será nuestra agenda,
también haríamos:
var ficha: record
nombre: string;
direccion: string;
edad: integer;
observaciones: string
end;
Tampoco hay ningún problema con esto, ¿verdad? Y si podemos utilizar variables creando los
tipos "en el momento", como en el caso anterior, ¿para qué necesitamos definir tipos? Vamos a
verlo con un ejemplo. Supongamos que vamos a tener ahora dos variables: una "ficha1" que
contendrá el dato de la ficha actual y otra "ficha2" en la que almacenaremos datos temporales.
var
ficha1: record
nombre: string;
direccion: string;
edad: integer;
observaciones: string
end;
ficha2: record
nombre: string;
direccion: string;
edad: integer;
observaciones: string
end;
begin
ficha1.nombre := 'Pepe';
ficha1.direccion := 'Su casa';
ficha1.edad := 65;
ficha1.observaciones := 'El mayor de mis amigos...';
ficha2 := ficha1;
writeln( ficha2.nombre);
end.
Veamos qué haría este programa: define dos variables que van a guardar la misma clase de
datos. Da valores a cada uno de los datos que almacenará una de ellas. Después hacemos que la
segunda valga lo mismo que la primera, e imprimimos el nombre de la segunda. Aparecerá
escrito "Pepe" en la pantalla...
No. Aunque a nuestros ojos "ficha1" y "ficha2" sean iguales, para el compilador no es así, por lo
que protesta y el programa ni siquiera llega a ejecutarse. Es decir: las hemos definido para que
almacene la misma clase de valores, pero no son del mismo tipo.
Esto es fácil de solucionar:
var ficha1, ficha2: record
nombre: string;
direccion: string;
edad: integer;
observaciones: string
end;
begin
...
Si las definimos a la vez, SI QUE SON DEL MISMO TIPO. Pero surge un problema que se
entenderá mejor más adelante, cuando empecemos a crear funciones y procedimientos. ¿Qué
ocurre si queremos usar en alguna parte del programa otras variables que también sean de ese
tipo? ¿Las definimos también a la vez? En muchas ocasiones no será posible.
Así que tiene que haber una forma de indicar que todo eso que sigue a la palabra "record" es un
tipo al que nosotros queremos acceder con la misma comodidad que si fuese "integer" o
"boolean", queremos definir un tipo, no simplemente declararlo, como estábamos haciendo.
Pues es sencillo:
type NombreDeTipo = DeclaracionDeTipo;
o en nuestro caso
type TipoFicha = record
nombre: string;
direccion: string;
edad: integer;
observaciones: string
end;
Ahora sí que podremos asignar valores entre variables que hayamos definido en distintas partes
del programa, podremos usar esos tipos para crear ficheros (que también veremos más
adelante), etc.