Sunteți pe pagina 1din 40

GUIAPRCTICADEADA95

1. EstructurabsicadeunprogramaenAda. 2. Variables,constantesytipos. 3. Declaracindevariables 4. Definicindeconstantes 5. Definicindetipos 6. Tiposescalares. 7. Enumerados 8. Enteros 9. Operacionescontiposordinales 10. Reales 11. Sentencias,asignacinyexpresiones. 12. Entrada/salida. 13. Sentenciasdecontrol. 14. Subprogramas. 15. Tiposestructurados. 16. Ristrasdecaracteres. 17. Excepciones. 18. Ficheros. 19. Ficherosdetexto 20. Ficherosuniformes 21. Memoriadinmica. 22. EstructurageneraldeunprogramaenAda. 23. Packages. 24. Tiposprivateylimitedprivate. 25. Unidadesgenricas. 26. Parmetrizacindeunidadesgenricas.

GuaPrcticadeADA95

1/40

Estructura bsica de un programa en Ada.


Un programa en Ada consta de al menos dos partes: una clusula de contexto y un procedimiento principal.
Programa simple en Ada with Text_IO; clusula de contexto procedure Hola is procedimiento principal Parte de declaraciones begin Cuerpo de sentencias ejecutables Text_IO.Put_Line(Hola); end Hola;

(Las lneas a partir de los dobles guiones,, son comentarios. Todas las sentencias en Ada deben terminar con un punto y coma (;)) Las clusulas de contexto sirven para especificar el uso de libreras externas al programa. Una librera es un conjunto de recursos (procedimientos, funciones, tipos, ) ya desarrollados y compilados, y que se hallan disponibles para ser usados por nuestros programas. En el caso del ejemplo, la clusula with de la 2 lnea est indicando que nuestro programa va a hacer uso de la librera Text_IO, la cual proporciona servicios bsicos de entrada/salida; concretamente, en el ejemplo se est usando el procedimiento Put_Line, que saca un mensaje por pantalla, y se especifica que hay que buscarlo en la librera Text_IO, antecediendo al nombre del procedimiento con el nombre de la librera seguido por un punto (.). Si se quiere evitar tener que hacer este tipo de cualificaciones con todos los recursos externos que se empleen, se habr de disponer una clusula use como en el siguiente ejemplo:
Programa simple en Ada with Text_IO; clusula de contexto use Text_IO; procedure Hola is procedimiento principal Parte de declaraciones begin Cuerpo de sentencias ejecutables Put_Line(Hola); ya no es necesario poner Text_IO. end Hola;

El procedimiento principal es el punto de arranque del programa, del que dependen en ltima instancia, todos los dems procedimientos y funciones que se utilicen. Un procedimento consta de: (1) una cabecera (lnea 5 del segundo ejemplo), donde se le da nombre, (2) una seccin de declaraciones, donde se declaran y/o definen todos los elementos que el procedimiento va a utilizar (variables, constantes, tipos, procedimientos, funciones, ), y (3) el cuerpo del procedimiento las sentencias que describen su algoritmo, lneas 7 a 10, que comienza con la palabra begin y termina con la palabra end acompaada del nombre del procedimiento. El cuerpo de un procedimiento no puede estar vaco, en caso de desear, circunstancialmente, tener un procedimiento que no haga nada, debe de contener la instruccin null;.

GuaPrcticadeADA95

2/40

Variables, constantes y tipos.


Declaracin de variables.
Las variables se declaran como nombre_de_variable : tipo, tal como en el siguiente ejemplo:
x : integer; una variable de tipo integer llamada x

Si hay que declarar varias variables del mismo tipo, se puede formar una lista, aunque ello no es obligatorio:
x, y, z : integer;

Las variables pueden inicializarse con un valor en el momento de su declaracin:


x, y, z : integer := 0;

Definicin de constantes.
Para definir una constante, se hace igual que para declarar una variable inicializndola al mismo tiempo, pero poniendo la palabra constant antes del tipo.
c: constant integer := 10;

Ahora bien, si se trata de constantes numricas, tambin se pueden definir sin especificar su tipo:
pi: constant := 3.1416;

Definicin de tipos.
Ada, como todos los lenguajes, ofrece un conjunto bsico de tipos predefinidos junto con mecanismos para definir nuevos tipos. Para definir un nuevo tipo, se usa la palabra type, seguida del nombre del nuevo tipo; la palabra is, y la descripcin del nuevo tipo:
type byte is range 0..255;

Ada, tambin ofrece la posibilidad de definir un subtipo de un tipo ya definido. Por ejemplo:
subtype byte is integer range 0..255;

La diferencia entre ambas definciones de byte, es que en la segunda, al ser un subtipo, es una versin restringida el tipo base de la definicin (en este caso, integer), mientras que en la primera se est definiendo un tipo distinto, que no es compatible con el integer, a pesar de que su rango de valores parezca coincidir con una parte de los enteros. De hecho, se puede declarar un nuevo tipo para que sea en todo igual a otro existente, y sin embargo incompatible:
type MiEntero is new integer; type MiEnteroCorto is new integer range 0..255;

GuaPrcticadeADA95

3/40

Tipos escalares.
Los tipos en Ada se clasifican en escalares (simples) y estructurados. Los escalares se dividen en: discretos, u ordinales, y no discretos. Los tipos discretos son enumerados y enteros. Los no discretos son los reales. Tanto los enteros como los reales se clasifican a su vez como numricos. Los tipos enumerados son aquellos que se definen especificando la lista ordenada de valores que lo componen:
type type type type type Da is (Lun, Mar, Mie, Jue, Vie, Sab, Dom); Palos is (Oros, Bastos, Espadas, Copas); Gnero is (M, F); Color is (Blanco, Rojo, Amarillo, Verde, Azul, Marrn, Negro); Luz is (Rojo, Naranja, Verde);

Una vez definido el tipo, se pueden declarar variables. Si, como ocurre con los tipos Color y Luz, hay valores que se repiten, habr que cualificar ese valor cuando su uso pueda ser ambiguo:
x := ColorRojo; x debe ser de tipo Color y := LuzRojo; y debe ser de tipo Luz

Ada tiene predefinido el tipo enumerado character que representa el alfabeto de caracteres utilizado, y el tipo boolean, que puede tomar los valores true o false. Ada posee un tipo integer predefinido cuyo rango de valores depende de la implementacin del lenguaje. Adems, se pueden definir nuevos tipos enteros que pueden ser, con signo o sin signo:
type MiEntero is range -32768..32767; Entero con signo type MiNatural is mod 32767; Entero sin signo (rango 0..32766)

En ambos casos se pueden usar expresiones para definir los lmites del tipo:
type MiEntero is range -2**15..2**15; Entero con signo type MiNatural is mod 2**16; Entero sin signo (rango 0..65535)

Existen predefinidos en el paquete standard dos subtipos del tipo integer:


subtype Natural is integer range 0..Integerlast; subtype Positive is integer range 1..Integerlast;

Todos los tipos ordinales tienen asociadas, entre otras, las siguientes operaciones como atributos (todas se usan cualificadas con el nombre del tipo), sea T un tipo ordinal: Tsucc(x) devuelve el valor que sigue a x en la lista de valores del tipo (el ltimo valor no tiene sucesor) Tpred(x) devuelve el valor que precede a x en la lista de valores del tipo(el primer valor no tiene predecesor) Tpos(x) devuelve la posicin que ocupa x en la lista de valores del tipo (al primer valor le corresponde la posicin 0) Tval(x) devuelve el valor correspondiente a la posicin x en la lista de valores del tipo

GuaPrcticadeADA95

4/40

Tfirst devuelve el valor ms pequeo del tipo Tlast devuelve el mayor valor del tipo Trange devuelve el nmero de valores posibles del tipo Ejemplos:
x:=Dasucc(Mar); x toma el valor Mie x:=Dapred(Mar); x toma el valor Lun y:=DaPos(Mar); y toma el valor 1 x:=DaVal(3); x toma el valor Jue

Ada tambin tiene un tipo predefinido, float, para representar nmeros reales, cuyo rango y precisin dependen de la implementacin. No obstante, el programador tambin puede definir sus propios reales con dos posibles formatos: coma fija y coma flotante. Al definir un tipo real de coma flotante se puede especificar el nmero de dgitos significativos, y el rango de valores posibles.
type rflotante is digits 5 range -1.0..1.0;

Al definir un tipo real de coma fija, se pretende obtener una precisin definida. Los nmeros reales en coma fija se pueden catalogar en: ordinarios y decimales. En el primer caso, se especifica el lmite de error en su representacin (delta) y, si se quiere, el rango de variacin. En el segundo se indica el nmero de dgitos significativos y el incremento entre valores sucesivos admitidos (delta).
type rfija1 is delta 0.01 range -1.0..1.0; Coma fija ordinario type rfija2 is delta 0.01 digits 5; Coma fija decimal

