Anterior | Superior | Siguiente

Guía de referencia básica de Ada 95

Ristras de caracteres.

Clasificación.

Ada ofrece tres clases de ristras de caracteres:

  1. Ristras de tamaño fijo (fixed strings).
  2. Ristras de tamaño limitado (bounded strings).
  3. Ristras de tamaño dinámico (unbounded strings).

La librería "Ada.Strings" define elementos de carácter general que se pueden usar con las distintas clases de ristras; entre otros:

Space : constant Character  := ' ';
type Alignment  is (Left, Right, Center);
type Truncation is (Left, Right, Error);
type Membership is (Inside, Outside);
type Direction  is (Forward, Backward);
type Trim_End   is (Left, Right, Both);

Cuando alguno de estos elementos vaya a ser usado directamente en un programa se tiene que incluir la librería "Ada.Strings" en la cláusula de contexto.

Ristras de tamaño fijo. [clasificación de ristras]

Declaración.

El paquete estándar de Ada contiene la definición del tipo String como un array no restringido de caracteres con rango positivo:

type String is array(Positive range <>) of Character;

Ello significa que, sin más, se pueden declarar ristras de caracteres como versiones restringidas del tipo String:

S1, S2: String(1..10);
S3, S4: String(1..20);

Las variables de tipo String son arrays y se les puede aplicar cualquier operación general de array, incluyendo la posibilidad de acceder a los elementos individuales mediante un índice (los elementos individuales son caracteres, no ristras):

C := S1(3); --C debe ser de tipo Character
S2(4) := 'a';

Asignación.

A una variable String se le puede asignar una ristra literal siempre que tenga el tamaño adecuado:

S1 := "ABCDEFGHIJ";
S3 := "01234567890123456789";

Para asignar ristras de tamaños diferentes es necesario incluir en la cláusula de contexto las librerías "Ada.Strings" y "Ada.Strings.Fixed"; la segunda ofrece un procedimiento llamado Move que permite esta operación:

procedure Move (Source  : in  String;
                Target  : out String;
                Drop    : in  Truncation := Error;
                Justify : in  Alignment  := Left;
                Pad     : in  Character  := Space );

El significado de los parámetros de Move es el siguiente: Source es la ristra a asignar, Target es la ristra donde se va a asignar, Drop indica qué hacer si Source tiene mayor longitud que Target (producir un error o cortar la ristra por uno de sus extremos, left, rigth, asignando sólo los caracteres que caben), Justify indica cómo alinear Source dentro de Target si tiene menor longitud y Pad es el carácter con que se rellenará el resto de Target, en ese caso.

Move(S1,S4);                  --S4 = "ABCDEFGHIJ          "
Move(S1,S4,Pad =>'0');        --S4 = "ABCDEFGHIJ0000000000"
Move(S3,S2);                  --¡ERROR!
Move(S3,S2,Drop => Left);     --S2 = "0123456789"
Move(S1,S4,Justify => Right); --S4 = "          ABCDEFGHIJ"

Otras operaciones aplicables a las ristras de tamaño fijo.

Las ristras de tamaño fijo son las únicas a las que les son aplicables operaciones de entrada/salida , también se les pueden aplicar operadores relacionales; la concatenación de ristras se hace usando el operador "&" que en Ada está definido para cualquier array monodimensional.

S1 := "ABCDE" & "12345"; --S1="ABCDE12345"

Para la localización de una subristra dentro de una ristra se puede usar la función Index definida en la librería "Ada.Strings.Fixed" con el siguiente protocolo:

function Index (Source  : in String;
                Pattern : in String;
                Going   : in Direction := Forward;
                Mapping : in Maps.Character_Mapping
                              := Maps.Identity)
return Natural;

Donde Source es la ristra donde se va a buscar, Pattern es el patrón de búsqueda, Going es la dirección de búsqueda (el tipo Direction está definido en Ada.Strings con los valores Forward y Backward) y Mapping especifica cómo se van a corresponder los caracteres.

S4 := "01234567890123456789";
I := Index(S4, "345");           --I = 4
J := Index(S4, "345", Backward); --J = 14

La extracción de una subristra se puede hacer especificando un slice:

S2 := S4(3..12);     --S2 = "2345678901"
S2(1..5) := "ABCDE"; --S2 = "ABCDE78901"

