Strings
Los Strings o cadenas de caracteres en Ada están condicionadas por la codificación de caracteres.
-
String
: 256 caracteres disponibles en la codificación Latin-1 (8 bit). -
Wide_String
: 65536 caracteres disponibles (16 bit). -
Wide_Wide_String
: 1114112 caracteres disponibles (code points de 32 bit). Ideal para almacenar emojis (UTF-8).
type String is
array (Positive range <>) of Character;
type Wide_String is
array (Positive range <>) of Wide_Character;
type Wide_Wide_String is
array (Positive range <>) of
Wide_Wide_Character;
Cada una tiene su procedimiento de salida asociado. Si bien Wide_Wide_String
tiene un amplio abanico
de caracteres posibles, no es lo suficientemente flexible para todo Unicode, ya que el estándar Unicode
no solo manipula caracteres, también la combinación de los mismos. Para trabajar con Unicode se recomienda
el uso de una biblioteca externa como VSS.
with Ada.Text_IO;
with Ada.Wide_Text_IO;
with Ada.Wide_Wide_Text_IO;
procedure Strings is
ñandú : constant String := "Ñandú";
π : constant := 3.14;
hello : constant Wide_String := "Привіт";
fire : constant Wide_Wide_String := "🔥";
begin
Ada.Text_IO.Put_Line(ñandú);
Ada.Text_IO.Put_Line(π'Image);
Ada.Wide_Text_IO.Put_Line (hello);
Ada.Wide_Wide_Text_IO.Put_Line (fire);
end Strings;
Sin embargo el código anterior no compilará, ya que es necesario configurar
el proyecto para que soporte Unicode. Se debe editar el archivo de proyecto gpr
,
en este caso strings.gpr
y añadir la opción -gnatW8
para que autorice el uso
de caracteres Unicode.
package Compiler is
for Default_Switches ("Ada") use Strings_Config.Ada_Compiler_Switches & ("-gnatW8");
end Compiler;
Una vez configurado se puede ejecutar normalmente.
$ alr run
✓ Build finished successfully in 7.82 seconds.
ñandú
3.14000000000000000E+00
Привіт
🔥
Se puede notar el uso de identificadores con caracteres especiales como |
Se recomienda usar solamente ASCII para identificadores, ya que facilita la programación entre personas con distintos idiomas y configuración de teclado. |
Caracteres
Los strings son arreglos compuestos por caracteres. El cual es un símbolo que ésta definido por la codificación,
al igual que el string. Está delimitado por dos comillas simples (''
).
-
Character
: 256 caracteres disponibles en la codificación Latin-1 (8 bit). -
Wide_Character
: 65536 caracteres disponibles (16 bit). -
Wide_Wide_Character
: 1114112 caracteres disponibles (code points de 32 bit).
type Roman_Digit is ('I', 'V', 'X', 'L', 'C', 'D', 'M');
Concatenación
En muchos lenguajes de programación se tiene un mecanismo que permite
crear strings multilínea. En Ada esto no es posible, sin embargo, se puede lograr el efecto de múltiples líneas usando secuencias de escape para representar caracteres de nueva línea dentro de una cadena o definiendo múltiples cadenas concatenadas con el operador &
.
with Ada.Text_IO;
procedure Main is
My_String : constant String := "Primera línea" & ASCII.LF
& "Segunda línea" & ASCII.LF
& "Tercera línea";
begin
Ada.Text_IO.Put_Line(My_String);
end Main;
Unbounded String
Una vez definido un string su tamaño es estático. Si se desea tener un tamaño dinámico
se debe usar el tipo Unbounded String que permite aumentar su tamaño. Un dato del tipo Unbounded_String
representa un String
que va desde 1 caracter y de un largo variable entre 0 y el máximo de los números naturales (Narutal’Last
).
Los Unbounded_String
a diferencia de los strings nativos no son arreglos de caracters, eso quiere decir que no se les puede aplicar el atributo 'Range
ni los parentesis para indexar. En vez de eso son un tipo privado que tiene en su paquete (el Ada.Strings.Unbounded
) todas las operaciones necesarias para reemplazar caracteres (Replace_Element
), convertir a string (To_String
) y desde string (To_Unbounded_String
), concatenar (operador &
), reemplazar subcadenas del Unbounded_String
por otras (Replace_Slice
), buscar subcadenas (Index
), etc.
La ventaja de un Unbounded_String
es que puede crecer y decrecer sin límite (o sin otro límite que la memoria disponible).
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
procedure Ejemplo_Unbounded is
-- Declaración de un Unbounded_String
Mi_Cadena : Unbounded_String;
Otra_Cadena : Unbounded_String;
-- Declaración de una cadena regular
Mi_String : String := "Hola";
begin
-- Conversión de String a Unbounded_String
Mi_Cadena := To_Unbounded_String(Mi_String);
Put_Line("Mi_Cadena (inicial): " & To_String(Mi_Cadena));
-- Concatenación con Unbounded_String
Otra_Cadena := Mi_Cadena & " Mundo";
Put_Line("Otra_Cadena (concatenada): " & To_String(Otra_Cadena));
-- Concatenación con String
Mi_Cadena := Mi_Cadena & " ";
Mi_Cadena := Mi_Cadena & To_Unbounded_String("de nuevo");
Put_Line("Mi_Cadena (concatenada): " & To_String(Mi_Cadena));
-- Longitud de la cadena
Put_Line("Longitud de Mi_Cadena: " & Integer'Image(Length(Mi_Cadena)));
-- Acceso a un caracter (necesita conversión a String)
if Length(Mi_Cadena) > 0 then
Put_Line("Primer caracter de Mi_Cadena (usando To_String): " & To_String(Mi_Cadena)(1));
end if;
-- Reemplazo de un caracter
Replace_Element(Mi_Cadena, 1, 'h');
Put_Line("Mi_Cadena (después de reemplazar): " & To_String(Mi_Cadena));
-- Extracción de una subcadena (Slice)
Put_Line("Sub_Cadena: " & Slice(Mi_Cadena, 3, 6));
end Ejemplo_Unbounded;
¿Por qué tantos tipos de String?
A diferencia de otros lenguajes que tienen un solo tipo de string para todos los casos. Es importante recalcar que Ada es un lenguaje pensado para sistemas críticos donde la gestión de memoria es de suma importancia para evitar errores imprevistos. El tener una definición exacta del tamaño de un string, permite un manejo granular y seguro de los tipos y tamaños de datos.
Las formas restringidas (String
) pueden lanzar excepciones al alcanzar sus límites (Constraint_Error
).
Y las formas dinámicas (Unbounded_String
) pueden alcanzar límites de memoria (heap) que no son deseables en aplicaciones de uso crítico.
Sin embargo tener tantos tipos de datos puede causar problemas de complejidad combinatoria (muchos tipos de datos y su manejo de memoria respectivo). Es por esto que actualmente la comunidad está pensando alternativas de solución.
Por el momento se recomienda usar una biblioteca externa como VSS para cuando
el uso de String
y Unbounded_String
no sea apropiado.
Más Info
Para mayor información se puede revisar el manual avanzado de strings en Ada.