En el caso de nmeros decimales en coma fija, el delta tiene que ser potencia de 10.

Sentencias, asignacin y expresiones.


Toda sentencia en Ada termina en punto y coma (;). Existe la sentencia nula (que no hace nada), y se expresa como null;. La asignacin se expresa con el smbolo :=. Ejemplo:
x := 3;

En la parte izquierda de la asignacin debe ir una variable. En la parte derecha de la asignacin va una expresin de un tipo adecuado. Una expresin est formada por operandos (constantes, variables, expresiones, ) y operadores. Como resultado de su evaluacin una expresin da lugar a un valor. El tipo de la expresin es el tipo del valor resultante. Ejemplos:
-4.0 -4.0 + A

GuaPrcticadeADA95

5/40

B**2 - 4.0*A*C Index = 0 or Item_Hit (Cold and Sunny) or Warm A**(B**C)

Entrada/salida.
Las funciones bsicas de entrada/salida son: get(X), put(X) para X de tipo character, string, integer o float get_line(S,L), put_line(S) para S de tipo string. L es la longitud leda. Leen o escriben una string en una lnea y pasan a la siguiente. new_line, que, cuando se est escribiendo, inicia una nueva lnea. skip_line, que, cuando se est leyendo, desestima el resto de la lnea actual. Para realizar entrada/salida de ristras o caracteres basta con incluir la clusula de contexto with Text_IO;. Para realizar entrada/salida de otros tipos escalares hay que hacer, adems, una declaracin, en la seccin de declaraciones del procedimiento, que especifica la aplicacin de un paquete genrico de entrada/salida adecuado sobre el tipo en cuestin (a esto se llama crear una instancia del paquete), tal como se muestra en los siguientes ejemplos:
package Da_IO is new Enumeration_IO(Da); Enumeration_IO sirve para tipos enumerados package MiEntero_IO is new Integer_IO(MiEntero);Integer_IO sirve para enteros con signo package rf_IO is new Float_IO(rf); Float_IO sirve para reales en coma flotante package rfija1_IO is new Fixed_IO(rfija1);Fixed_IO sirve para reales en coma fija ordinarios package rfija2_IO is new Decimal_IO(rfija1);Decimal_IO sirve para reales en coma fija decimales package Natural_IO is new Modular_IO(Natural);Modular_IO sirve para enteros sin signo

En cualquier caso, hay que utilizar la clusula with Text_IO;, puesto que estos paquetes de entrada/salida (Enumeration_IO, Integer_IO, Float_IO, ), se encuentran incluidos en la librera Text_IO.

Sentencias de control.
Seleccin de dos alternativas.
if Exp_lgica then if Exp_lgica then sentencias; sentencias; end if; else sentencias; end if;

Seleccin mltiple.
case selector is when alternativa => sentencias;

GuaPrcticadeADA95

6/40

when alternativa => sentencias; when others => sentencias; end case; El selector debe ser una expresin discreta de tipos integer o enumerados (tipo ordinal). Las alternativas pueden ser uno o varios valores, o rangos, del tipo del selector separados por | (equivale al operador OR). case mes is when 1 .. 2 | 12 => put(El invierno es duro); when 3 .. 5 => put(Primavera de la vida); when 6 .. 8 => put(Estacin llena de diversin); when 9 .. 11 => put(poca de reflexin); when others => put(En qu planeta ests?); end case; Los valores no pueden repetirse entre dos clusulas when. En el caso de que las clusulas when no cubran todos los posibles valores del tipo del selector, es necesario incluir la clusula others para los valores no contemplados.

Iteracin.
Controlada por contador. for variable in [reverse] secuencia de control loop end loop; La variable de control es local al bucle, NO SE DECLARA (es del tipo de la secuencia de control) y no puede modificarse explcitamente. La secuencia de control puede ser un rango de un tipo ordinal (entero o enumerado). Cuando se utiliza reverse la secuencia de control se recorre en orden inverso: for num in reverse 1..5 loop Put(num); escribe 5 4 3 2 1 end loop; Controlada por condicin lgica. while condicin loop end loop; Bucles sin esquema de iteracin. En Ada se puede construir un bucle tal como: loop end loop;

GuaPrcticadeADA95

7/40

del que se sale, normalmente, mediante una sentencia exit when o con una alternativa que contenga una clusula exit. loop exit when condicin; end loop;

Bloques.
Un bloque es una sentencia compuesta, formada por una secuencia de sentencias agrupadas mediante las palabras delimitadoras begin, end, y posiblemente acompaadas de algunas declaraciones locales.
[declare declaraciones locales] begin sentencias end;

(la parte delimitada por corchetes es opcional) Un bloque puede ponerse en cualquier sitio donde pueda ponerse una sentencia simple. Ejemplos de bloques:
bloque sin declaraciones locales begin Put_Line(Hola); end; bloque con declaraciones locales declare Aux : integer; la variable Aux slo existe dentro del bloque begin Aux := i; i, j estn declarados en un mbito ms externo i := j; j := Aux; end;

Subprogramas.
Definicin de subprogramas.
Un subprograma es un procedimiento o funcin. La estructura de la definicin de un subprograma consta de tres elementos: 1. Cabecera 2. Declaraciones locales 3. Sentencias ejecutables

GuaPrcticadeADA95

8/40

La cabecera describe el protocolo del subprograma, y consta de: especificacin de procedure o function, nombre del subprograma, lista de parmetros y tipo del resultado, caso de ser una function. procedure Nombre_procedimiento (parmetros) is function Nombre_funcin (parmetros) return Tipo is La lista de parmetros est formada por especificaciones de parmetros formales separadas por ;. Cada especificacin de parmetros consta de una lista de nombres de parmetros separados por , y seguida de :, el modo de paso (in, out o in out) y el tipo de los parmetros. procedure LisParam(S1,S2: in integer;S3: out float) is

Los parmetros in son constantes y no pueden modificarse en el subprograma. Los parmetros in out pueden usarse y modificarse. Las funciones slo tienen parmetros in.

La parte de sentencias ejecutables comienza con la palabra begin y abarca hasta que aparezca la palabra end seguida del nombre del subprograma y ;. La parte de declaraciones locales abarca desde la cabecera hasta la palabra begin que da comienzo a las sentencias ejecutables. Los elementos declarados (variables, tipos, subtipos, procedimientos,) tienen mbito esttico. Ejemplo de subprogramas with Text_IO; use Text_IO; procedure Ejemplo is procedimiento principal Ejemplo requerimientos de entrada/salida; package Sal1 is new Integer_IO(integer); package Sal2 is new Float_IO(float); use Sal1, Sal2; funcin local EsPar
function EsPar(x: in integer) return boolean is begin return ((x rem 2) = 0); end EsPar;

procedimiento local Media


procedure Media(x,y: in float;med: out float) is dos: float; variable local begin dos := 2.0; med := (x + y) / dos; end Media;

R1,R2,R3 : float; variables locales de Ejemplo i : integer; begin put(Entre un numero: ); Get(i); skip_line;
if EsPar(i) then put_line(es par); else put_line(no es par); end

GuaPrcticadeADA95

9/40

if;

put(Entre una pareja de numeros separados por un espacio: ); Get(R1); Get(R2); skip_line; Media(R1,R2,R3); Put(R3); new_line; end Ejemplo;

Sobrecarga de operadores.
Ada permite que el programador sobrecargue los operadores del lenguaje, esto es, que pueda redefinirlos dndoles nuevos significados. Para sobrecargar un operador, simplemente hay que definir una funcin cuyo nombre sea el operador entre comillas y que tenga los parmetros adecuados. Por ejemplo, dado el siguiente tipo:
type Complejo is record PReal, PImag: float; end Complejo;

podemos sobrecargar el operador de suma (+) para utilizarlo con el fin de sumar nmeros complejos:
function +(A, B : in Complejo) return Complejo is Suma: Complejo; begin Suma.PReal := A.PReal + B.PReal; Suma.PImag := A.PImag + B.PImag; return Suma; end +;

Una vez definida esta funcin, se puede aplicar el operador entre variables del tipo definido en los parmetros, devolviendo un valor del tipo definido como resultado.
S, X, Y: Complejo; S := X + Y;

Slo se pueden redefinir los operadores del lenguaje (no se pueden inventar operadores), y siempre manteniendo su cardinalidad (los binarios se redefinirn con funciones de dos parmetros y los unarios con funciones de un parmetro).

Tipos estructurados.
Arrays.
Los arrays son estructuras homogneas, es decir, estn formados por un conjunto ordenado de elementos del mismo tipo que se pueden acceder individualmente mediante ndices discretos. En Ada hay dos clases de arrays: restringidos y no restringidos. Los restringidos son arrays para los que se especifica el tamao en su definicin (tamao fijo). Los no restringidos son aquellos en los que el rango de los ndices no se establece al definir el tipo, sino que se concreta posteriormente.