En las ristras de tamaño fijo se puede acceder a los caracteres individuales indicando su posición entre paréntesis:

S2 := "abcdefghij";
C  := S2(5);         --  C = 'e' (C es de tipo Character)

No confundir con:

S2 := "abcdefghij";
S  := S2(5 .. 5);    --  S = "e" (S es de tipo String(1 .. 1))
C  := S2(5 .. 5)(5); --  Se obtiene el caracter a partir del Slice

Ristras de tamaño limitado. [clasificación de ristras]

Declaración.

Las ristras de tamaño limitado pueden tomar cualquier tamaño entre cero (ristra nula) y el número máximo de caracteres que se especifique en cada caso. La declaración de ristras de tamaño limitado requiere tres pasos:

Primero hay que incluir en la cláusula de contexto la librería genérica "Ada.Strings.Bounded".

with Ada.Strings.Bounded;

A continuación, dentro de la unidad de compilación, hay que instanciar la librería para los tamaños que se desee.

package Str10 is new Ada.Strings.Bounded.Generic_Bounded_Length(10);
package Str20 is new Ada.Strings.Bounded.Generic_Bounded_Length(20);
use Str10, Str20;

Sólo entonces se pueden declarar variables de tipo Bounded_String, cualificado con la instancia que corresponda al tamaño deseado.

SL1, SL2: Str10.Bounded_String;
SL3, SL4: Str20.Bounded_String;

Asignación y conversión.

Se pueden asignar entre sí ristras de tamaño limitado del mismo tipo, pero no se puede asignar a una ristra de tamaño limitado una de tamaño fijo (ni al revés) ni una ristra literal (son de tamaño fijo), así como no se pueden emplear en operaciones de entrada/salida. Afortunadamente, la librería "Ada.Strings.Bounded" ofrece operaciones de conversión entre ristras de tamaño fijo y ristras de tamaño limitado.

function To_Bounded_String (Source : in String;
                            Drop   : in Truncation := Error)
return Bounded_String;

function To_String (Source : in Bounded_String) return String;

El parámetro Drop es necesario cuando se convierte una ristra de tamaño fijo a tamaño limitado porque la primera podría tener un tamaño mayor que el límite de la segunda y hay que especificar lo que se hace en ese caso; al revés no es necesario: la función crea una ristra de tamaño fijo exactamente igual a la longitud de Source.

get_line(S1,Lon);
SL1 := To_Bounded_String(S1(1..Lon));
put_line(To_String(SL1));

Recuerde que las funciones de conversión no cambian el tipo de la variable convertida (que es de entrada), sólo crean su valor equivalente en el nuevo tipo.

El valor Null_Bounded_String representa la ristra nula (equivale a To_Bounded_String("")).

SL1 := Str10.Null_Bounded_String;
SL2 := Str20.Null_Bounded_String;

Otras operaciones aplicables a las ristras de tamaño limitado.

Entre ristras de tamaño limitado son aplicables los operadores relacionales; la operación de concatenación se puede realizar tanto usando el operador "&" como la función Append:

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

La función Append devuelve la concatenación de Left y Right; el parámetro Drop indica qué hacer en caso de que el resultado tenga una longitud mayor que el límite establecido.

SL1 := To_Bounded_String("Alfa"); --SL1 = "Alfa"
SL2 := To_Bounded_String("beto"); --SL2 = "beto"
SL1 := Append(SL1,SL2);           --SL1 = "Alfabeto"
SL2 := Append(SL1,SL2);           --¡ERROR!
SL2 := Append(SL1,SL2,Rigth);     --SL2 = "Alfabetobe"

Uno de los parámetros de Append puede no ser de tipo Bounded_String (puede ser una ristra de tamaño fijo, dinámico o un cáracter).

La longitud actual de una ristra de tamaño limitado se obtiene con la función Length.

X := Length(SL1); --X = 8

La localización de una subristra requiere una función Index similar a las de las ristras de tamaño fijo.

function Index (Source  : in Bounded_String;
                Pattern : in String;
                Going   : in Direction := Forward;
                Mapping : in Maps.Character_Mapping
                              := Maps.Identity)
return Natural;

Para la operación de extracción la sintaxis de slices (que ya no se puede utilizar puesto que las ristras de tamaño limitado no son arrays) es sustituida por una función Slice.

