Lección 11 - Parte a: Subrangos y Arreglos lineales
Introducción:
Hasta ahora hemos visto, en las dos primeras partes de este curso, como crear programas que puedan hacer una cosa u otra en función de ciertas condiciones, como hacer que repitan ciertas instrucciones también de forma condicional, entre otras cosas. En todos esos programas hemos usado variables de distintos tipos, sin embargo siempre han sido tipos primitivos de Pascal, o sea, los que ya están predefinidos por el lenguaje, tales como REAL, STRING, CHAR, INTEGER, etc. Sin embargo es posible que el programador defina tipos propios que pueden contener datos más complejos que simples números, caracteres o cadenas.
Obviamente esto no es totalmente libre porque seguirá dependiendo de los tipos primitivos, pero dada nuestra imaginación podemos crear tipos realmente muy complejos y que contengan mucha información. Los posibles tipos que podemos definir nosotros mismos son:
- Subrangos
- Arreglos
- Conjuntos
- Enumerados
- Registros
- Punteros
Todos excepto Punteros, al igual que los tipos primitivos, corresponden a tipos estáticos de Pascal. Esto significa que declarada una variable de uno de esos tipos se asignará de la memoria el espacio suficiente para albergar el mayor valor posible. Este espacio de memoria estará en uso aunque nosotros no usemos la variable declarada o aunque usemos solo una parte de la información que esta pueda guardar. Este espacio de memoria se asigna ya al compilar el programa, o sea, en tiempo de compilación. Esto no significa que al compilar el programa estemos ocupando nuestra RAM con las variables que el programa use, sino que al compilarlo se agregan las instrucciones que harán que el programa solicite esa memoria ya al ser ejecutado y la mantendrá siempre en uso hasta que se cierre.
Los Punteros corresponden a un tipo dinámico. Esto es que, podremos pedir memoria cuando la necesitemos y devolverla cuando ya no la usemos, todo en tiempo de ejecución, pero este será el último tema de este curso.
Subrangos:
Muy bien, el primer tipo a definir por el usuario que veremos es llamado subrango. Este es el tipo más sencillo de declarar. Consiste en crear un Subrango de uno de los tipos primitivos ordinales de Pascal. Por ejemplo, un Subrango de los enteros podrían ser los naturales, ya que estos son lo enteros de 0 en adelante (algunos los toman de 1 en adelante).
Los tipos a definir se declaran antes que las variables pero luego que las constantes. Para ello debemos indicar mediante la palabra reservada TYPE que haremos declaración de tipos. Veamos un ejemplo de declaración de subrangos:
Código:
Aquí hemos declarado seis tipos Subrangos diferentes. Como ven la sintaxis es bien sencilla, luego de la palabra TYPE se declaran todos los tipos necesarios de esta manera:Type Naturales= 0..MAXINT; Mes= 1..12; Decimal= 0..9; Minusculas= 'a'..'z'; Digito= '0'..'9'; Mayusculas= 'A'..'Z';
Identificador= valor_inicial..valor_final;
En este ejemplo tenemos el tipo Naturales que contendrá valores enteros entre 0 y MAXINT. Luego está el tipo Mes que contendrá enteros entre 1 y 12. Decimal contendrá valores entre 0 y 9. Luego vemos tres subrangos de caracteres: Minusculas que contendrá los caracteres de la a a la z. Esto es porque las letras están ordenadas según la Tabla Ascii ascendentemente y sabemos que ‘a’<’z’. Digito contendrá los caracteres del '0' al '9'. Notar que Digito contiene los caracteres numéricos y Decimal los valores enteros de esos números. NO ES LO MISMO.
Finalmente tenemos el tipo Mayusculas que contiene caracteres de la A a la Z.
Dado que estos son tipos, para usarlos debemos declarar variables de ese tipo:
Código Pascal:
Ver original
Type Naturales= 0..MAXINT; Mes= 1..12; Decimal= 0..9; Minusculas= 'a'..'z'; Digito= '0'..'9'; Mayusculas= 'A'..'Z'; Var letraMin: Minusculas; numero: Naturales; letraMay: Mayusculas;
Como ven es la misma sintaxis que para declarar una variable de tipo primitivo, le damos un identificador, dos puntos y luego el nombre del tipo. Esto significa que la variable letraMin podrá tomar valores de la a a la z ya que es del tipo Minusculas. Como el Subrango Minusculas corresponde a un Subrango de caracteres, letraMin se comportará como una variable char con la diferencia de que no podrá tomar valores fuera del rango indicado por Minusculas. Si esto sucede tendremos un error en tiempo de ejecución. Si han activado Range checking como se los indiqué al inicio del tutorial, el compilador verificará esto en la medida de lo posible y se los advertirá, pero no siempre podrá hacerlo. Por ejemplo, si ustedes hacen read(letraMin) el compilador no podrá asumir que el usuario puede ingresar un carácter fuera del rango y por tanto compilará correctamente, pero si hacen, letraMin:= ‘A’ les advertirá su error. Hay más casos de esto, pero lo verán en la práctica.
Lo mismo sucede para los subrangos Decimal, Mes y Naturales, que son subrangos de integer. Las variables de estos tipos funcionarán como variables enteras con la diferencia de que deben tomar valores dentro de los rangos establecidos.
Visto de esta manera no puedo incentivarlos mucho con el uso de los subrangos, sin embargo veremos que resultan útiles para definir Arreglos, que es el tema que viene a continuación.
Lo que puedo decirles es que al definir un Subrango ustedes podrán estar seguros de que sus variables tendrán los valores adecuados.
Arreglos:
Declaración:
Un arreglo es una tabla compuesta por celdas que contienen, todas, valores de un mismo tipo.
Ese es un ejemplo de un arreglo de enteros compuesto por nueve celdas. Cada celda tiene un valor distinto (pueden no serlo) y cada una es independiente de las demás. Como pueden ver todas las celdas están numeradas del 1 al 9. Estos valores son llamados subíndices y son los que usaremos para dirigirnos a una celda específica. Veamos primero cómo se declara un arreglo:
Identificador= array[Subrango] of tipo;
Debemos indicar un nombre para el arreglo (identificador), luego, al igual que para los subrangos va un signo de igual ( = ) y la palabra reservada array (arreglo en inglés) seguida inmediatamente por un Subrango entre paréntesis rectos [] el cual indicará la dimensión del arreglo (cuantas celdas tendrá). Luego colocamos la palabra reservada of y un tipo para los valores que habrá en cada celda. Este tipo puede ser uno primitivo de Pascal o uno definido anteriormente por el programador. Veamos algunos ejemplos:
El arreglo dibujado arriba podría estar declarado como:
Código:
En este ejemplo le dimos el nombre Arreglo1. Declaramos directamente entre los paréntesis rectos un Subrango. La dimensión de ese Subrango indica la dimensión del arreglo, en este caso el Subrango va de 1 a 9 por tanto contiene 9 elementos. Esto indica que el arreglo tendrá nueve celdas. Es importante notar que esto indica solo la dimensión del arreglo y no el tipo de datos que contendrá, o sea, Arreglo1 no contendrá datos que solo vayan de 1 a 9 sino que contendrá cualquier entero en sus celdas ya que su tipo está declarado luego de of y es integer.Arreglo1= array[1..9] of integer;
El Subrango entre paréntesis rectos, además de indicar cuántas celdas tendrá el arreglo, también indica cómo se numeran. Arreglo1 tendrá 9 celdas numeradas del uno al nueve, sin embargo, de haberse declarado
Código:
sería igual al anterior solo que sus nueve celdas estarían numeradas del 10 al 19, o de haberse declarado de esta manera Arreglo1= array[10..19] of integer;
Código:
seguiría teniendo nueve celdas solo que estarían identificadas de la a a la i.Arreglo1= array[‘a’..’i’] of integer;
Lo más común es numerarlas del 1 en adelante y es lo recomendable.
Tal como hemos declarado esos arreglos estamos declarando sus dimensiones con subrangos anónimos, o sea, declarando estos justo dentro de los paréntesis rectos sin darles nombre alguno. Sin embargo también es posible colocar dentro de estos paréntesis un Subrango ya declarado anteriormente. Por ejemplo:
Código:
Como ven, teniendo declarado antes el Subrango Decimal es posible utilizarlo para definir la dimensión y numeración del arreglo. En este caso Arreglo1 tendrá 10 celdas numeradas del 0 al 9.Type Decimal= 0..9; Arreglo1= array[Decimal] of integer;
También es posible hacer esto
Código:
En este caso, el arreglo tiene 10 celdas numeradas del 0 al 9 y cada una puede contener datos del tipo Decimal. Siempre es posible utilizar algún tipo para definir otro sí y solo sí el tipo a utilizar está definido anteriormente. No sería posible utilizar Decimal para definir el arreglo si declaráramos este Subrango más abajo que el arreglo.Type Decimal= 0..9; Arreglo1= array[Decimal] of Decimal;
Un arreglo es un tipo y por tanto va declarado luego de la palabra Type tal como se ve en estos dos ejemplos.
Veamos ahora más ejemplos de arreglos:
Código:
Sigue en la parte b. Type rango = 33..90; arr1 = array [char] of integer; (* 256 celdas *) arr2 = array [33..90] of real; arr3 = array [integer] of char; (* demasiado grande! *) arr4 = array [rango] of boolean;