Вы находитесь на странице: 1из 32

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;".

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;

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 Da is (Lun, Mar, Mie, Jue, Vie, Sab, Dom);
type Palos is (Oros, Bastos, Espadas, Copas);
type Gnero is (M, F);
type Color is (Blanco, Rojo, Amarillo, Verde, Azul,
Marrn, Negro);
type 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 := Color'Rojo; -- x debe ser de tipo Color
y := Luz'Rojo; -- 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..Integer'last;
subtype Positive is integer range 1..Integer'last;
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:
T'succ(x) devuelve el valor que sigue a x en la lista de valores del tipo
(el ltimo valor no tiene sucesor)
T'pred(x) devuelve el valor que precede a x en la lista de valores del
tipo(el primer valor no tiene predecesor)
T'pos(x) devuelve la posicin que ocupa x en la lista de valores del
tipo (al primer valor le corresponde la posicin 0)
T'val(x) devuelve el valor correspondiente a la posicin x en la lista de
valores del tipo
T'first devuelve el valor ms pequeo del tipo
T'last devuelve el mayor valor del tipo
T'range devuelve el nmero de valores posibles del tipo
Ejemplos:
x:=Da'succ(Mar); --x toma el valor Mie
x:=Da'pred(Mar); --x toma el valor Lun
y:=Da'Pos(Mar); --y toma el valor 1
x:=Da'Val(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
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
sentencias;
end if;

if Exp_lgica then
sentencias;
else
sentencias;
end if;

Seleccin mltiple.

case selector is
when alternativa => sentencias;
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;
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
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 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.
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 5x3
...
A: Matriz;
Los arrays tienen los siguientes atributos: First, Last, Range, Length. Si A es
un array, entonces:
A'First es el lmite inferior del rango del primer ndice de A.
A'First(N) es el lmite inferior del rango del N-simo ndice de A
A'Last es el lmite superior del rango del primer ndice de A.
A'Last(N) es el lmite superior del rango del N-simo ndice de A
A'Range es equivalente al rango A'First .. A'Last.
A'Range(N) es equivalente al rango A'First(N) .. A'Last(N).
A'Length es el nmero de valores del rango del primer ndice.
A'Length(N) es el nmero de valores del rango del N-simo ndice.
...
--Ejemplo que recorre una matriz escribiendo sus
elementos
for i in A'Range(1) loop

for j in A'First(2)..A'Last(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));
...
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.
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.
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);
unbounded_string a string

--conversin de

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 : in String;
Target : out String;
Drop
: in Truncation :=
Error;
Justify : in Alignment :=
Left;
Pad
: in Character := 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));
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

: in String;

tambin puede ser del tipo Bounded_String o Unbounded_String

Pattern
return Natural;

: in String )

--Source

s1,s2 : string(1..5);
s3 : string(1..10);
...
s1 := "12345";
s2 := "abcde" ;
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;
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 "whenNombreExcepcin" 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.
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("
end Excepciones;

No se puede dividir por cero");

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;
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".

Operadores principales
Clasificacin Operador Descripcin
Delimitadores ()
Llamada a funcin
()
.
Aritmticos

**

Elemento de un array
Operador punto para los miembros de un
estructura
Exponenciacin

abs
NOT
*

Valor absoluto
no lgico
Multiplicacin

/
rem
=
&

Divisin
Resto
Menos unario
Suma unaria
Concatenacin de string

+
Relacionales =

Suma
Sustraccin
Igualdad lgica

Lgicos

/=
<
<=
>
>=
in
not in
and

Desigualdad lgica
Menor que
Menor o igual que
Mayor que
Mayor o igual que
Miembro de
No miembro de
Y lgico

Asignacin

or
O lgico
xor
O exclusive
and then
or else
:=
Asignacin simple

Separador

Separador coma

Asociacin
De izquierda a
derecha

De derecha a
izquierda

De izquierda a
derecha

De izquierda a
derecha

De izquierda a
derecha

De izquierda a
derecha

De derecha a
izquierda
De izquierda a
derecha

Вам также может понравиться