From: Peter Mueller on
Hello,

I have some strings and depending of an enum I want to return a
string. My code looks the following:

function Event_To_String(Event : in Events_Type) return String is
Ev1_Name : aliased constant String :="ev3434";
Ev2_Name : aliased constant String :="evEnd";
eventStrings : constant array (1..2) of access constant String :=
(Ev1_Name'Access,Ev2_Name'Access);

begin

return EventStrings(Events_Type'Pos(Event));
end Event_To_String;

The compiler says:

expected type "Standard.String"
found type access to "Standard.String" defined ...

I think that my code returns the pointer to the string and not the
string. But I don't know how to fix it.
Is there a better solution to create an array of strings and accessing
them with an index?

Thanks,
Peter
From: Jeffrey R. Carter on
Peter Mueller wrote:
>
> I have some strings and depending of an enum I want to return a
> string. My code looks the following:
>
> function Event_To_String(Event : in Events_Type) return String is
> Ev1_Name : aliased constant String :="ev3434";
> Ev2_Name : aliased constant String :="evEnd";
> eventStrings : constant array (1..2) of access constant String :=
> (Ev1_Name'Access,Ev2_Name'Access);
>
> begin
>
> return EventStrings(Events_Type'Pos(Event));
> end Event_To_String;
>
> The compiler says:
>
> expected type "Standard.String"
> found type access to "Standard.String" defined ...
>
> I think that my code returns the pointer to the string and not the
> string. But I don't know how to fix it.

You're correct. But first, a probable error:

'Pos for an enumeration type returns values starting at zero:

type E is (One, Two);

E'Pos (One) = 0
E'Pos (Two) = 1

Your array index range is "Integer range 1 .. 2". So, assuming Events_Type is
the first-named subtype (the name used in the type declaration), if you ever
called this with Events_Type'First, you would get Constraint_Error.

However, there is no reason to use Integer indices. An array may be indexed by
any discrete subtype:

type Event_Name is array (Events_Type) of ...;

Then you can say

Eventstrings (Event)

As for your question, you dereference an access value by appending .all to it:

Eventstrings (Event).all

> Is there a better solution to create an array of strings and accessing
> them with an index?

For a discrete subtype like this, probably not. What you have is a mapping
Events_Type => String. If you were mapping something non-discrete to String,
than a map or similar associative data structure would be better.

It's also possible to store String values in [Un]Bounded_String objects; that
would be better if the strings are not constant. It would also eliminate
(explicit) use of access types and values.

--
Jeff Carter
"C's solution to this [variable-sized array parameters] has real
problems, and people who are complaining about safety definitely
have a point."
Dennis Ritchie
25
From: Hibou57 (Yannick Duchêne) on
On 29 oct, 21:48, Peter Mueller <peter.o.muel...(a)gmx.de> wrote:
> Hello,
>
> I have some strings and depending of an enum I want to return a
> string. My code looks the following:
>
> function Event_To_String(Event : in Events_Type) return String is
>    Ev1_Name : aliased constant String :="ev3434";
>    Ev2_Name : aliased constant String :="evEnd";
>    eventStrings : constant array (1..2) of access constant String :=
> (Ev1_Name'Access,Ev2_Name'Access);
>
>    begin
>
>    return EventStrings(Events_Type'Pos(Event));
> end Event_To_String;
>
> The compiler says:
>
> expected type "Standard.String"
> found type access to "Standard.String" defined ...
>
> I think that my code returns the pointer to the string and not the
> string. But I don't know how to fix it.
> Is there a better solution to create an array of strings and accessing
> them with an index?
>
> Thanks,
> Peter

The compiler error you've reported is not the single point to notice
about in test case.

The first one, the one you are talking about :
You have a function whose return type is String.
You have an array of anonymous access to String.
The return statement returns an item of that array.

So fat, you have then a function which is expected to return a String,
but you return an access to String.
The expected returned type of the function and the type you return are
not the same.
The compiler complains about that, it tries to tell you that the
expression you attempt to return, is not of type String.

To get a String from an access to String, you have to use the “ .all ”
suffixe.
Do know what is “ .all ” ?
If you need explanations about it, just tell, you will be asked about
it.

Just change
“ return EventStrings(Events_Type'Pos(Event)); ”
into
“ return EventStrings(Events_Type'Pos(Event)).all; ” and every thing
will be OK.

That's to correct what does not work.

To got further now : you wants an association from Events_Type to
String, aren't you ?
So why to you use an array whose index range is “ 1 .. 2 ” ?
I suggest you to use Events_Type instead.

So, as a second step, you may turn
“ eventStrings : constant array (1..2) of access constant String ”
into
“ eventStrings : constant array (Events_Type) of access constant
String ”

Do you understand what it is ?

Then, as you use Events_Type as the array index range, you do not need
any more (and must not also), the “ Events_Type'Pos(Event) ” and you
can use just Event instead

So then replace
“ return EventStrings(Events_Type'Pos(Event)).all ”
with
“ return EventStrings(Event).all ”

Providing that your Events_Type is a enumeration of two elements
(otherwise, just update the array initialization to match the required
number of items).

Next now : you have an array of constant, which will be initialized
each times you enter the function. There are no kind of “ static ” in
Ada like there are in C. To achieve static global allocation, you have
to declare your array outside of the function, at the package level.

So now, try to change

function Event_To_String(Event : in Events_Type) return String is
Ev1_Name : aliased constant String :="ev3434";
Ev2_Name : aliased constant String :="evEnd";
eventStrings : constant array (Events_Type) of access constant
String :=
(Ev1_Name'Access,
Ev2_Name'Access);

begin
return EventStrings(Event).all;
end Event_To_String;begin

into

Ev1_Name : aliased constant String :="ev3434";
Ev2_Name : aliased constant String :="evEnd";

eventStrings : constant array (Events_Type) of access constant
String :=
(Ev1_Name'Access,
Ev2_Name'Access);

function Event_To_String(Event : in Events_Type) return String is
begin
return EventStrings(Event).all;
end Event_To_String;begin

What tutorial do you have in hands to learn Ada ?

Read you soon

Y.
From: Hibou57 (Yannick Duchêne) on
On 29 oct, 22:36, "Jeffrey R. Carter" <spam.jrcarter....(a)spam.acm.org>
wrote:
> You're correct. But first, a probable error:
He is not at all : his implementation is returning an access to String
while the function is expected to return a String.
From: Gautier write-only on
Hello!

My usual way of doing that is:

function Event_To_String(Event : in Events_Type) return String is
begin
case Event is
when Ev1 => return "ev3434";
when Ev2 => return "evEnd";
end case;
end;

You live longer without pointer ;-).

For more complicated cases, I use unbounded strings, like there:

type External_packer_info is record
name, title, URL, options: Unbounded_String;
expanded_options : Unbounded_String;
-- options with dynamically expanded tokens
made_by_version : Unsigned_16;
pkzm : Zip.PKZip_method;
end record;

ext: array(External) of External_packer_info:=
(
(U("zip.exe"), U("Zip"), U("http://info-zip.org/"), U("-9"), U
(""), 20, Zip.deflate),
-- Zip 2.32 or later
...
);

HTH
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!