❌ About FreshRSS

Normal view

There are new articles available, click to refresh the page.
Before yesterdayNews from the Ada programming language world

Coding Ada: strings (iv) – unbounded to string

By: spqr
16 February 2021 at 20:52

As mentioned before, strings in Ada can be tricky. Normal strings are fixed in length, and Ada is very stringent about this. Consider a piece of code like this:

with ada.Text_IO; use Ada.Text_IO;
with ada.strings.unbounded; use ada.strings.unbounded;

procedure ustr2strfail is
   function tub(Source : String) return unbounded_string renames ada.strings.unbounded.to_unbounded_string;
   type lexicon is array(1..10) of unbounded_string;
   words : lexicon := (tub("gum"),tub("sin"),tub("cry"),
           tub("lug"),tub("star"),tub("fault"),tub("sleeper"),
           tub("a"),tub("vader"),tub("nordic"));
   aword : string(1..10);
begin
   aword := to_string(words(7));
   put(aword);
end ustr2strfail;

This will compile fine, however when it runs, the following error will propogate:

raised CONSTRAINT_ERROR : ustr2strfail.adb:12 length check failed

This means that although the unbounded string is converted to a string using the function to_string(), it only works if the length of the unbounded string equals the length of the string aword. So in the code above, aword has a length of 10, and when an attempt is made to assign it the unbounded string, β€œsleeper”, it fails. It would work if sleeper was padded out with 3 spaces after it. How to fix this? Do exactly that, pad the words. Here is a subroutine that does this:

with ada.Text_IO; use Ada.Text_IO;
with ada.strings.unbounded; use ada.strings.unbounded;
with ada.strings.unbounded.Text_IO; use ada.strings.unbounded.Text_IO;
with ada.strings.fixed; use ada.strings.fixed;

procedure ustr2str is
   subtype string10 is string(1..10);
   R : string10;
   function tub(Source : String) return unbounded_string renames ada.strings.unbounded.to_unbounded_string;
   type lexicon is array(1..10) of unbounded_string;
   words : lexicon := (tub("gum"),tub("sin"),tub("cry"),
           tub("lug"),tub("star"),tub("fault"),tub("sleeper"),
           tub("a"),tub("vader"),tub("nordic"));

   function padString(V: unbounded_string) return string10 is
      temp : constant string := to_string(V);
      res : string10;
   begin
      ada.strings.fixed.move(temp, res, drop=>ada.strings.right);
      return res;
   end padString;

begin
   R := padString(words(7));
   put(R);
end ustr2str;

It uses the procedure move(), from the ada.strings.fixed package. It has the following basic form:

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

The procedure move() copies characters from Source to Target. If Source has the same length as Target, then the effect is to assign Source to Target. If Source is shorter than Target then, Justify is used to place the Source into the Target (default = Left). Pad specifies the padding, default is Space. Drop is used if Source is longer than Target.

spqr

Coding Ada: strings (iii) – arrays of strings

By: spqr
13 January 2021 at 20:44

The problem with strings in Ada is that they just don’t play nicely. As we have seen in previous posts, strings in Ada are either fixed, or unbounded. Now creating an array of strings in other languages isn’t that hard, nor is it in Ada – some things are just beyond its scope. Now by an array of strings, I mean a structure that could hold something like a dictionary of words. So how do we go about this?

The first example below creates a type, lexicon, with is a 5 element array of strings, 3 characters in length (so 5 three letter words). The variable words is then an instantiation of lexicon, which is assigned five three letter words. It’s not really possible to use the term string without the constraints (1..3). This is because of the fact that strings in Ada are fixed length – and it means all the strings assigned to words will have to be of length 3.

type lexicon is array(1..5) of string(1..3);
words : lexicon := ("gum","sin","cry","lug","fly");

It is also not possible to make the constraint larger, e.g. (1..10), and use words or variable length, e.g. β€œgum”, β€œhousefly”, β€œstar”. This will cause a constraint error (the word star would have to be specified as β€œstar β€œ, with 6 spaces filling out the word). The alternative is to unbounded strings, but they come with their own baggage. Consider the following code, changing the string to an unbounded_string.

type lexicon is array(1..5) of unbounded_string;
words : lexicon := ("gum","sin","cry","lug","star");

Compile this, and it will produce a series of errors of the form:

file.adb:10:24: expected private type "Ada.Strings.Unbounded.Unbounded_String"
file.adb:10:24: found a string type

This means that when it tried to assign the words, it considered β€œgum” to be a string, NOT an unbounded_string. The declaration of lexicon works fine if reading directly from a file, but not predefined strings. The fix? Not pretty, because the strings have to be converted to unbound strings using the function to_unbounded_string().

words : lexicon :=(to_unbounded_string("gum"),to_unbounded_string("sin"),to_unbounded_string("cry"),to_unbounded_string("lug"),to_unbounded_string("star"));

Messy right? There is one way of cleaning up this code and that is providing an alias for the function name to_unbounded_string(). Here is how that is done, renaming the function to tub().

function tub(Source : String) return unbounded_string renames ada.strings.unbounded.to_unbounded_string;

Then the code below it becomes:

type lexicon is array(1..5) of unbounded_string;
words : lexicon := (tub("gum"),tub("sin"),tub("cry"),tub("lug"),tub("star"));