GuaPrcticadeADA95

10/40

type Vector is array(1..10) of float; array restringido de 10 elementos type Libre is array(integer range <>) of float; array no restringido V: Vector; L: Libre(1..10); Si el array tiene ms de una dimensin, se declara separando los rangos de cada dimensin mediante comas (,).
type Matriz is array(1..5,1..3) of integer;matriz de 53 A: Matriz;

Los arrays tienen los siguientes atributos: First, Last, Range, Length. Si A es un array, entonces: AFirst es el lmite inferior del rango del primer ndice de A. AFirst(N) es el lmite inferior del rango del N-simo ndice de A ALast es el lmite superior del rango del primer ndice de A. ALast(N) es el lmite superior del rango del N-simo ndice de A ARange es equivalente al rango AFirst .. ALast. ARange(N) es equivalente al rango AFirst(N) .. ALast(N). ALength es el nmero de valores del rango del primer ndice. ALength(N) es el nmero de valores del rango del N-simo ndice.
Ejemplo que recorre una matriz escribiendo sus elementos for i in ARange(1) loop for j in AFirst(2)..ALast(2) loop put(A(i,j)); put( ); end loop; new_line; end loop;

Literales arrays e inicializacin de arrays. Se puede expresar un valor literal de tipo array utilizando parntesis para agrupar los valores por filas y columnas. Se puede utilizar la palabra others para indicar un valor por defecto para las posiciones que no se especifiquen explcitamente. Un literal de tipo array se puede utilizar, entre otras cosas, para inicializar una variable de tipo array en su declaracin.
type matriz is array(1..5,1..5) of integer; type vector is array(1..5) of integer; v1 : vector := (1,2,3,4,5); v2 : vector := (9,8,7, others => 0); v3 : vector := (1 => 9, 3 => 8, 5 => 7, others => 0); m1 : matriz := (others => (others => 0)); m2 : matriz := ((1,2,3,4,5), (1,2,others => 0), (1 => 9, 3 => 8, 5 => 7, others => 0), others => (others => 0));

GuaPrcticadeADA95

11/40

Rodajas (slices). Se puede hacer referencia a un trozo de un array monodimensional, simplemente especificando sus lmites. Este tipo de corte se conoce como rodaja o slice.
v1(1..3):= v2(3..5);

Records.
Los records son estructuras heterogneas, es decir, agregados de elementos del mismo o distintos tipos que se pueden acceder individualmente mediante su nombre. Un record se define con la palabra record, seguida de la declaracin de los campos del record y end record. type Complejo is record real: float; imag: float; end record; Para acceder a una campo individual de un record se utiliza el operador punto (.); mediante el nombre de la variable cualificada con el nombre del campo en cuestin:
x,w : Complejo; Declaracin de variables de tipo record y : array (1..20) of Complejo; Declaracin annima de un array x.real := 3.0; x.imag := x.real; y(7) := x; y(1).real := 3.0;

Literales records e inicializacin de records. Se pueden formar literales records de dos formas:

como agregado posicional, especificando los valores de todos los campos en el orden adecuado y entre parntesis
x := (3.5, 7.1);

como agregado nominal, especificando los nombres de los campos junto con los valores
w := (real => 3.5, imag => 7.1); w := (imag => 7.1, real => 3.5);

Ristras de caracteres.
Ada ofrece los tres tipos posibles de ristras de caracteres: tamao fijo, tamao limitado y tamao dinmico.
GuaPrcticadeADA95

12/40

Clusula de contexto
Para usar ristras de tamao fijo, tamao limitado y tamao dinmico, hay que incluir en la clusula with los paquetes Ada.Strings.Fixed, ada.Strings.Bounded y Ada.Strings.Unbounded, respectivamente.
with Text_IO, Ada.Strings.Fixed, Ada.Strings.Bounded, Ada.Strings.Unbounded;

En la cusula use slo hay que incluir Ada.Strings.Fixed y Ada.Strings.Unbounded, ya que las ristras de tamao limitado (bounded) necesitan una instanciacin para fijar la longitud mxima antes de poder usarse.
use Text_IO, Ada.Strings.Fixed, Ada.Strings.Unbounded;

Declaracin
Una ristra de tamao fijo es bsicamente un array de caracteres que se declara con la palabra String y especificando el rango de variacin de los ndices, que debe ser de tipo Positive. (Lo ms normal es que este rango empiece en 1). sf1, sf2 : String(1..10); variables de tipo ristra de 10 caracteres Antes de declarar ristras de tamao limitado es necesario instanciar el subpaquete genrico llamado Ada.Strings.Bounded.Generic_bounded_length para el tamao mximo que se desee (esto se hace para poder tener instancias para distintas longitudes).
package String_max_10 is new Ada.Strings.Bounded.Generic_bounded_length(10); use String_max_10;

Una vez hecho esto se pueden declarar variables de tamao limitado (tipo Bounded_string), cualificando el nombre del tipo con el de la instancia definida. sl1, sl2 : String_max_10.Bounded_string; ristras de hasta 10 caracteres Las ristras de longitud dinmica se declaran del tipo Unbounded_string. sd1, sd2 : Unbounded_string; ristra de longitud dinmica

Ristra nula
En las ristras de tamao fijo no existe la ristra nula, dado que una variable de tipo String siempre tiene la longitud definida (Ada utiliza caracteres de relleno, por defecto es el espacio). La ristra nula para las ristras de tamao limitado est representada por el valor Null_Bounded_String.
sl1 := Null_Bounded_String.

La ristra nula para las ristras de tamao dinmico est representada por el valor Null_Unbounded_String.
sd1 := Null_Unbounded_String;

