Storing and using strings of varying length (ADA)

蓝咒 提交于 2021-02-19 05:06:50

问题


Im working on a problem where I need to make a set of boxes according to an input number where each and every box has a unique name. I've managed to create the boxes but I've only managed to insert one name on all of them as my names are overwritten in the name collecting procedure.

here is the code https://pastebin.com/FBMvvrn4

with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Float_Text_IO;     use Ada.Float_Text_IO;
with Ada.Integer_Text_IO;   use Ada.Integer_Text_IO;

procedure exercise is

  N : Integer;
  Names : String(1..10);
  L : Integer;

  procedure Objectcatcha (N: out Integer) is

  begin

  Put("Enter amount of objects: ");
  Get(N);

  end Objectcatcha;

  procedure Namescatcha (Names: out string; L: out integer) is

  begin
 for I in 1..N loop
    Get_Line(Names, L);
 end loop;

  end Namescatcha;

  procedure SpaceBox(Names: in String; L: in Integer; N : in integer) is

 begin

 for I in 1..N loop
    Put("+-----------+     ");
 end loop;
 New_Line;

 for I in 1..N loop
    Put("! ");
    Put(Names(1..L));
    for J in (L+1)..10 loop
       Put(" ");
    end loop;
    Put("!");

    if I = N then
       Put("");
    else
       Put("<>---");
    end if;
 end loop;
 New_Line;

 for I in 1..N loop
    Put("+-----------+     ");
 end loop;

  end SpaceBox;

  begin

  Objectcatcha(N);

  Put("Enter the name of the objects: ");
  Namescatcha(Names, L);

  SpaceBox(Names,L, N);

  end exercise;

I've been sitting around a lot with this and Id be very glad if someone could help me find a way to name each box individually.

Thanks in advance!


回答1:


Where you can, (and you can here), just declare a variable of the exact size to hold the name you are using. This can be done by declaring it as an indefinite array, and initialising it with the correct name.

