# How to use strings in Ada?

**URL:** https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317
**Category:** General
**Tags:** ada
**Created:** [October 12, 2024, 7:37pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317 "2024-10-12T19:37:39Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![stevelitt](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/dec6dc/32.png) [@stevelitt](https://forum.ada-lang.io/u/stevelitt)
#### Post date: [October 12, 2024, 7:37pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/1 "2024-10-12T19:37:39Z")

</div>

I’m learning Ada, and for the most part it’s making sense to me, but I’m having trouble with string handling. I’d like to translate the following 9 line Turbo Pascal program to Ada:

```
program stringdemo;
var st1, st2: string;
begin
st1 := 'Ada';
st2 := 'strings confuse me.';
writeln(st1);
st1 := st1 + ' ' + st2;
writeln(st1);
end.
```

Three questions:

- How do I do this with unbounded strings?
- How do I do this with bounded strings?
- Are there any other ways to do this I should be aware of?

Thanks,

Steve

---

<div class="post-metadata">

### Author: ![simonjwright](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/simonjwright/32/11_2.png) [@simonjwright](https://forum.ada-lang.io/u/simonjwright)
#### Post date: [October 12, 2024, 8:15pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/2 "2024-10-12T20:15:54Z")

</div>

This is with unbounded strings:

```ada
with Ada.Strings.Unbounded;
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;

procedure String_Demo is
   use Ada.Strings.Unbounded;
   St1, St2 : Unbounded_String;
begin
   St1 := To_Unbounded_String ("Ada");
   St2 := To_Unbounded_String ("strings confuse me");
   Put_Line (St1);
   St1 := St1 & " " & St2;
   Put_Line (St1);
end String_Demo;

```

---

<div class="post-metadata">

### Author: ![simonjwright](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/simonjwright/32/11_2.png) [@simonjwright](https://forum.ada-lang.io/u/simonjwright)
#### Post date: [October 12, 2024, 8:25pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/3 "2024-10-12T20:25:57Z")

</div>

… and this is with bounded strings - more work, as you can see.

```ada
with Ada.Strings.Bounded;
with Ada.Text_IO.Bounded_IO;

procedure String_Demo is
   package Bounded_Strings_256 is new Ada.Strings.Bounded.Generic_Bounded_Length
     (Max => 256);
   package Bounded_Strings_256_IO is new Ada.Text_IO.Bounded_IO
     (Bounded => Bounded_Strings_256);
   use Bounded_Strings_256;
   use Bounded_Strings_256_IO;
   St1, St2 : Bounded_String;
begin
   St1 := To_Bounded_String ("Ada");
   St2 := To_Bounded_String ("strings confuse me");
   Put_Line (St1);
   St1 := St1 & " " & St2;
   Put_Line (St1);
end String_Demo;

```

---

<div class="post-metadata">

### Author: ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)
#### Post date: [October 13, 2024, 12:36am UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/4 "2024-10-13T00:36:15Z")

</div>

> [@stevelitt](#):
>
> I’m learning Ada, and for the most part it’s making sense to me, but I’m having trouble with string handling.

Oh, ok.  
This is actually easy, at least once you understand that Strings are just arrays, unconstrained arrays, but arrays nonetheless.

For illustration-purposes, we’re going to use non-string arrays to explain what’s going on.

```ada
Type Vector is Array (Positive range <>) of Natural;

-- Returns a vector from user-input.
Function Prompt return Vector is
  Empty : Constant Vector(2..1):= (others => 1);
  Function Collect( Result : in Vector := Empty ) return Vector is
  Begin
     Ada.Text_IO.Put_Line( "Enter a natural number (Negative to exit): " );
     Declare
        Input : String renames Ada.Text_IO.Get_Line;
        Value : Integer renames Natural'Val( Input );
     Begin
        Return Collect( Result & Value );
     End;
  Exception
     when Constraint_Error => Return Result;
  End Collect;
Begin
  Return Collect;
End Prompt;

Data_Set : Vector:= Prompt;

```

Now, `Data_Set` is unconstrained by its subtype and must be constrained by the initialization, which here is `Prompt`. Since `Prompt` returns an unconstrained array, it can be any length from 0 to its full index.

So, having constrained `Data_Set` with the initial value, while it **is** variable, the size is fixed, meaning you could have `(1,4,7,5)` and change it to `(9,3,7,1)`, but **not** `(7,7)` or `(2,3,3,1,8)`.

The other way to constrain a value would be like `Data_Set_2 : Vector(2..7):= (others => 7);`, which creates a length-5 vector and filling its elements with 7.

Now, we come to the syntactic sugar for Strings – Strings are merely arrays which have an element which is a character-type (meaning an enumeration having at least one element surrounded by single quotes) – the syntactic sugar allows you to say `"Hello"` instead of write `('H','e','l','l','o')`.

> Three questions:
> 
> - How do I do this with unbounded strings?
> - How do I do this with bounded strings?
> - Are there any other ways to do this I should be aware of?

I typically do something like:

```ada
Function "+"(Right : String) return Ada.Strings.Unbounded_Strings.Unbounded_String renames Ada.Strings.Unbounded_Strings.To_Unbounded_String;
Function "+"(Right : Ada.Strings.Unbounded_Strings.Unbounded_String) return String renames Ada.Strings.Unbounded_Strings.To_String;
--...
X : Unbounded_String:= +"Initial stuff."'
X:= X & (+"Other stuff");
--...
Return Result : String:= +X;

```

Which you can pretty much do with bounded as well.

---

<div class="post-metadata">

### Author: ![stevelitt](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/dec6dc/32.png) [@stevelitt](https://forum.ada-lang.io/u/stevelitt)
#### Post date: [October 13, 2024, 2:19am UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/5 "2024-10-13T02:19:27Z")

</div>

Thank you simonjwright. This worked! So did your other solution.

---

<div class="post-metadata">

### Author: ![mgrojo](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/mgrojo/32/15_2.png) [@mgrojo](https://forum.ada-lang.io/u/mgrojo)
#### Post date: [October 13, 2024, 7:09am UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/6 "2024-10-13T07:09:18Z")

</div>

> [@stevelitt](#):
>
> Are there any other ways to do this I should be aware of?

Your Pascal example can also be translated to fixed strings, although is more cumbersome, because you can only assign directly when you respect the size or use a slice. First, you will need to declare a string buffer with the necessary size (this is sometimes the difficult part).

This version is using `Ada.Strings.Fixed.Head` which keeps the direct assignments:

```ada
with Ada.Strings.Fixed;
with Ada.Text_IO; use Ada.Text_IO;

procedure String_Demo is
   use Ada.Strings;
   St1, St2 : String (1 .. 100);
begin
   St1 := Fixed.Head ("Ada", St1'Length);
   St2 := Fixed.Head ("strings confuse me", St2'Length);
   Put_Line (St1);
   St1 := Fixed.Head (Fixed.Trim (St1, Side => Right) & " " & St2, St1'Length);
   Put_Line (St1);
end String_Demo;

```

This version is using `Ada.Strings.Fixed.Move`, which is probably more efficient (less copying).

```ada
with Ada.Strings.Fixed;
with Ada.Text_IO; use Ada.Text_IO;

procedure String_Demo is
   use Ada.Strings;
   St1, St2 : String (1 .. 100);
begin
   Fixed.Move ("Ada", St1);
   Fixed.Move ("strings confuse me", St2);
   Put_Line (St1);
   Fixed.Move (Fixed.Trim (St1, Side => Right) & " " & St2, St1);
   Put_Line (St1);
end String_Demo;

```

This example is with assignment to slices, probably the most efficient version:

```ada
with Ada.Text_IO; use Ada.Text_IO;

procedure String_Demo is
    -- In this case, you have to initialize the buffer with the padding character.
   St1, St2 : String (1 .. 100) := (others => ' ');
   Ada_Str : constant String := "Ada";
   Confusion_Str : constant String := "strings confuse me";
begin
   St1 (1 .. Ada_Str'Last) := Ada_Str;
   St2 (1 .. Confusion_Str'Last) := Confusion_Str;
   Put_Line (St1);
   St1 (1 .. Ada_Str'Last + Confusion_Str'Last + 1) :=
     Ada_Str & " " & Confusion_Str;
   Put_Line (St1);
end String_Demo;

```

But you don’t usually do these variable-length assignments with fixed strings, but you declare them with the size you need and then return them as function results.

So a more realistic equivalent of your demo is simply:

```ada
with Ada.Text_IO; use Ada.Text_IO;

procedure String_Demo is
   Ada_Str : constant String := "Ada";
   Confusion_Str : constant String := "strings confuse me";
   St1 : constant String := Ada_Str & " " & Confusion_Str;
begin
   Put_Line (Ada_Str);
   Put_Line (St1);
end String_Demo;

```

---

<div class="post-metadata">

### Author: ![JC001](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/j/e56c9b/32.png) [@JC001](https://forum.ada-lang.io/u/JC001)
#### Post date: [October 13, 2024, 9:27am UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/7 "2024-10-13T09:27:02Z")

</div>

Others have answered your question, but I’d like to touch on why you’re confused. In many languages, including Turbo Pascal, strings are magic. You cannot define a type that behaves like Turbo Pascal’s String, AFAIK. Ada has its share of magic things, but strings are not one of them. As pointed out, type String is an unconstrained 1-D array type, no different from any other such type. You can even declare your own character and string types. Ada.Strings.[Un]Bounded are no different from any other ADTs.

Your confusion comes from thinking in terms of TP’s strings when you’re using Ada. Once you start thinking in Ada terms when using Ada, things will become much simpler.

Type String is suitable for almost everything you normally need to do with strings, except when you need to store differing-length ones in a definite composite type (such as a record). For that you’d usually use a holder, but the designers of Ada 95, in their finite wisdom, decided to treat strings specially and create special-purpose ADTs for them.

---

<div class="post-metadata">

### Author: ![evanescente-ondine](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/evanescente-ondine/32/451_2.png) [@evanescente-ondine](https://forum.ada-lang.io/u/evanescente-ondine)
#### Post date: [October 13, 2024, 1:44pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/8 "2024-10-13T13:44:40Z")

</div>

Take a good book instead of copying other language’s code. That’s a terrible way to learn.

---

<div class="post-metadata">

### Author: ![stevelitt](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/dec6dc/32.png) [@stevelitt](https://forum.ada-lang.io/u/stevelitt)
#### Post date: [October 13, 2024, 6:37pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/9 "2024-10-13T18:37:50Z")

</div>

Thanks evanescente-ondine. What book(s) do you recommend? Because I have bad eyesight and because I make transcription errors copying code from paper to editor, I’d prefer a PDF format for my book. If it’s a print book, I need at least 12 point text. Thanks!

---

<div class="post-metadata">

### Author: ![stevelitt](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/dec6dc/32.png) [@stevelitt](https://forum.ada-lang.io/u/stevelitt)
#### Post date: [October 13, 2024, 6:41pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/10 "2024-10-13T18:41:30Z")

</div>

Thanks OneWingedShark. Your example is a little too advanced for my current understanding (I’ve been studying Ada for about 4 days), but I’m going to come back to it again and again to learn the many techniques you use in your example.

---

<div class="post-metadata">

### Author: ![stevelitt](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/dec6dc/32.png) [@stevelitt](https://forum.ada-lang.io/u/stevelitt)
#### Post date: [October 13, 2024, 6:46pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/11 "2024-10-13T18:46:51Z")

</div>

Thanks JC001. I didn’t know about Abstract Data Types before your post, now I’ll learn more about them. From you and others, I now know clear as day that a string is simply an array of characters, and I can use ADTs to manipulate these arrays of characters.

---

<div class="post-metadata">

### Author: ![evanescente-ondine](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/evanescente-ondine/32/451_2.png) [@evanescente-ondine](https://forum.ada-lang.io/u/evanescente-ondine)
#### Post date: [October 13, 2024, 6:58pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/12 "2024-10-13T18:58:44Z")

</div>

Forget ADTs for now… you’ll read about them in due time. Take Software “Construction and Data Structures with Ada 95”, you can find it online well enough.  
The code examples are [here](https://www2.seas.gwu.edu/~mfeldman/cs2-book/cs2code.zip).  
I hate physical books when it comes to programming too. You won’t even have to copy from the pdf, for the most part.  
It’s accessible and to your level.

---

<div class="post-metadata">

### Author: ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)
#### Post date: [October 13, 2024, 8:31pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/13 "2024-10-13T20:31:24Z")

</div>

> [@JC001](#):
>
> You cannot define a type that behaves like Turbo Pascal’s String, AFAIK.

That’s not _entirely_ true.  
(Adding in your own `"+"` or `"&"` operators to the following…)

```ada
Package Pascal_String with Pure is
   Subtype Byte is Interfaces.Unsigned_8;
   Type String is private;
   -- All the manipulation functions + create.
   Function "+"( Input : Standard.String ) return String
      with Pre => Input'Length in Byte'Range;
   Function "+"(Input : String) return Standard.String;
Private

   Type String is record
      Length : Byte:= 0;
      Text : Standard.String(1..255):= (others => ASCII.NUL);
   end record
   with Size => 256 * Byte'Size;
   -- Convert to/from Internal.String via unchecked conversion.

   Function "+"( Input : Standard.String ) return String is
   ( Length => Byte(Input'Length),
     Text => Input & (Input'Length+1..256 => ASCII.NUL)
    );
   Function "+"(Input : String) return Standard.String is
   ( Input.Text(1..Input.Length) );
End_Pascal_String;

```

---

<div class="post-metadata">

### Author: ![JC001](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/j/e56c9b/32.png) [@JC001](https://forum.ada-lang.io/u/JC001)
#### Post date: [October 14, 2024, 6:55pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/14 "2024-10-14T18:55:15Z")

</div>

> [@OneWingedShark](#):
>
> > [@JC001](#):
> >
> > You cannot define a type that behaves like Turbo Pascal’s String, AFAIK.
> 
> That’s not _entirely_ true.

By a magic type in a language, I mean a type that a user cannot declare in that language. Character is a magic type in Ada. String is a magic type in Turbo Pascal.

---

<div class="post-metadata">

### Author: ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)
#### Post date: [October 14, 2024, 10:21pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/15 "2024-10-14T22:21:40Z")

</div>

> [@JC001](#):
>
> By a magic type in a language, I mean a type that a user cannot declare in that language. Character is a magic type in Ada.

Is it?  
I mean, I’ve used character-types myself.  
The Base\_64 encoder [here](https://github.com/OneWingedShark/Base_64/blob/1ded3b0655bcf13d0e1a702a0179d8875baf2389/src/base_64.ads#L93), for example.

---

<div class="post-metadata">

### Author: ![dmitry-kazakov](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/dmitry-kazakov/32/522_2.png) [@dmitry-kazakov](https://forum.ada-lang.io/u/dmitry-kazakov)
#### Post date: [October 15, 2024, 10:02am UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/17 "2024-10-15T10:02:25Z")

</div>

Avoid unbounded strings they are heap-allocated. Bounded strings are basically useless.  
Most tasks in Ada can be accomplished with fixed strings, which have clean syntax, slices, returned on the stack. String slices are essential for string processing because they allow you to avoid copying in most cases.

```ada
with Ada.Text_IO; use Ada.Text_IO;
procedure Test is
   St1 : constant String := "Ada";
   St2 : constant String := "strings confuse me.";
begin
   Put_Line (St1);
   Put_Line (St1 & ' ' & St2);
end;

```

---

<div class="post-metadata">

### Author: ![stevelitt](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/dec6dc/32.png) [@stevelitt](https://forum.ada-lang.io/u/stevelitt)
#### Post date: [October 15, 2024, 4:01pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/18 "2024-10-15T16:01:51Z")

</div>

[dmitry-kazakov], what’s wrong with allocating off the heap? Is Ada like C where I need to remember to free it when it’s no longer needed or is about to go out of scope?

---

<div class="post-metadata">

### Author: ![JC001](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/j/e56c9b/32.png) [@JC001](https://forum.ada-lang.io/u/JC001)
#### Post date: [October 15, 2024, 4:27pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/19 "2024-10-15T16:27:22Z")

</div>

> [@OneWingedShark](#):
>
> > [@JC001](#):
> >
> > Character is a magic type in Ada.
> 
> Is it?  
> I mean, I’ve used character-types myself.

Try to create a type identical to Standard.Character.

---

<div class="post-metadata">

### Author: ![dmitry-kazakov](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/dmitry-kazakov/32/522_2.png) [@dmitry-kazakov](https://forum.ada-lang.io/u/dmitry-kazakov)
#### Post date: [October 15, 2024, 4:58pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/20 "2024-10-15T16:58:36Z")

</div>

Yes, in Ada like in C if you allocate memory you must explicitly free it later. Unbounded\_String do it in the background, so you need not to care.  
Use Ada.Finalization if you want to design a type like Unbounded\_String.

Heap is bad because it requires interlocking to allocate and deallocate.

Of course, in Ada you can have a specially designed memory pool to improve performance like mark-and-release pool. But Unbounded\_String uses a normal pool because there is no way to predict allocation and deallocation in general case.

---

<div class="post-metadata">

### Author: ![dmitry-kazakov](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/dmitry-kazakov/32/522_2.png) [@dmitry-kazakov](https://forum.ada-lang.io/u/dmitry-kazakov)
#### Post date: [October 15, 2024, 5:12pm UTC](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317/21 "2024-10-15T17:12:13Z")

</div>

```ada
   type Roman_Latin is
        ( 'a','b','c','d','e','f','g','h','i','j','k','l',
           'm','n','o','p','q','r','s','t','v','x','y','z', ' '
        );
   for Roman_Latin'Size use 5; -- Note, 5 bits.
   type Roman_String is array (Positive range <>) of Roman_Latin;

   A : constant Roman_String := "veni vidi vici";

```

[Next page](https://forum.ada-lang.io/t/how-to-use-strings-in-ada/1317.md?page=2)