Not perfect, but then that is Ada and strings for you.

spqr

Coding Ada: strings (iv) – unbounded to string

By: spqr
16 February 2021 at 20:52

As mentioned before, strings in Ada can be tricky. Normal strings are fixed in length, and Ada is very stringent about this. Consider a piece of code like this:

with ada.Text_IO; use Ada.Text_IO;
with ada.strings.unbounded; use ada.strings.unbounded;

procedure ustr2strfail is
   function tub(Source : String) return unbounded_string renames ada.strings.unbounded.to_unbounded_string;
   type lexicon is array(1..10) of unbounded_string;
   words : lexicon := (tub("gum"),tub("sin"),tub("cry"),
           tub("lug"),tub("star"),tub("fault"),tub("sleeper"),
           tub("a"),tub("vader"),tub("nordic"));
   aword : string(1..10);
begin
   aword := to_string(words(7));
   put(aword);
end ustr2strfail;

This will compile fine, however when it runs, the following error will propogate:

raised CONSTRAINT_ERROR : ustr2strfail.adb:12 length check failed

This means that although the unbounded string is converted to a string using the function to_string(), it only works if the length of the unbounded string equals the length of the string aword. So in the code above, aword has a length of 10, and when an attempt is made to assign it the unbounded string, β€œsleeper”, it fails. It would work if sleeper was padded out with 3 spaces after it. How to fix this? Do exactly that, pad the words. Here is a subroutine that does this:

with ada.Text_IO; use Ada.Text_IO;
with ada.strings.unbounded; use ada.strings.unbounded;
with ada.strings.unbounded.Text_IO; use ada.strings.unbounded.Text_IO;
with ada.strings.fixed; use ada.strings.fixed;

procedure ustr2str is
   subtype string10 is string(1..10);
   R : string10;
   function tub(Source : String) return unbounded_string renames ada.strings.unbounded.to_unbounded_string;
   type lexicon is array(1..10) of unbounded_string;
   words : lexicon := (tub("gum"),tub("sin"),tub("cry"),
           tub("lug"),tub("star"),tub("fault"),tub("sleeper"),
           tub("a"),tub("vader"),tub("nordic"));

   function padString(V: unbounded_string) return string10 is
      temp : constant string := to_string(V);
      res : string10;
   begin
      ada.strings.fixed.move(temp, res, drop=>ada.strings.right);
      return res;
   end padString;

begin
   R := padString(words(7));
   put(R);
end ustr2str;

It uses the procedure move(), from the ada.strings.fixed package. It has the following basic form:

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

The procedure move() copies characters from Source to Target. If Source has the same length as Target, then the effect is to assign Source to Target. If Source is shorter than Target then, Justify is used to place the Source into the Target (default = Left). Pad specifies the padding, default is Space. Drop is used if Source is longer than Target.

spqr

Coding Ada: strings (iii) – arrays of strings

By: spqr
13 January 2021 at 20:44

The problem with strings in Ada is that they just don’t play nicely. As we have seen in previous posts, strings in Ada are either fixed, or unbounded. Now creating an array of strings in other languages isn’t that hard, nor is it in Ada – some things are just beyond its scope. Now by an array of strings, I mean a structure that could hold something like a dictionary of words. So how do we go about this?

The first example below creates a type, lexicon, with is a 5 element array of strings, 3 characters in length (so 5 three letter words). The variable words is then an instantiation of lexicon, which is assigned five three letter words. It’s not really possible to use the term string without the constraints (1..3). This is because of the fact that strings in Ada are fixed length – and it means all the strings assigned to words will have to be of length 3.

type lexicon is array(1..5) of string(1..3);
words : lexicon := ("gum","sin","cry","lug","fly");

It is also not possible to make the constraint larger, e.g. (1..10), and use words or variable length, e.g. β€œgum”, β€œhousefly”, β€œstar”. This will cause a constraint error (the word star would have to be specified as β€œstar β€œ, with 6 spaces filling out the word). The alternative is to unbounded strings, but they come with their own baggage. Consider the following code, changing the string to an unbounded_string.

type lexicon is array(1..5) of unbounded_string;
words : lexicon := ("gum","sin","cry","lug","star");

Compile this, and it will produce a series of errors of the form:

file.adb:10:24: expected private type "Ada.Strings.Unbounded.Unbounded_String"
file.adb:10:24: found a string type

This means that when it tried to assign the words, it considered β€œgum” to be a string, NOT an unbounded_string. The declaration of lexicon works fine if reading directly from a file, but not predefined strings. The fix? Not pretty, because the strings have to be converted to unbound strings using the function to_unbounded_string().

words : lexicon :=(to_unbounded_string("gum"),to_unbounded_string("sin"),to_unbounded_string("cry"),to_unbounded_string("lug"),to_unbounded_string("star"));

Messy right? There is one way of cleaning up this code and that is providing an alias for the function name to_unbounded_string(). Here is how that is done, renaming the function to tub().

function tub(Source : String) return unbounded_string renames ada.strings.unbounded.to_unbounded_string;

Then the code below it becomes:

type lexicon is array(1..5) of unbounded_string;
words : lexicon := (tub("gum"),tub("sin"),tub("cry"),tub("lug"),tub("star"));

Not perfect, but then that is Ada and strings for you.

spqr

❌
❌