function Slice (Source : in Bounded_String;
                Low    : in Positive;
                High   : in Natural)
return String;

La función Slice devuelve la subristra de Source que empieza en la posición Low y acaba en la posición High (ambas incluidas); el resultado es de tamaño fijo.

SL3 := To_Bounded_String(Slice(SL1,3,6)); -- SL3 = "fabe"

En las ristras de tamaño limitado se puede acceder a los caracteres individuales usando una función llamada Element:

SL3 := To_Bounded_String("abcdefghij");
C   := Element(SL3, 5);         --  C = 'e'

Ristras de tamaño dinámico. [clasificación de ristras]

Declaración.

Las ristras de tamaño dinámico pueden tomar cualquier tamaño sin necesidad de una reserva previa. La declaración de ristras de tamaño dinámico requiere, en primer lugar, incluir en la cláusula de contexto la librería "Ada.Strings.Unbounded".

with Ada.Strings.Unbounded;
use Ada.Strings.Unbounded;  --se puede incluir en el use porque no es genérica

Entonces se pueden declarar variables de tipo Unbounded_String.

SD1, SD2, SD3, SD4: Unbounded_String;

Asignación y conversión.

Se pueden asignar entre sí ristras de tamaño dinámico, pero no se puede asignar a una ristra de tamaño dinámico una de tamaño fijo o limitado (ni al revés) ni una ristra literal (son de tamaño fijo), así como no se pueden emplear en operaciones de entrada/salida. Afortunadamente, la librería "Ada.Strings.Unbounded" ofrece operaciones de conversión entre ristras de tamaño fijo y ristras de tamaño dinámico.

function To_Unbounded_String (Source : in String)
return Unbounded_String;

function To_String (Source : in Unbounded_String) return String;

La función To_Unbounded_String crea una ristra de tamaño dinámico a partir de una de tamaño fijo y la operación To_String hace lo contrario.

get_line(S1,Lon);
SD1 := To_UnBounded_String(S1(1..Lon));
put_line(To_String(SD1));

Recuerde que las funciones de conversión no cambian el tipo de la variable convertida (que es de entrada), sólo crean su valor equivalente en el nuevo tipo.

El valor Null_Unbounded_String representa la ristra nula (equivale a To_Unbounded_String("")).

SD1 := Null_Unbounded_String;

Otras operaciones aplicables a las ristras de tamaño dinámico.

Entre ristras de tamaño dinámico son aplicables los operadores relacionales; la operación de concatenación se puede realizar tanto usando el operador "&" como el procedimiento Append.

procedure Append (Source   : in out Unbounded_String;
                  New_Item : in Unbounded_String);

El procedimiento Append crea una ristra concatendo Source con New_item y pone el resultado en Source (que queda modificada).

SD1 := To_Unbounded_String("Alfa"); --SD1 = "Alfa"
SD2 := To_Unbounded_String("beto"); --SD2 = "beto"
Append(SD1,SD2);                    --SD1 = "Alfabeto"

El segundo parámetro de Append puede no ser de tipo Unbounded_String (puede ser una ristra de tamaño fijo, dinámico o un cáracter).

La longitud actual de una ristra de tamaño dinámico se obtiene con la función Length.

X := Length(SD1); --X = 8

La localización de una subristra requiere una función Index similar a las de las ristras de tamaño fijo.

function Index(Source  : in Unbounded_String;
               Pattern : in String;
               Going   : in Direction := Forward;
               Mapping : in Maps.Character_Mapping
                              := Maps.Identity)
return Natural;

Para la operación de extracción la sintaxis de slices (que ya no se puede utilizar puesto que las ristras de tamaño limitado no son arrays) es sustituida por una función Slice.

function Slice (Source : in UnBounded_String;
                Low    : in Positive;
                High   : in Natural)
return String;

La función Slice devuelve la subristra de Source que empieza en la posición Low y acaba en la posición High (ambas incluidas); el resultado es de tamaño fijo.

SD3 := To_Unbounded_String(Slice(SD1,3,6)); -- SD3 = "fabe"

En las ristras de tamaño dinámico se puede acceder a los caracteres individuales usando una función llamada Element:

SD3 := To_Unbounded_String("abcdefghij");
C   := Element(SD3, 5);         --  C = 'e'

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

Anterior | Superior | Siguiente