comp.lang.ada
 help / color / mirror / Atom feed
* Variable-length arrays (from a C programmer)
@ 1998-04-23  0:00 Paul T. McAlister
  1998-04-24  0:00 ` Stephen Leake
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Paul T. McAlister @ 1998-04-23  0:00 UTC (permalink / raw)



I have an application where I will be displaying a number of different
screens full of text messages.
I want these messages and screens to be data table driven.

In "C" (see example), I can define an array of messages for each page,
then define an array of pages for the whole thing.
I don't have to worry about string length or number of items defined in
the arrays, the compiler handles all of that for me.

I have not been able to figure out how to do the equivalent thing in
Ada.
I don't know how to define strings without setting the length to the
maximum length string I will have, which wastes a lot of space.
I think I know how to define the variable length arrays for the messages
for each screen, but I don't know how to define an array type of these
arrays of string for each page (since they are different types because
they are different lengths).
I am using Ada83.

I know this is a lengthy question, but any help would be greatly
appreciated.

- - - - - - - - - - - -

#include <stdio.h>

// structure for each message
typedef struct
{
  char *text;   // pointer to message text
  int   xPos;   // x position on screen
  int   yPos;   // y position on screen
}
MSG_STRUCT;

// structure for each page
typedef struct
{
  MSG_STRUCT  *msg;      // pointer to array of message structures
  int         num_msgs;   // number of message on this page
}
PAGE_STRUCT;

// page 1 messages
MSG_STRUCT page1[] =
{ {"Greetings Earthling", 0, 0}
, {"Take me to your leader", 1, 0}
};

// page 2 messages
MSG_STRUCT page2[] =
{ {"Screen 2", 0, 0}
, {"This text is some lines farther down", 5, 0}
, {"and this is even FARTHER down", 10, 0}
};

// page 3 messages
MSG_STRUCT page3[] =
{ {"This is the third screen", 0, 0}
, {"and by now you should be getting", 1, 10}
, {"the point of what it is", 2, 12}
, {"I am trying to do!!", 3, 14}
};

// messages for all pages
PAGE_STRUCT pages[] =
{ {page1, (sizeof(page1) / sizeof(page1[0]))}
, {page2, (sizeof(page2) / sizeof(page2[0]))}
, {page3, (sizeof(page3) / sizeof(page3[0]))}
};

void main()
{
  int iPage;
  int iMsg;
  int nPage;

  // find number of pages
  nPage = sizeof(pages) / sizeof(pages[0]);

  // for each page
  for (iPage = 0; iPage < nPage; ++iPage)
  {
    printf("\n");   // put blank line between pages

    // for each message
    for (iMsg = 0; iMsg < pages[iPage].num_msgs; ++iMsg)
    {
      printf(pages[iPage].msg[iMsg].text);  // print message
      printf("\n");                         // terminate line
    }
  }
}

  --PTM                                   8-)
--------------------------------------
Paul McAlister
Paul.McAlister@AlliedSignal.com
913.768.2238
--------------------------------------






^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Variable-length arrays (from a C programmer)
  1998-04-23  0:00 Variable-length arrays (from a C programmer) Paul T. McAlister
  1998-04-24  0:00 ` Stephen Leake
