Anterior | Superior | Siguiente

Guía de referencia básica de Ada 95

Tipos estructurados.

Introducción.

Un tipo estructurado define una agrupación de componentes de un tipo más simple; normalmente se distingue entre tipos estructurados homogéneos y tipos estructurados heterogéneos.

Estructuras homogéneas.

Definición.

Los arrays son estructuras homogéneas constituidas por un conjunto ordenado de elementos del mismo tipo a los que se puede acceder individualmente indicando su posición en el array, la cual se expresa como un conjunto de índices discretos. Un array puede ser mono o multidimensional; determinar la posición de un elemento requiere un índice por cada dimensión. Cuando se declara un array es necesario indicar el tipo de los elementos y el rango de variación de los índices de cada dimensión; si el array tiene más de una dimensión, se declara separando los rangos de cada dimensión mediante comas (",").

type TV is array(0..4) of integer;
V: TV; --elementos V(0), V(1), V(2), V(3) y V(4) de tipo integer
M:array(1..2,'A'..'B') of float; --elementos M(1,'A'), M(1,'B'), M(2,'A') y M(2,'B') de tipo float
VM: array(1..2) of TV; --array de arrays

Se pueden declarar arrays no restringidos (unconstraint arrays) especificando el tipo de los índices pero no su rango:

type TLibre is array(integer range <>) of float;

No se pueden declarar variables de un tipo no restringido: se debe definir primero un subtipo restringido o especificar directamente los rangos de los índices en la propia declaración de una variable. Se hace una excepción en el caso de los parámetros formales de un subprograma que sólo declaran una vista de los parámetros reales, para que se pueda aplicar a arrays de diferentes tamaños. En este caso el funcionamiento interno de los subprogramas depende de la adecuada utilización de operaciones "atributos" que permiten acceder a las distintas características de los arrays.

subtype TRestringido is TLibre(1..50);
A: TRestringido;
B: TLibre(1..10);
...
procedure OrdenarVector(V: in out TLibre);
...
OrdenarVector(A);
OrdenarVector(B);

Atributos.

Todos los array tienen los atributos: First, Last, Length y Range; si A es un array y N un valor entero positivo menor o igual que el número de dimensiones del array, se tiene que:

A'First es el límite inferior del rango del primer índice de A.
A'First(N) es el límite inferior del rango del N-ésimo índice de A. (A'First(1) = A'First).
A'Last es el límite superior del rango del primer índice de A.
A'Last(N) es el límite superior del rango del N-ésimo índice de A. (A'Last(1) = A'Last).
A'Range es equivalente al rango A'First .. A'Last.
A'Range(N) es equivalente al rango A'First(N) .. A'Last(N). (A'Range(1) = A'Range).
A'Length es el número de valores del rango del primer índice.
A'Length(N) es el número de valores del rango del N-ésimo índice. (A'Length(1) = A'Length).

El uso de los atributos permite escribir algoritmos aplicables independientemente del rango de las distintas dimensiones de un array.

procedure OrdenarVector(V: in out TLibre) is
   E: Float;
   P: Integer;
begin
   for I in V'First..Integer'Pred(V'Last) loop
      P := I;
      for J in Integer'Succ(I)..V'Last loop
         if V(J) < V(P) then
            P := J;
         end if ;
      end loop;
      if P /= I then
         E := V(I);
         V(I) := V(P);
         V(P) := E;
      end if;
   end loop;
end OrdenarVector;

Literales array.

Son agregados de valores del tipo de los elementos del array que se pueden utilizar para inicializar variables o constantes de tipo array, asignarlos a variables de tipo array o emplearlos en otras operaciones que involucren arrays. Un agregado posicional de un array monodimensional se forma enumerando los valores según su posición:

V: array(1..5) of integer := (12,3,45,6,8); --V(1) = 12, V(2) = 3, V(3) = 45, V(4) = 6 y V(5) = 8.

Se puede utilizar una cláusula others para dar un mismo valor a las últimas posiciones del array:

V := (12,3,45, others => 0); --V(1) = 12, V(2) = 3, V(3) = 45, V(4) = 0 y V(5) = 0.
V := (others => 0); --todas las posiciones a cero.

Para un array multidimensional se enumeran los elementos agrupándolos por dimensiones:

M: array(1..3,1..2) of character := (('a','b'),('c','d'),('e','f'));
...
M := (('a','b'),('c', others => 'd'), others => ('e','f'));

También se pueden definir agregados por asociación nominal, indicando para cada valor la posición a que corresponde, en cuyo caso se pueden enumerar salteados y desordenados:

V := (4, 3 => 15, 5 => 8, others => 0); --V(1) = 4, V(2) = 0, V(3) = 15, V(4) = 0 y V(5) = 8.
M := (3 => ('e','f'), 1 => ('a','b'), others => ('c','d'));

Rodajas (slices).

En un array monodimensional se pueden referenciar slices: son subconjuntos contiguos de elementos; sólo hay que especificar el rango del slice.

V(1..3) := V(3..5);

Un slice es un array con el rango de índices especificado; si, por ejemplo, se quiere asignar a una variable simple el primer elemento del slice que va de las posiciones 3 a la 5 de un vector, hay que tener en cuenta que el índice de dicho elemento es 3:

A := V(3..5)(3); --correcto
A := V(3..5)(1); --incorrecto

Estructuras heterogéneas.

Definición.

Los record son estructuras heterogéneas: agregados de elementos (campos) del mismo o distintos tipos que se pueden acceder individualmente mediante su nombre. Un record se define con la palabra "record", seguida de la declaración de los campos del record y "end record".

type Complejo is record
    Real, Imag: Float;
end record;

Se pueden especificar valores iniciales para los campos de un record en la propia definición del tipo.

type Complejo is record
    Real, Imag: Float := 0.0;
end record;

El acceso a los campos individuales de una variable record se consigue poniendo un punto (".") detrás del nombre de la variable y a continuación el nombre del campo al que se quiere acceder.

X, Y, Z: Complejo;
...
X.Real := 1.0;
X.Imag := 1.0;
Y.Real := X.Real;
Y.Imag := X.Imag;
Z := Y; --X, Y, Z tienen el mismo valor

Literales record.

Se pueden formar literales record para usarlos en inicializaciones, asignaciones y otras operaciones de record de dos formas:

  1. como agregado posicional, especificando los valores de todos los campos en el orden adecuado y entre paréntesis: X := (3.5, 7.1);
  2. como agregado nominal, especificando los nombres de los campos junto con los valores: X := (real => 3.5, imag => 7.1);

Cuando se usa un agregado nominal los campos se pueden enumerar en cualquier orden, pero siempre hay que enumerarlos todos.

Record variante.

Se pueden definir tipos record que puedan tener campos diferentes en función del valor de un discriminate discreto.

type Figura is (Rectángulo, Círculo);
type Polígono(Forma:Figura) is record --Forma es el discriminante
    Pos_X, Pos_Y: Float;
    case Forma is
        when Rectángulo => Base,Altura: Float;
        when Círculo => Radio: Float;
    end case;
end record;

Cuando se declaren variables hay que especificar obligatoriamente el valor del campo discriminante (excepto en la declaración de parámetros formales); una vez hecha la declaración no se puede cambiar.

R: Polígono(Rectángulo);

© Grupo de Estructuras de Datos y Lingüística Computacional - ULPGC.

Anterior | Superior | Siguiente