Documente Academic
Documente Profesional
Documente Cultură
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
(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
Si hay que declarar varias variables del mismo tipo, se puede formar una lista, aunque ello no es obligatorio:
x, y, z : integer;
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)
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.
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
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;
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.
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);
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
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
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.
GuaPrcticadeADA95
16/40
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
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.
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.
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
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;
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
: : : :
in in in in
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
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);
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.
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;
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
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;
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
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;
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
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
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.
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.
GuaPrcticadeADA95
31/40
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);
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;
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;
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;
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;
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
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
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;
: 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
(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