@ 1998-04-24  0:00 ` Anonymous
  1998-04-24  0:00 ` Stephen Leake
  1998-04-28  0:00 ` Matthew Heaney
  3 siblings, 0 replies; 5+ messages in thread
From: Anonymous @ 1998-04-24  0:00 UTC (permalink / raw)



On Thu, 23 Apr 1998 14:50:13 -0500, "Paul T. McAlister"
<Paul.McAlister@AlliedSignal.com> asked about variable-length arrays of
variable-length arrays.

This is a common problem. The solution in Ada 83 was to use
discriminated records with a default discriminant value, where the
discriminant determined the length of the array, thereby making the
components of the array all the same type:

type Message_Info is record
   Text   : Some_Variable_Length_String_Type;
   Line   : Positive; -- Also known as Y position
   Column : Positive;
end record;

Max_Messages_Per_Page : constant := 25;

subtype Message_Num is Natural range 0 .. Max_Messages_Per_Page;

type Message_List is array (Message_Num range <>) of Message_Info;

type Page_Info (Num_Messages : Message_Num := 0) is record
   Message : Message_List (1 .. Num_Messages);
end record;

type Page_List is array (Positive range <>) of Page_Info;

Some people didn't like this, so Ada includes access-to-objects as a way
to have ragged arrays:

type Message_Info is record
   Text   : Ada.Strings.Unbounded.Unbounded_String;
   Line   : Positive; -- Also known as Y position
   Column : Positive;
end record;

type Message_Ptr is access all Message_Info;

Message_1 : aliased Message_Info := ...;
Message_2 : aliased Message_Info := ...;

type Page_List is array (Positive range <>) of Message_Ptr;

-- Then you declare your page array:

Page_1 : aliased Page_List := (Message_1'access, Message_2'access);

This can be carried on for as many levels as you wish. You define an
access type at each level, and an array type with the access type as the
component. As long as you declare things aliased, you can get access
values using 'access.

Jeff Carter  PGP:1024/440FBE21
My real e-mail address: ( carter @ innocon . com )
"You brightly-colored, mealy-templed, cranberry-smelling, electric
donkey-bottom biters."
Monty Python & the Holy Grail

Posted with Spam Hater - see
http://www.compulink.co.uk/~net-services/spam/




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Variable-length arrays (from a C programmer)
  1998-04-23  0:00 Variable-length arrays (from a C programmer) Paul T. McAlister
  1998-04-24  0:00 ` Stephen Leake
  1998-04-24  0:00 ` Anonymous
@ 1998-04-24  0:00 ` Stephen Leake
  1998-04-28  0:00 ` Matthew Heaney
  3 siblings, 0 replies; 5+ messages in thread
From: Stephen Leake @ 1998-04-24  0:00 UTC (permalink / raw)



Paul T. McAlister wrote:
> 
> I have an application where I will be displaying a number of different
> screens full of text messages.
> I want these messages and screens to be data table driven.
> 
> In "C" (see example), I can define an array of messages for each page,
> then define an array of pages for the whole thing.
> I don't have to worry about string length or number of items defined in
> the arrays, the compiler handles all of that for me.
> 
> I have not been able to figure out how to do the equivalent thing in
> Ada.
> I don't know how to define strings without setting the length to the
> maximum length string I will have, which wastes a lot of space.
> I think I know how to define the variable length arrays for the messages
> for each screen, but I don't know how to define an array type of these
> arrays of string for each page (since they are different types because
> they are different lengths).
> I am using Ada83.
> 
> I know this is a lengthy question, but any help would be greatly
> appreciated.


> 
> - - - - - - - - - - - -
> 
> #include <stdio.h>
> 
> // structure for each message
> typedef struct
> {
>   char *text;   // pointer to message text
>   int   xPos;   // x position on screen
>   int   yPos;   // y position on screen
> }
> MSG_STRUCT;
> 
> // structure for each page
> typedef struct
> {
>   MSG_STRUCT  *msg;      // pointer to array of message structures
>   int         num_msgs;   // number of message on this page
> }
> PAGE_STRUCT;
> 
> // page 1 messages
> MSG_STRUCT page1[] =
> { {"Greetings Earthling", 0, 0}
> , {"Take me to your leader", 1, 0}
> };
> 
> // page 2 messages
> MSG_STRUCT page2[] =
> { {"Screen 2", 0, 0}
> , {"This text is some lines farther down", 5, 0}
> , {"and this is even FARTHER down", 10, 0}
> };
> 
> // page 3 messages
> MSG_STRUCT page3[] =
> { {"This is the third screen", 0, 0}
> , {"and by now you should be getting", 1, 10}
> , {"the point of what it is", 2, 12}
> , {"I am trying to do!!", 3, 14}
> };
> 
> // messages for all pages
> PAGE_STRUCT pages[] =
> { {page1, (sizeof(page1) / sizeof(page1[0]))}
> , {page2, (sizeof(page2) / sizeof(page2[0]))}
> , {page3, (sizeof(page3) / sizeof(page3[0]))}
> };
> 
> void main()
> {
>   int iPage;
>   int iMsg;
>   int nPage;
> 
>   // find number of pages
>   nPage = sizeof(pages) / sizeof(pages[0]);
> 
>   // for each page
>   for (iPage = 0; iPage < nPage; ++iPage)
>   {
>     printf("\n");   // put blank line between pages
> 
>     // for each message
>     for (iMsg = 0; iMsg < pages[iPage].num_msgs; ++iMsg)
>     {
>       printf(pages[iPage].msg[iMsg].text);  // print message
>       printf("\n");                         // terminate line
>     }
>   }
> }
> 
>   --PTM                                   8-)
> --------------------------------------
> Paul McAlister
> Paul.McAlister@AlliedSignal.com
> 913.768.2238
> --------------------------------------




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Variable-length arrays (from a C programmer)
  1998-04-23  0:00 Variable-length arrays (from a C programmer) Paul T. McAlister
@ 1998-04-24  0:00 ` Stephen Leake
  1998-04-24  0:00 ` Anonymous
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Stephen Leake @ 1998-04-24  0:00 UTC (permalink / raw)



Paul T. McAlister wrote:
> 
> I have an application where I will be displaying a number of different
> screens full of text messages.
> I want these messages and screens to be data table driven.
> 
> In "C" (see example), I can define an array of messages for each page,
> then define an array of pages for the whole thing.
> I don't have to worry about string length or number of items defined in
> the arrays, the compiler handles all of that for me.
> 
> I have not been able to figure out how to do the equivalent thing in
> Ada.
> I don't know how to define strings without setting the length to the
> maximum length string I will have, which wastes a lot of space.
> I think I know how to define the variable length arrays for the messages
> for each screen, but I don't know how to define an array type of these
> arrays of string for each page (since they are different types because
> they are different lengths).
> I am using Ada83.
> 
> I know this is a lengthy question, but any help would be greatly
> appreciated.

Here's one way. It allocates the strings at elaboration time. Note that
Ada can determine the size of an array from its initializer (like a C
string, but unlike a C array).

with Ada.Text_IO; use Ada.Text_IO;
procedure Test is
-- structure for each page
   type String_Ptr is access String;

   type Msg_Struct is record
      Text : String_ptr;   -- pointer to message text
      XPos : integer;   -- x position on screen
      YPos : integer;   -- y position on screen
   end record;

   type Msg_Struct_Array is array (Integer range <> ) of Msg_Struct;
   type Msg_Struct_Array_Ptr is access Msg_Struct_Array;
   type Page_Struct is array (Integer range <> ) of
Msg_Struct_Array_ptr;

   Pages : constant Page_Struct :=
      (-- page 1 messages
       new Msg_Struct_Array'
       ((new String'("Greetings Earthling"), 0, 0),
        (new String'("Take me to your leader"), 1, 0)),

       -- page 2 messages
       new Msg_Struct_Array'
       ((new String'("Screen 2"), 0, 0),
        (new String'("This text is some lines farther down"), 5, 0),
        (new String'("and this is even FARTHER down"), 10, 0)),

       -- page 3 messages
       new Msg_Struct_Array'
       ((new String'("This is the third screen"), 0, 0),
        (new String'("and by now you should be getting"), 1, 10),
        (new String'("the point of what it is"), 2, 12),
        (new String'("I am trying to do!!"), 3, 14))
       );

  IPage : integer;
  IMsg : integer;
  NPage : integer;
begin
  -- find number of pages
  nPage := Pages'length;

  -- for each page
  for iPage in Pages'range loop
    New_Line;   -- put blank line between pages

    -- for each message
    for iMsg in Pages(IPage)'Range loop
      Put (Pages(IPage).all(IMsg).Text.all);  -- print message
      New_Line;                               -- terminate line
    end loop;
  end loop;
end Test;

This allocates everything at elaboration time; a smart compiler could do
it at compile or link time. To get closer to the C semantics (no
explicit allocation), you have to introduce more Ada names:

Page1_Message1 : constant aliased String := "Greetings Earthling";

Message1 : aliased Msg_Struct := (Page1_Message1'access, 0, 0);

etc.

-- Stephe




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Variable-length arrays (from a C programmer)
  1998-04-23  0:00 Variable-length arrays (from a C programmer) Paul T. McAlister
                   ` (2 preceding siblings ...)
  1998-04-24  0:00 ` Stephen Leake
@ 1998-04-28  0:00 ` Matthew Heaney
  3 siblings, 0 replies; 5+ messages in thread