Tambin sirve para representar la ristra nula una ristra fija vaca, que se representa mediante dos dobles comillas ("), pero para ello son necesarias las funciones de coversin entre ristras.

GuaPrcticadeADA95

13/40

Literales ristra
Un valor de tipo ristra se escribe como una secuencia de caracteres delimitada por comillas dobles: esto es una ristra. Un valor literal es una ristra de tamao fijo cuyo tamao es igual al nmero de caracteres de que consta (18 en el ejemplo). Los literales de tipo Character se delimitan por comillas simples. a esto es una ristra. a esto es un carcter, no es una ristra.

Conversin entre ristras


En los respectivos paquetes, existen funciones para convertir ristras de tamao fijo a ristras de tamao limitado o dinmico y viceversa. sl1 := to_bounded_string(esta linea); conversin de string a bounded-string sf1 := to_string(sl1); conversin de bounded_string a string sd1 := to_unbounded_string(esta linea);conversin de string a unbounded_string sf2 := to_string(sd1); conversin de unbounded_string a string La conversin entre ristras limitadas y dinmicas ha de hacerse a travs de ristras de tamao fijo. sd2 := to_unbounded_string(to_string(sl1));conversin limitada->fija>dinmica sl2 := to_bounded_string(to_string(sd1)); conversin dinmica->fija>limitada Se puede asignar la ristra nula convirtiendo una ristra fija vaca. sl1 := to_bounded_string("); asigna la ristra nula a sl1 sd1 := to_unbounded_string("); asigna la ristra nula a sd1

Asignacin
Se pueden asignar entre s ristras del mismo tipo (son de distinto tipo las ristras limitadas de diferente tamao). En las ristras de tamao fijo, la asignacin slo puede realizarse entre ristras del mismo tamao:
sf1 := 1234567890;

Si se necesita asignar una ristra de un tamao distinto, se puede emplear la operacin move:
move(prueba, sf1);

La operacin move admite hasta 5 parametros:


procedure Move (Source Target Drop : in String; : out String; : in Truncation := Error;

GuaPrcticadeADA95

14/40

Justify : in Pad : in

Alignment Character

:= Left; := Space );

Source es la ristra origen Target es la ristra destino Drop determina que accin se tomar en caso de que la ristra origen sea mayor que la destino (las acciones posibles son: left, que corta la ristra por la izquierda, rigth, que corta la ristra por la derecha, y error)

Justify determina, en caso de que la ristra origen sea menor que la destino, cmo se situar (left, a la izquierda, center, en el centro, y rigth, a la derecha) Pad determina, en caso de que la ristra origen sea menor que la destino, con qu carcter se rellenarn las posiciones sobrantes

Entrada / Salida
Slo las ristras de tamao fijo pueden intervenir en operaciones de entrada/salida (ello no es un gran problema al existir las funciones de conversin). Una ristra se lee con la operacin get(X) o get_line(X,L), donde X es una variable de tipo String y L es una variable de tipo Natural o compatible con l. La primera exige que se entre el nmero exacto de caracteres, de acuerdo con la declaracin de la ristra; la segunda permite la entrada de un nmero menor de caracteres, e indica en el segundo parmetro el ndice del ltimo carcter ledo (si el rango de la ristra empieza en uno, esto es igual al nmero de caracteres ledos). Cuando se lee una ristra con get_line, los caracteres ledos sustituyen a los correspondientes que hubiese en la ristra, pero el resto quedan como estaban.
sf1 := 1234567890; get_line(sf1,l_sf1); l_sf1 es una variable de tipo Natural o compatible

Suponiendo que el usuario introduce la ristra abcde, sf1 quedar con el valor abcde67890. Asimismo, las ristras de tipo String se escriben con las operaciones put(X) o put_line(X). La diferencia entre ambas es que la segunda produce un salto de lnea despus de escribir la ristra.

Clculo de la longitud
En ristras de tamao fijo esta operacion carece de sentido. En ristras de tamao limitado o de tamao dinmico se utiliza una funcin llamada Length, que devuelve la longitud de la ristra. x := Length(ULPGC); x toma el valor 5

Extraccin de una subristra


En ristras de tamao fijo esta operacin se realiza mediante slices (rodajas), igual que en los arrays.
put_line(sf1(1..5));

GuaPrcticadeADA95

15/40

En los otros tipos de ristras, se ha de utilizar una funcin llamada Slice. function Slice ( Source : in Bounded_String; Source tambin puede ser del tipo Unbounded_String
Inicio : in Positive; Fin : in Natural ) return String; Move(Slice(sl1,1,5),sf2); copia en sf2 la subristra formada por los

caracteres de sl1 desde el 1 al 5 Hay que tener cuidado de que los lmites del slice estn comprendidos dentro del rango de ndices de la ristra, ya que si no se producira un error.

Concatenacin
Se utiliza como operador de concatenacin el operador &, que funciona entre todo tipo de ristras y entre ristras y caracteres.
sl2 := To_Bounded_String(algo ); sl1 := sl2 & nada; sl1 toma el valor algo nada

Con las ristras de tamao limitado se puede utilizar la funcin append:


function Append (Left, Right : in Bounded_String; Drop : in Truncation := Error ) return Bounded_String;

En este caso, la funcin devuelve la ristra resultante de concatenar Left y Right. El parmetro Drop indica qu hacer en caso de que la ristra resultante exceda el tamao mximo permitido. Los valores posibles de Drop son: Error (produce un error), Left (trunca la ristra por la izquierda) y Right (trunca la ristra por la derecha). Existen versiones para concatenar ristras de tamao limitado con ristras de tamao fijo o con caracteres. Con las ristras de tamao dinmico se puede utilizar el procedimiento append:
procedure Append (Source : in out Unbounded_String; New_Item : in Unbounded_String);

En este caso, no se necesita el parmetro Drop, ya que el tamao de las ristras no est lmitado. Existen versiones de Append para concatenar una ristra de tamao dinmico con una ristra de tamao fijo o con un carcter, en este orden.

Localizacin de una subristra


Se realiza mediante la funcin Index.
function Index ( Source Pattern return Natural; s1,s2 : s3 : s1 := s2 := string(1..5); string(1..10); 12345; abcde ; : in String; : in String ) Source tambin puede ser del

tipo Bounded_String o Unbounded_String

GuaPrcticadeADA95

16/40

s3 := s1 & s2; put(Index(s3,45)); Se escribe un 4

Operadores relacionales
Los operadores relaciones (=, /=, <, >, <=, >=) son aplicables entre ristras atendiendo al alfabeto utilizado.

Ms sobre ristras
Los paquetes Ada.Strings.Fixed, Ada.Strings.Bounded y Ada.Strings.UnBounded contienen un gran nmero de otras operaciones para el tratamiento de ristras de tamao fijo, limitado y dinmico respectivamente.

Excepciones.
Introduccin.
En la ejecucin de un programa pueden darse muchas situaciones inesperadas, bien errores, bien casos muy particulares no previstos. Tener en cuenta todas las posibles situaciones anmalas oscurecera los algoritmos. El mecanismo de manejo de excepciones permite controlar estas situaciones sin tener que cargar con ese efecto indeseado. Normalmente, la ocurrencia de un error causa la terminacin del programa con un mensaje indicando la excepcin ocurrida. En el estndar de Ada estn definidas las siguientes excepciones: Constraint_error.- ocurre cuando se intenta asignar a una variable un valor no vlido, o cuando se intenta acceder a una posicin de un array fuera del rango permitido. Program_error.- ocurre en situaciones extraas cuando parte de un programa no es accesible, o cuando se alcanza el end de una funcin sin encontrar un return. Storage_error.- ocurre cuando se agota la memoria disponible. Tasking_error.- est relacionado con errores en programas que utilicen programacin concurrente. Las excepciones se lanzan automticamente cuando se produce un error. Tambin pueden ser lanzadas manualmente mediante una sentencia raise en cualquier lugar de un programa.
raise Constrain_error; produce la excepcin Constrain_error

No es normal lanzar manualmente una excepcin predefinida; la utilidad de raise consiste en lanzar excepciones definidas por el programador.

Declaracin de excepciones.
La sintaxis de declaracin de excepciones es igual a la de declaracin de variables (aunque una excepcin NO es una variable).
MiExcepcin : exception;

GuaPrcticadeADA95

17/40

Manejo de excepciones.
Cuando ocurre una excepcin se puede: 1. Capturarla 2. Ignorarla Si se captura, entonces cabe: 1. Controlarla, e intentar que el programa contine su ejecucin. 2. Reenviarla a otra parte del programa. La captura de excepciones se realiza en una seccin que se inicia con la palabra exception y se puede situar al final de cada bloque (begin..end). Dentro de esta seccin se utilizan sentencias when NombreExcepcin para capturar las distintas excepciones y situar el cdigo que realiza el tratamiento de las mismas. Si se quiere relanzar la excepcin, basta con poner la sentencia raise. Si se desea, se puede lanzar una nueva excepcin con raise NombreExcepcin.
begin exception when E1 => when E2|E3||En => when others => end;

Excepciones de entrada/salida.
En el paquete Text_IO se definen las siguientes excepciones relacionadas con las operaciones de entrada/salida. Status_Error.- ocurre cuando se intenta leer o escribir en un fichero que no est abierto, o abrir un fichero que est abierto. Mode_Error.- ocurre cuando se intenta leer de un fichero que est abierto para escritura o escribir en un fichero que est abierto para lectura. Name_Error.- ocurre cuando se intenta abrir un fichero y el nombre externo es incorrecto. Use_Error.- ocurre cuando se intenta abrir un fichero para un uso ilegal (p.e. si se intenta crear un fichero con un nombre externo que ya existe). Device_Error.- ocurre cuando se produce un fallo tcnico en un dispositivo de entrada/salida. End_Error.- ocurre cuando se intenta leer de un fichero en el que se ha alcanzado la marca de fin de fichero. Data_Error.- ocurre cuando se intenta leer un valor entero, real o enumerado y los datos de entrada tienen un formato incorrecto.

Ejemplo.

GuaPrcticadeADA95

18/40

with Text_IO; use Text_IO; procedure Excepciones is package Entero_IO is new Integer_IO(Integer); package Real_IO is new Float_IO(Float); use Entero_IO, Real_IO; Divisin_por_cero: exception; declaracin de excepcin procedure Leer(x,y: out integer) is begin loop begin put(Deme dos nmeros enteros: ); get(x); get(y); exit; exception when Data_error => se controla la excepcin y se recupera la ejecucin del programa put_line(Por favor, teclee correctamente); skip_line; end; end loop; end Leer; function Divide(x,y: in integer) return float is r: float; begin r := float(x) / float(y); return r; exception when Constraint_error => se relanza una excepcin ms apropiada raise Divisin_por_cero; end Divide; a, b: integer; begin Leer(a,b); put(El cociente es: ); put(Divide(a,b));new_line; exception when Divisin_por_cero => se deja que el programa acabe de forma controlada new_line; put_line( No se puede dividir por cero); end Excepciones;

GuaPrcticadeADA95

19/40

Ficheros de texto.
Introduccin.
Un fichero de texto es bsicamente una secuencia de caracteres, algunos de los cuales se pueden interpretar como marcas (fin de lnea, fin de pgina, fin de fichero).

Clusula de contexto.
Los elementos necesarios para manejar ficheros de texto se encuentran en el paquete Text_IO, que habr que incluir en la clusula de contexto.
with Text_IO; use Text_IO;

Declaracin
Para poder usar ficheros de texto se deben declarar en el programa variables de tipo File_Type. Estas variables se conocen como ficheros lgicos, o simplemente ficheros, en oposicin a los ficheros externos a los que hacen referencia. El programa manipula los ficheros externos a travs de los ficheros lgicos.
Fichero1 : File_Type; Fichero2 : Text_IO.File_Type;

Apertura
Antes de poder hacer transacciones con una variable fichero debe asociarse con un fichero externo; esto se puede hacer con los procedimientos: Create y Open. El primero sirve para crear un fichero y el segundo para abrir un fichero que ya existe.
procedure Create (File Mode Name Form procedure Open (File Mode Name Form : : : : : : : : in in in in in in in in out File_Type; File_Mode := Out_File; String := ; String := ); out File_Type; File_Mode; String; String := );

File es la variable fichero (fichero lgico). Mode es el modo de apertura (puede tomar los valores: In_File, Out_File, Append_File). o In_File abre el fichero en modo lectura. o Out_File abre el fichero en modo escritura (si el fichero ya existe, se vaca). o Append_File abre el fichero en modo escritura para aadir texto al final de un fichero existente. Name es el nombre del fichero externo (no aparecer en ningn otro sitio del programa). Form no se usa generalmente; es un parmetro que depende del sistema y puede servir para cosas como proteger el fichero con una password.

GuaPrcticadeADA95

20/40

Create(Fichero1,Name => C:\TEMP\unfichero.txt); Open(Fichero2, In_File, C:\TEMP\otrofichero.txt);

En el ejemplo, la primera sentencia crea y abre en modo escritura un fichero externo llamado C:\TEMP\unfichero.txt y lo asocia con la variable Fichero1. La segunda sentencia abre en modo lectura un fichero externo llamado C:\TEMP\otrofichero.txt y lo asocia con la variable Fichero2. Los errores que pudieran producirse al intentar abrir un fichero pueden controlarse mediante excepciones. Existe una funcin para ver si un fichero est abierto:
function Is_Open(File : in File_Type) return Boolean;

Por ejemplo: Is_Open(Fichero1) devuelve True si el fichero Fichero1 est abierto y False, si no. Existen funciones similares para obtener el modo de apertura y nombre de un fichero abierto.
function function Mode Name (File : in File_Type) return File_Mode; (File : in File_Type) return String;

Cierre
Una vez que se ha terminado de trabajar con un fichero se debe cerrar con la operacin Close.
procedure Close (File : in out File_Type); Close(Fichero1); cierra Fichero1

Transferencia de informacin
Para realizar lecturas y escrituras desde/a ficheros se utilizan las ya conocidas operaciones get, put, get_line, put_line, con un primer parmetro que es la variable fichero de la que se va a leer o escribir.
get_line(Fichero1,S,L); put_line(Fichero2,S(1..L));

El texto ledo de Fichero1 en la variable S se copia en Fichero2. Se supone que S es una ristra de tamao fijo y L es una variable de tipo Natural.

Estructura del fichero


Existen operaciones para controlar las marcas del fichero en relacin a:

Lneas: New_Line, Skip_Line y End_Of_Line.


o o o New_Line(Fichero1) Inicia una nueva lnea en Fichero1 Skip_Line(Fichero1) Salta hasta despus de la prxima marca de fin de lnea End_Of_Line(Fichero1)Es una funcin que devuelve True si se ha alcanzado el fin de la lnea, y False en caso contrario New_Page(Fichero1) Inicia una nueva pgina en Fichero1

Pginas: New_Page, Skip_Page y End_Of_Page


o

GuaPrcticadeADA95

21/40

o o

Skip_Page(Fichero1) Salta hasta despus de la prxima marca de fin de pgina End_Of_Page(Fichero1)Es una funcin que devuelve True si se ha alcanzado el final de la pgina y False en caso contrario End_Of_File(Fichero1) es una funcin que devuelve True si se ha

Ficheros: End_Of_File
o

alcanzado el final de fichero1 y False en caso contrario. Existen funciones para configurar el tamao de la lnea y el tamao de la pgina.

Eliminacin de un fichero externo


Se realiza mediante la operacin Delete.
procedure Delete (File : in out File_Type);

Delete borra el fichero externo asociado con la variable fichero que se le pase y cierra sta.

Adems
En el anexo A.10 del Ada 95 reference manual incluido en la ayuda de ObjectAda 7.1 se puede encontrar ms informacin sobre manipulacin de ficheros de texto.

Ejemplo
with Text_Io; use Text_Io; El procedimiento Copiar_Fichero copia un fichero de texto, llamado original.txt en otro llamado copia.txt precondiciones: debe existir un fichero externo llamado original.txt no debe existir un fichero externo llamado copia.txt postcondiciones: Existe un fichero externo llamado copia.txt cuyo contenido es idntico al de original.txt procedure Copiar_Fichero is F_Entrada,F_Salida: File_Type; Lnea : String(1..200); Lon_Lnea : Natural; begin se abren los ficheros Open(F_Entrada,Mode => In_File,Name => original.txt); Create(F_Salida,Name => copia.txt); se copia F_Entrada en F_Salida while not End_Of_File(F_Entrada) loop Get_Line(F_Entrada,Lnea,Lon_Lnea); Put_Line(F_Salida,Lnea(1..Lon_Lnea)); end loop; se cierran los ficheros Close(F_Entrada);

GuaPrcticadeADA95

22/40

Close(F_Salida); end Copiar_Fichero;

Ficheros uniformes.
Introduccin
Un fichero uniforme es una secuencia arbitrariamente larga de elementos del mismo tipo. En Ada se distinguen ficheros secuenciales y ficheros de acceso directo. (Un fichero de texto es bsicamente un fichero secuencial de caracteres).

Clusula de contexto
Los elementos necesarios para manejar ficheros secuenciales se encuentran en el paquete Sequential_IO, los ficheros de acceso directo se manejan con el paquete Direct_IO que habr que incluir en la clusula de contexto.
with Text_IO,Sequential_IO,Direct_IO; use Text_IO;

Declaracin
Para poder usar ficheros uniformes se ha de definir previamente el tipo de sus componentes (a menos que sea de un tipo predefinido)
type TPersona is record Nombre : string(1..20); DNI : string(1..10); Edad : natural; end record;

Una vez definido el tipo, se han de definir instancias de los paquetes de manejo de ficheros, segn el tipo de acceso que se vaya a utilizar.
package FichTPersona_Sec is new Sequential_IO(TPersona); Acceso secuencial package FichTPersona_Dir is new Direct_IO(TPersona); Acceso directo use FichTPersona_Sec,FichTPersona_Dir;

Ahora se pueden declarar variables de tipo fichero directo o secuencial:


Fichero1 : FichTPersona_Sec.File_Type; Fichero2 : FichTPersona_Dir.File_Type;

Apertura
Antes de poder hacer transacciones con una variable fichero debe asociarse con un fichero externo; esto se puede hacer con los procedimientos: Create y Open. El primero sirve para crear un fichero y el segundo para abrir un fichero que ya existe.
procedure Create (File Mode acceso directo Name Form : in out File_Type; : in File_Mode := Out_File; InOut_File en : in String : in String := ; := );

GuaPrcticadeADA95

23/40

procedure Open

(File Mode Name Form

: : : :

in in in in

out File_Type; File_Mode; String; String := );

File es la variable fichero (fichero lgico). Mode es el modo de apertura (puede tomar los valores: In_File, Out_File, Append_File, InOut_File). o In_File abre el fichero en modo lectura. o Out_File abre el fichero en modo escritura (si el fichero ya existe, se vaca). o Append_File abre un fichero secuencial en modo escritura para aadir informacin al final. o InOut_File abre un fichero de acceso directo, permitiendo realizar lecturas y escrituras. Name es el nombre del fichero externo (no aparecer en ningn otro sitio del programa). Form no se usa generalmente; es un parmetro que depende del sistema y puede servir para cosas como proteger el fichero con una password.
Create(Fichero1,Name => C:\TEMP\unfichero.dat); Open(Fichero2,InOut_File,C:\TEMP\otrofichero.dat);

En el ejemplo, la primera sentencia crea y abre en modo escritura un fichero secuencial externo llamado C:\TEMP\unfichero.dat y lo asocia con la variable Fichero1. La segunda sentencia abre en modo lectura/escritura un fichero externo de acceso directo llamado C:\TEMP\otrofichero.dat y lo asocia con la variable Fichero2. Los errores que pudieran producirse al intentar abrir un fichero pueden controlarse mediante excepciones. Existe una funcin para ver si un fichero est abierto:
function Is_Open(File : in File_Type) return Boolean;

Por ejemplo: Is_Open(Fichero1) devuelve True si el fichero Fichero1 est abierto y False, si no. Existen funciones similares para obtener el modo de apertura y nombre de un fichero abierto.
function function Mode Name (File : in File_Type) return File_Mode; (File : in File_Type) return String;

Cierre
Una vez que se ha terminado de trabajar con un fichero se debe cerrar con la operacin Close.
procedure Close (File : in out File_Type); Close(Fichero1); cierra Fichero1

Transferencia de informacin
Para realizar lecturas y escrituras desde/a ficheros se han de declarar previamente variables del tipo de los componentes del fichero.
Persona_1,Persona_2,Persona_3 : TPersona;

GuaPrcticadeADA95

24/40

Las operaciones de entrada/salida se realizan con las operaciones Read y Write.


procedure Read(File : in out File_Type; Item : out Element_Type; From : in Positive_Count); procedure Read(File : in out File_Type; Item : out Element_Type);

Read lee un elemento de un fichero y avanza una posicin:


File es la variable fichero. Item es la variable, del tipo de los componentes del fichero, en la que se lee el elemento. From es la posicin en el fichero desde donde se quiere leer el dato. Slo es aplicable a ficheros de acceso directo. Si no se especifica se lee de la posicin actual en el fichero.

procedure Write(File : in out File_Type; Item : in Element_Type; To : in Positive_Count); procedure Write(File : in out File_Type; Item : in Element_Type);

Write escribe un elemento en un fichero y avanza una posicin:


File es la variable fichero. Item es la variable, del tipo de los componentes del fichero, cuyo contenido se escribe en el fichero To es la posicin en el fichero donde se quiere escribir el dato. Slo es aplicable a ficheros de acceso directo. Si no se especifica se escribe en la posicin actual en el fichero.

Estructura del fichero


Existe una operacin para controlar la marca de fin de fichero:
End_Of_File(Fichero1) es una funcin que devuelve True si se ha alcanzado

el final de Fichero1 y False en caso contrario.

Operaciones con ficheros de acceso directo


El tamao, en nmero de componentes, de un fichero de acceso directo se obtiene mediante la funcin Size, que devuelve un nmero comprendido entre 0 y el mximo tamao posible definido en la implementacin del compilador de Ada que se est usando.
function Size(File : in File_Type) return Count;

Se puede saltar a una posicin especfica de un fichero utilizando el procedimiento Set_Index


procedure Set_Index(File : in out File_Type; To : in Positive_Count);

La posicin actual en el fichero se puede averiguar mediante la funcin Index, que devuelve un valor comprendido entre 1 y el mximo tamao posible definido en la

GuaPrcticadeADA95

25/40

implementacin.
function Index(File : in File_Type) return Positive_Count;

Eliminacin de un fichero externo


Se realiza mediante la operacin Delete.
procedure Delete (File : in out File_Type);

Delete borra el fichero externo asociado con la variable fichero que se le pase y cierra sta.

Adems
En los anexos A.7, A.8 y A.9 del Ada 95 reference manual incluido en la ayuda de ObjectAda 7.1 se puede encontrar ms informacin sobre manipulacin de ficheros.

Punteros.
Introduccin
Los tipos puntero representan direcciones de memoria y son un importante mecanismo para llevar a cabo una gestin dinmica de la memoria, as como para crear estructuras de datos dinmicas complejas.

Declaracin
En Ada los punteros se denominan accesos. Para declarar punteros que puedan referenciar a variables dinmicas se utiliza la palabra reservada access.
type TPersona is record Nombre : string(1..20); Apellido1 : string(1..20); Apellido2 : string(1..20); end record; type TP_Persona is access TPersona; Tipo de los punteros a TPersona dinmicos type TP_Integer is access integer; Tipo de los punteros a integer dinmicos Pint1, Pint2 : TP_Integer; Punteros a integer dinmico PPer1, PPer2 : TP_Persona; Punteros a TPersona dinmicos i : integer; Variable esttica de tipo integer p : TPersona; Variable esttica de tipo TPersona

Los punteros se inicializan automticamente con el valor null. indicando que no referencian a ninguna variable.

Ubicacin dinmica
Para crear una variable dinmica se utiliza la palabra reservada new seguida del tipo de la variable que se quiere crear:
Pint1 := new integer; Se crea una variable dinmica de tipo integer

GuaPrcticadeADA95

26/40

PPer1 := new TPersona; Se crea una variable dinmica de tipo TPersona

Las variables creadas dinmicamente se pueden inicializar en su creacin:


Pint2 := new integer(35); PPer2 := new TPersona(Pepe ,Prez ,Prez );

Adems, una variable puntero puede ser inicializada en su declaracin:


Pint : TP_Integer := new integer(35);

Acceso a las variables referenciadas por los punteros


Para acceder o modificar el contenido de una variable referenciada por un puntero, se utiliza el cualificador all:
i := Pint2.all; Se asigna a i el valor de la variable referenciada por Pint2 PPer1.all := PPer2.all; Se asigna a la variable referenciada por PPer1 el valor de la variable referenciada por PPer2 Pint1 := Pint2; Pint1 y Pint2 referencian a la misma variable i := Pint1; ERROR, i es de tipo integer y Pint es de tipo puntero

Cuando la variable referenciada es un record se puede acceder a cada campo utilizando simplemente el cualificador punto (.):
p.Nombre := PPer1.Nombre; p.Apellido1 := PPer1.all.Apellido1; El .all es inncesario

Si la variable referenciada es un array se puede acceder a sus elementos individuales utilizando parntesis del modo habitual:
type TArray is array (integer range <>) type TP_Array is access TArray; v : TP_Array := new TArray(1,2,3,4,5); i := v(3); of integer;

Liberacin de variables dinmicas


En Ada, una variable dinmica se libera automticamente cuando finaliza la ejecucin de la parte del programa donde est definido el tipo puntero correspondiente. Por tanto, para realizar un control ms eficiente de la memoria es necesario emplear operaciones de liberacin explcita de las variables creadas dinmicamente cuando ya no sean necesarias. Para ello se necesita, primero, incluir Unchecked_Deallocation en la clusula de contexto:
with Text_io, Unchecked_Deallocation;

A continuacin, se debe instanciar el procedimiento genrico Unchecked_Deallocation para el tipo de dato y tipo de puntero que se quiere liberar:
procedure Libera_Persona is new Unchecked_Deallocation(TPersona,TP_Persona);

Ahora, se puede usar Libera_Persona para liberar variables dinmicas de tipo TPersona referenciadas por variables puntero de tipo TP_Persona:
Libera_Persona(PPer1);

GuaPrcticadeADA95

27/40

Punteros que apuntan a variables estticas


Las variables puntero almacenan direcciones. Todas las variables tienen una direccin; sera lgico querer que en una variable puntero a un tipo T se pueda almacenar la direccin no slo de variables de tipo T creadas dinmicamente, sino tambin de variables estticas de tipo T. En Ada los punteros slo pueden almacenar direcciones de variables dinmicas, a menos que se declaren access all:
type PGen_TPersona is access all TPersona; Las variables de tipo PGen_TPersona pueden referenciar variables de tipo TPersona, tanto estticas como dinmicas PGPer : PGen_TPersona;

Para que la direccin de una variable esttica pueda ser asignada a un puntero, sta debe permitirlo en su declaracin, utilizando la palabra aliased:
p1: aliased TPersona;

La direccin de una variable declarada as puede obtenerse mediante el atributo access:


PGPer := p1access; Asigna a PGPer la direccin de p1

Se puede imponer restriccin de lectura a un puntero, de forma que no se pueda modificar el objeto al que apunta, pudiendo entonces utilizarse para referenciar una constante, o para referenciar una variable de forma segura, con la garanta de que no podr modificarse a travs del puntero:
type Punt_Const_Int is access constant integer; Tipo de los punteros a enteros constantes type Punt_Int is access all integer; Tipo de los punteros a variables integer (estticos o dinmicos) PCI1,PCI2 : Punt_Const_Int; Pint3 : Punt_Int; i : aliased integer; PCI1 := iaccess; Pint3 := iaccess; PCI1 y Pint3 son alias de i i := 3; Pint3.all := 4; Modifica i PCI1.all := 5; ERROR, no se puede modificar i a travs de PCI PCI2 := new integer(9); Se puede hacer new siempre que se inicialice

Declaraciones incompletas de tipos


Una aplicacin frecuente de los punteros es la creacin de estructuras de datos dinmicas, por ejemplo listas encadenadas. Este tipo de estructuras estn formadas por un conjunto de nodos conectados mediante campos de enlace que son punteros a nodos del mismo tipo. Para estos nodos sera necesaria una definicin de tipo tal como:
type NodoLista is record Info: integer; Siguiente: PNodoLista; end record;

GuaPrcticadeADA95

28/40

donde PNodoLista es el tipo de los punteros a objetos de tipo NodoLista. Esto significa que debera existir una definicin para PNodoLista:
type PNodoLista is access NodoLista;

Esta definicin debera estar antes que la de NodoLista, para que sea conocida cuando se declara el campo siguiente de ste; pero entonces NodoLista no se conocera cuando se intenta definir PNodoLista, crendose un crculo vicioso. La solucin consiste en empezar con una declaracin incompleta de NodoLista que establezca que tal tipo va a existir, pero sin concretarlo, cosa que debe hacerse ms adelante en la misma parte del programa. Una declaracin incompleta comienza igual que una definicin completa, pero termina con un punto y coma (;) donde sta tiene la palabra is:
type NodoLista; type PNodoLista is access NodoLista; type NodoLista is record Info: integer; Siguiente: PNodoLista; end record;

GuaPrcticadeADA95

29/40

Estructura general de un programa en Ada.


Formalmente un programa en Ada se estructura en unidades distribuidas en uno o varios ficheros. Las unidades pueden ser:

subprogramas.- definen algoritmos y se clasifican en procedimientos y funciones. paquetes (package).- definen mdulos que son colecciones de entidades (tipos, constantes, subprogramas, ). tareas (task) .- definen acciones que pueden ejecutarse en paralelo con otras. unidades protegidas (protected unit).- sirven para coordinar la comparticin de datos entre tareas concurrentes. unidades genricas.- sirven para definir componentes reusables.

Paquetes.
Los paquetes son la clase de unidad ms importante. En general un programa en Ada se compone de un conjunto de paquetes y un procedimiento principal. La clasula de contexto with sirve para declarar que se van a usar los servicios de un paquete. Un paquete se divide generalmente en dos partes: especificacin e implementacin (body). Ambas partes se sitan casi siempre en ficheros diferentes, con las extensiones *.ads y *.adb, respectivamente. La estructura de la especificacin de un package es la siguiente:
package nombre_de_la_unidad is declaraciones private declaraciones privadas end nombre_de_la_unidad;

Las declaraciones que aparecen antes de la palabra private constituyen la parte visible, o interfaz, del paquete. Las que aparecen despus son privadas; no obstante, la parte privada es opcional, y si no aparece la palabra private se entiende que el paquete no tiene parte privada. Las declaraciones pueden ser desde declaraciones de tipos hasta prototipos de procedimientos o funciones. Un prototipo de un procedimiento o funcin es su cabecera, pero cambiando la palabra is por un punto y coma (;), lo que indica que el subprograma se desarrollar ms tarde (en la implementacin del paquete). La declaracin de un paquete requiere una implementacin si hay declaraciones que requieran completarse (por ejemplo, el prototipo de una funcin requiere su desarrollo). La estructura de un package body es:
package body nombre_de_la_unidad is desarrollo del package end nombre_de_la_unidad;

GuaPrcticadeADA95

30/40

Todas las declaraciones hechas en la especificacin del paquete se pueden usar en la implementacin (body), aunque estn en la parte private. Las declaraciones hechas en el package body slo se pueden usar en el mismo.

Tipos private y limited private.


Si se declara un tipo en la especificacin de un paquete, cualquiera que utilice el paquete podr acceder a los elementos internos de la implementacin del mismo. Esto hace que la aplicacin se vuelva dependiente de la forma en que se ha implementado el nuevo tipo. Para evitar esta dependencia y poder cambiar la implementacin si es necesario se declara el tipo como private en la parte pblica del paquete y se pone su definicin en la parte privada. Al declarar un tipo como private su definicin queda oculta, y el usuario del paquete slo podr utilizar con l las operaciones que se hallan declarado en la parte pblica del paquete, adems de la asignacin (:=), la comparacin de igualdad (=) y la de desigualdad (/=).
package Manejo_De_Claves is type Clave is private; Clavenula : constant Clave; procedure Tomar_Clave(C : out Clave); function <(X, Y : in Clave) return Boolean; private Max : constant := 2 ** 16 - 1; type Clave is range 0 .. Max; Clavenula : constant Clave := 0; end Manejo_De_Claves;

Huelga decir que el paquete Manejo_De_Claves necesita un package body para completar su definicin.
package body Manejo_De_Claves is procedure Tomar_Clave(C : out Clave) is begin Cuerpo del procedimiento end Tomar_Clave; function <(X, Y : in Clave) return Boolean is begin Cuerpo del operador end <; end Manejo_De_Claves;

Si adems se quiere deshabilitar las operaciones de asignacin y comparacin de igualdad/desigualdad, habr que declarar el tipo como limited private.

Unidades genricas en Ada.


Ada permite crear unidades genricas, es decir, con parmetros que se pueden concretar para diferentes instancias de la unidad. Para ello basta anteceder la unidad correspondiente con la palabra generic; los parmetros formales de la unidad se sitan en la zona comprendida entre la palabra generic y el comienzo de la unidad propiamente dicha. Vemos un ejemplo para el caso de un procedimiento genrico:
generic type TElemento is private;

GuaPrcticadeADA95

31/40

procedure Algo(Elemento:in TElemento) is Declaraciones begin Acciones end Algo;

Para utilizar el procedimiento Algo primero se debern crear instancias para los tipos apropiados:
procedure Algo_entero is new Algo(TElemento=>integer); procedure Algo_carcter is new Algo(character);

Ahora, ya se pueden invocar los procedimientos Algo_entero y Algo_carcter, segn convenga:


Algo_entero(30); Algo_carcter(a');

Paquetes genricos
Los paquetes genricos en Ada son los que soportan la genericidad de los tipos abstractos de datos (tad) en este lenguaje. El formato general de un paquete genrico es, en la especificacin del paquete:
generic Zona de declaracin de parmetros formales package nombre_del_paquete_genrico is Zona de uso de los parmetros formales end nombre_del_paquete_genrico;

En la implementacin del paquete:


package body nombre_del_paquete_genrico is Zona de uso de los parmetros formales end nombre_del_paquete_genrico;

Los parmetros formales se pueden emplear en la implementacin del paquete (package body) sin ms requerimientos. La forma de usar un paquete genrico es crear una instancia del paquete genrico en la que se especifiquen todos los parmetros formales requeridos. Esta sentencia tiene la forma:
package nombre_instancia is new nombre_del_paquete_genrico(parmetros_actuales,);

Parmetros formales
Los parmetros formales pueden ser: objetos, tipos o subprogramas. Al igual que los parmetros de los subprogramas, los parmetros de un paquete genrico pueden tener un valor por defecto. Los parmetros formales se declaran de distinta forma segn su naturaleza:

Tipos privados: private, limited private, tagged private y tagged limited private. La definicin del tipo privado corresponde, en este caso, al llamador no va a aparecer en la parte private, si estamos desarrollando un paquete, (type Tipo is private;). 32/40

GuaPrcticadeADA95

Tipos escalares: o Discretos. Se utiliza el smbolo <>, (type TDiscreto is <>;). o Enteros con signo. Se utiliza range <>, (type TEntero is range <>;). o Modulares. Se utiliza mod <>, (type TModular is mod <>;). o Reales en coma flotante. Se utiliza digits <>, (type TRealFlotante is digits <>;). o Reales en coma fija. Se utiliza delta <>, (type TRealFijo is delta <>;). o Decimales. Se utiliza delta <> digits <>, (type TDecimal is delta <> digits <>;). Arrays. Hay que incluir como parmetros, el tipo de los elementos del array, el tipo del ndice del array y el tipo array:
generic type TElemento is private; type ndice is (<>); type Vector is array (ndice range <>) of TElemento; package P is end P;

Punteros. Hay que especificar el tipo puntero y el tipo apuntado:


generic type TNodo is private; type TP_Nodo is access TNodo; package P is end P;

Subprogramas. Se utiliza la palabra with precediendo al protocolo del subprograma que se espera:
generic type TElemento is private; with procedure Accin(X : in TElemento); procedure Iterar(Seq : in Secuencia_de_TElemento); procedure Asignar_Elemento(X : in Item); Es posible la siguiente instancia procedure Asignar_Lista is new Iterar(TElemento => Item, Accin => Asignar_Elemento);

Se puede especificar un nombre por defecto para el subprograma pasado por parmetro, utilizando is nombre:
with procedure Accin (X : in TElemento) is Escribir;

Si se quiere que el nombre por defecto sea el mismo que el del parmetro formal, se pondr como nombre <>:
with procedure Accin (X : in TElemento) is <>;

En caso de especificar un nombre por defecto se podr omitir el parmetro al instanciar la unidad.

Paquetes. Se utiliza la palabra with precediendo a la instanciacin del paquete que queremos como parmetro formal.
with package Nombre_formal is new Nombre_genrico Parte_formal_real;

GuaPrcticadeADA95

33/40

Ejemplo:
El siguiente cdigo muestra la declaracin, implementacin y uso de un paquete genrico para manejar listas ordenadas. Fichero de especificacin (*.ads)
Se declara un paquete genrico para manejar listas ordenadas Se pasan como parmetros: El Tamao mximo de la Lista (por defecto 10) El tipo de dato que se va a almacenar en la Lista Una operacin de comparacin Una accin aplicable a un elemento de la Lista generic Tamao : Natural := 10; Tamao por defecto type Telemento is private; Tipo de dato a almacenar. El paquete no necesita conocer de Telemento mas que las operaciones que vienen a continuacin with function <(X,Y: in Telemento) return Boolean is <>; Operacin de comparacin de elementos with procedure Accion(X: in Telemento); Operacin que se aplica a un elemento package Lista_Ordenada is type Tlista is private; La implementacin de la lista queda oculta procedure Insertar(X: in Telemento; L: in out Tlista); Inserta un elemento en la lista procedure Extraer(I: in Natural; L: in out Tlista); Extrae un elemento de la lista procedure Iterar(L: in Tlista); Recorre la lista aplicando una operacin a cada elemento private Estructura de datos de la lista type Contenedor is array (1..Tamao) of Telemento; type Tlista is record Elementos : Contenedor; Num_Elementos : Natural := 0; end record; end Lista_Ordenada;

Fichero de implementacin (*.adb)


Implementacin de las operaciones de la lista ordenada package body Lista_Ordenada is procedure Insertar(X: in Telemento; L: in out Tlista) is I : Natural; begin I := 1; Esquema de bsqueda para la localizacin de la posicin while I <= L.Num_Elementos and then L.Elementos(I) < X loop I := I + 1; end loop; L.Num_Elementos := L.Num_Elementos + 1;Posible Constrain Error if I < L.Num_Elementos then Se desplazan los elementos para insertar el nuevo for J in reverse I+1..L.Num_Elementos loop L.Elementos(J) := L.Elementos(J-1);

GuaPrcticadeADA95

34/40

end loop; end if; L.Elementos(I) := X; end Insertar; procedure Extraer(I: in Natural; L: in out Tlista) is begin Se desplazan los elementos para cubrir el hueco de la extraccin for J in I..L.Num_Elementos-1 loop L.Elementos(J) := L.Elementos(J+1); end loop; L.Num_Elementos := L.Num_Elementos - 1;Posible Constrain Error end Extraer; procedure Iterar(L: in Tlista) is begin Esquema de recorrido sobre la lista for J in 1..L.Num_Elementos loop Accion(L.Elementos(J)); Se aplica la accin pasada como parmetro end loop; end Iterar; end Lista_Ordenada;

Fichero del programa principal (*.ada)


with Text_Io,Lista_Ordenada; use Text_Io; procedure Prueba_De_Contenedor is package Enteros_Io is new Integer_Io(Integer); use Enteros_Io; procedure Escribir_Elemento(X: in Integer) is begin Put(X); New_Line; end; Se crea una instancia del paquete genrico Lista_Ordenada, llamada Lista_Enteros, con un tamao mximo de 20, los elementos que se almacenan son de tipo integer, la operacin de comparacin es el operador < de los integer (al no especificarlo se usa por defecto), como accion se pasa el procedimiento Escribir_Elemento package Lista_Enteros is new Lista_Ordenada(20,Integer,Accion => Escribir_Elemento); use Lista_Enteros ; L: Tlista; begin for J in reverse 1..15 loop Insertar(J,L); end loop; Iterar(L); end Prueba_De_Contenedor;

GuaPrcticadeADA95

35/40

Operadores principales
Clasificacin Operador Descripcin Llamada a funcin Delimitadores () () . Aritmticos ** abs NOT * / rem = & + Relacionales = /= < <= > >= in not in and or xor and then or else := , Asociacin De izquierda a derecha

Lgicos

Elemento de un array Operador punto para los miembros de un estructura Exponenciacin De derecha a izquierda Valor absoluto no lgico Multiplicacin De izquierda a derecha Divisin Resto Menos unario Suma unaria Concatenacin de string De izquierda a derecha Suma Sustraccin Igualdad lgica De izquierda a derecha Desigualdad lgica Menor que Menor o igual que Mayor que Mayor o igual que Miembro de No miembro de Y lgico De izquierda a derecha O lgico O exclusive

Asignacin Separador

Asignacin simple Separador coma

De derecha a izquierda De izquierda a derecha

GuaPrcticadeADA95

36/40

Palabras reservadas.
abort and case digits exception goto loop of pragma record select then with abs array constant do exit if mod or private rem separate type xor accept at declare else for in new others procedure renames subtype use access begin delay end function is not out raise return task when all body delta entry generic limited nul package reange reverse terminate while

Funciones matemticas elementales.


Existe un paquete generico llamado Ada.Numerics.Generic_Elementary_Functions que ofrece las siguientes funciones matemticas:
function Sqrt Float_TypeBase; function Log Float_TypeBase; function Log Float_TypeBase; function Exp Float_TypeBase; function ** Float_TypeBase; function Sin Float_TypeBase; function Sin Float_TypeBase; function Cos Float_TypeBase; function Cos Float_TypeBase; (X (X (X, Base (X : Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase) return return return return return

(Left, Right : Float_TypeBase)

(X (X, Cycle (X (X, Cycle

: Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase)

return return return return

GuaPrcticadeADA95

37/40

function Tan Float_TypeBase; function Tan Float_TypeBase; function Cot Float_TypeBase; function Cot Float_TypeBase; function Arcsin Float_TypeBase; function Arcsin Float_TypeBase; function Arccos Float_TypeBase; function Arccos Float_TypeBase; function Arctan Float_TypeBase; function Arctan Float_TypeBase; function Arccot Float_TypeBase; function Arccot Float_TypeBase; function Sinh Float_TypeBase; function Cosh Float_TypeBase; function Tanh Float_TypeBase; function Coth Float_TypeBase; function Arcsinh Float_TypeBase; function Arccosh Float_TypeBase; function Arctanh Float_TypeBase; function Arccoth Float_TypeBase;

(X (X, Cycle (X (X, Cycle

: Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase)

return return return return

(X (X, Cycle (X (X, Cycle (Y X (Y X Cycle (X Y (X Y Cycle

: Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase)

return return return return

: Float_TypeBase; : Float_TypeBase := 1.0) return : Float_TypeBase; : Float_TypeBase := 1.0; : Float_TypeBase) return : Float_TypeBase; : Float_TypeBase := 1.0) return : Float_TypeBase; : Float_TypeBase := 1.0; : Float_TypeBase) return

(X (X (X (X (X (X (X (X

: Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase) : Float_TypeBase)

return return return return return return return return

(cycle es las unidades que determinan una circunferencia completa. Si no se especifica se suponen radianes)

Forma de usarlas.
1) Clusulas de contexto.

Incluir en una clusula with: Ada.Numerics.Generic_Elementary_Functions Incluir en una clusula use: Ada.Numerics

GuaPrcticadeADA95

38/40

2) Declaraciones.

Instanciar el paquete Generic_Elementary_Functions con el tipo real adecuado, e incluir la instancia en una clasula use.

Ejemplo.
with Text_IO, Ada.Numerics.Generic_Elementary_Functions; use TExt_IO, Ada.Numerics; procedure UsaMat is x, y : float; package MiFloat_IO is new Float_IO(float); package Funciones is new Generic_Elementary_Functions(float); use MiFloat_IO, Funciones; begin put(Dame un nmero real: ); get(x); y := sqrt(x); put(raz cuadrada: ); put(y); end UsaMat;

Conversin de tipos
Ada es un lenguaje muy estricto en la utilizacin de los tipos, y no permite nunca mezclar tipos diferentes de forma implcita. Sin embargo, puede haber situaciones en que sea necesario operar tipos diferentes en una expresin. Por ejemplo:
Media := SumaElementos / NumeroElementos;

Si SumaElementos y NumeroElementos son variables integer y Media es float, tal expresin es incorrecta, dado que el resultado de la divisin es de tipo integer, y pretendemos asignrsela a un float. Previamente, se deben convertir SumaElementos y NumeroElementos a float. Para ello basta hacer lo siguiente:
Media := float(SumaElementos) / float(NumeroElementos);

Ntese que:
Media := float(SumaElementos / NumeroElementos);

no dara el mismo resultado. En general, para convertir de un tipo numrico a otro basta con poner:
Nuevo_Tipo(Expresin_tipo_original)

Cuando una expresin real se convierte a un tipo entero, se redondea el resultado al entero ms cercano: integer(2.85) da como resultado 3. Si no es esto lo que queremos, podemos utilizar las siguiente funciones atributo de los reales en coma flotante:

GuaPrcticadeADA95

39/40

(Sea FT un tipo real en coma flotante, x una variable de tipo FT y el resultado tambin ser de tipo FT) FTrounding(x) redondea x al valor entero ms prximo FTtruncation(x) devuelve el valor de x sin decimales FTfloor(x) devuelve el valor entero ms grande menor que x FTceiling(x) devuelve el valor entero ms pequeo mayor que x

GuaPrcticadeADA95

40/40

S-ar putea să vă placă și