So your main program could be:

 Objectcatcha(N);    
 For I in 1 to N loop
   Put("Enter the name of the next object: ");
   Declare
     Name : String := Namescatcha;
   Begin
     SpaceBox(Name, Name'Length, N);  
   End;
 End loop;

Namescatcha is now a function returning just the right size of string:

function Namescatcha return String is
begin
   return Getline;
end Namescatcha;

and you should probably rewrite Spacebox without L (you can always use Name'Length to see the length of Name)




回答2:


Brian Drummond already covered how to get back a variable length name and some means to work with them. In order to address your one name overwriting all the names problem, you have to consider that you are using one name variable to hold them all so it makes sense that one is overwriting the others. To store multiple names together, consider using an Indefinite_Vector to hold them. In your Objectcatcha procedure you get the capacity so use that to set the size of the vector

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Indefinite_Vectors; use Ada.Containers;

-- Other stuff

package Name_Vectors is new Indefinite_Vectors
    (Index_Type   => Positive,
     Element_Type => String);

Names : Name_Vectors.Vector;

package Count_Type_IO is new Integer_IO(Count_Type);

procedure Objectcatcha is
    Number : Count_Type;
    Last : Positive; -- Placeholder for Get call
begin

    Put("Enter amount of objects: ");
    Count_Type_IO.Get
        (From => Get_Line,
         Item => Number,
         Last => Last);
    Names.Reserve_Capacity(Number);

end Objectcatcha;

procedure Namescatcha is
begin
    for Index in 1..Names.Capacity loop
        Names.Append(Get_Line);
    end loop;
end Namescatcha;

You will need to adjust your SpaceBox procedure to use the vector instead of the name or to only do one name at a time (your choice).

A few notes: 1. I changed your Get call to Get_Line for getting the number of names, you can change it back if you want. 2. When I stored the names in the vector, the last character stored might be the "new line" character, so you may have to strip it out. That's easy to do. Just use all the characters of the name except the last one. for example:

EDIT: Simon Wright indicated that this shouldn't be needed. My implementation does, so I'll leave this here if you have a setup similar to what I tested on and the new lines are copied.

declare
    Name : String := Names(Index);
begin
    Put(Name(1..Name'Length-1));
end;



回答3:


Since your program seems to be a non-performance-critical application, I'd use variable-size strings to avoid storing the N different string lengths. In plain Ada variable-size strings are called Unbounded_String. Here, your exercise using an open-source package (hac_pack: spec, body) which facilitates things around variable-size strings.

with HAC_Pack;  use HAC_Pack;

procedure Names_in_Boxes is

  Max : constant := 100;
  type Names_Type is array (1 .. Max) of VString;

  procedure Objectcatcha (N: out Integer) is
  begin
    Put("Enter amount of objects: ");
    Get(N);
    Skip_Line;
  end Objectcatcha;

  procedure Namescatcha (Names: out Names_Type; N : in Integer) is
  begin
    for I in 1..N loop
      Put(+"Object " & I & ": ");
      Get_Line(Names (I));
    end loop;
  end Namescatcha;

  procedure SpaceBox(Names: in Names_Type; N : in Integer) is
  begin
    Put_Line (N * (+"+-----------+     "));
    for I in 1..N loop
       Put("! " & Names(I) & (10 - Length(Names(I))) * ' ' & "!");
       if I = N then
          Put("");
       else
          Put("<>---");
       end if;
    end loop;
    New_Line;
    Put_Line (N * (+"+-----------+     "));
  end SpaceBox;

  --  "Global" variables, unknown to
  --  Objectcatcha, Namescatcha, SpaceBox:
  N : Integer;
  Names : Names_Type;

begin
  Objectcatcha(N);
  Put_Line("Enter the name of the objects: ");
  Namescatcha(Names, N);
  SpaceBox(Names, N);
end Names_in_Boxes;



回答4:


Thanks Zerte, Jere and Brian for your examples, it's much appreciated. Unfortunately I can't use third party packages so that rules out Zertes solution and as for Jere Im sorry but Im just a simple codemonkey with very shallow ADA knowledge and your example is just too complicated for me. Even if I got the exact code and it worked I still wouldnt learn it because it differs too much from what my school is teaching out. Like the procedures not having in/out parameters lets say for one. Maybe I misunderstand and its not that bad but at first glance it seems too complex for my level of ADA.

Brians I thought would work but what it does is, because it loops Spacebox N times, it creates N^2 amount of boxes, and on separate lines, when I only need N boxes on one line. Is there any way we could perhaps patch up the code to fix this because it seemed promising?

Thanks again for your time all of you!

with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Float_Text_IO;     use Ada.Float_Text_IO;
with Ada.Integer_Text_IO;   use Ada.Integer_Text_IO;
with Ada.Strings.Unbounded;     use Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Text_IO; use Ada.Strings.Unbounded.Text_IO;


procedure exercise is

   Y : Ada.Text_IO.Count;
   N : Integer; 
   Names : Unbounded_string;
   type Names_Type is array (Positive range <>) of Unbounded_String;

   procedure Objectcatcha (N : out Integer) is

   begin

      Put("Enter amount of objects: ");
      Get(N);
      Skip_Line;

   end Objectcatcha;



   procedure Namescatcha (Names: out Names_Type; N : in Integer) is

   begin
      for I in Names'Range loop
     Get_Line(Names(I));
      end loop;

   end Namescatcha;

   procedure SpaceBox (Names: in Names_Type; N : in Integer) is

   begin

      for I in 1..N loop
     Put("+-----------+     ");
      end loop;
      New_Line;

      for I in Names'Range loop
     Put("! ");
     Put(Names(I));

     Y := Ada.Text_IO.Count(I);
     Set_Col(13+18*(Y-1));

     Put("!");

     if I = N then
        Put("");
     else
        Put("<>---");
     end if;

      end loop;
      New_Line;

      for I in 1..N loop
     Put("+-----------+     ");
      end loop;

   end SpaceBox;

begin

   Objectcatcha(N);
   declare
      A : Names_Type (1..N);
   begin
      Put("Enter the name of the objects: ");
      Namescatcha(A, N);
      SpaceBox(A, N);
   end;

end exercise;

This code works exactly the way I wanted it to, so I think it's finally solved: yay! :)



来源:https://stackoverflow.com/questions/61719343/storing-and-using-strings-of-varying-length-ada

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!