From: Matthew Heaney @ 1998-04-28  0:00 UTC (permalink / raw)



In article <353F9B75.3019A7A4@AlliedSignal.com>, "Paul T. McAlister"
<Paul.McAlister@AlliedSignal.com> wrote:

(start of quote)
In "C" (see example), I can define an array of messages for each page,
then define an array of pages for the whole thing.
I don't have to worry about string length or number of items defined in
the arrays, the compiler handles all of that for me.

I have not been able to figure out how to do the equivalent thing in
Ada.
I don't know how to define strings without setting the length to the
maximum length string I will have, which wastes a lot of space.
I think I know how to define the variable length arrays for the messages
for each screen, but I don't know how to define an array type of these
arrays of string for each page (since they are different types because
they are different lengths).
I am using Ada83.
(end of quote)

You stated clearly that you are using Ada 83.  However, I wanted to let you
know that in Ada 95 there's a predefined string type that does exactly what
you want.  It's called Ada.Strings.Unbounded.Unbounded_String.

In Ada 83, you'll have to roll your own dynamic string abstraction,
something like

package Unbounded_Strings is

   type Unbounded_String is limited private;

   procedure Append (S : String; To : in out Unbounded_String);

   procedure Clear (Source : Unbounded_String);

...




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~1998-04-28  0:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-04-23  0:00 Variable-length arrays (from a C programmer) Paul T. McAlister
1998-04-24  0:00 ` Stephen Leake
1998-04-24  0:00 ` Anonymous
1998-04-24  0:00 ` Stephen Leake
1998-04-28  0:00 ` Matthew Heaney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox