存储和使用变长字符串 (ADA)

Storing and using strings of varying length (ADA)

我正在解决一个问题,我需要根据输入的数字制作一组框,其中每个框都有一个唯一的名称。我已经设法创建了这些盒子,但我只设法在所有盒子上插入一个名字,因为我的名字在名字收集过程中被覆盖了。

这是代码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;

我一直在研究这个问题,如果有人能帮我找到一种方法来单独命名每个盒子,我将非常高兴。

提前致谢!

只要可以(在这里也可以),只需声明一个大小与您使用的名称完全相同的变量即可。这可以通过将其声明为不定数组并使用正确的名称对其进行初始化来完成。

所以你的主程序可能是:

 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 现在是一个返回正确大小的字符串的函数:

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

并且您可能应该重写没有 L 的 Spacebox(您始终可以使用 Name'Length 查看 Name 的长度)

Brian Drummond 已经介绍了如何取回可变长度名称以及使用它们的一些方法。为了解决您的一个名称覆盖所有名称的问题,您必须考虑到您正在使用一个名称变量来保存所有名称,因此一个名称覆盖其他名称是有道理的。要将多个名称存储在一起,请考虑使用 Indefinite_Vector 来保存它们。在您的 Objectcatcha 过程中,您获得了容量,因此可以使用它来设置向量的大小

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;

您将需要调整您的 SpaceBox 程序以使用矢量而不是名称或一次只使用一个名称(您的选择)。

一些注意事项: 1. 我将您的 Get 调用更改为 Get_Line 以获取姓名数量,如果您愿意,可以将其改回。 2. 当我将名称存储在向量中时,存储的最后一个字符可能是 "new line" 字符,因此您可能需要将其删除。这很容易做到。只需使用名称中除最后一个字符以外的所有字符。例如:

编辑:Simon Wright 表示不需要这样做。我的实现确实如此,所以如果您的设置与我测试的设置类似并且新行已被复制,我会把它留在这里。

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

由于您的程序似乎是一个非性能关键型应用程序,我会使用可变大小的字符串来避免存储 N 个不同的字符串长度。 在普通的 Ada 中,可变大小的字符串称为 Unbounded_String。 在这里,您的练习使用了一个开源包 (hac_pack: spec, body),它促进了可变大小字符串的处理。

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;

感谢 Zerte、Jere 和 Brian 提供的示例,非常感谢。不幸的是,我不能使用第三方包,因此排除了 Zertes 解决方案,至于 Jere,我很抱歉,但我只是一个简单的 codemonkey,ADA 知识非常浅,你的例子对我来说太复杂了。即使我得到了准确的代码并且它有效,我仍然不会学习它,因为它与我学校教的东西相差太多。就像没有 in/out 参数的程序一样,让我们​​举一个例子。也许我误解了它并没有那么糟糕但乍一看它似乎对我的 ADA 水平来说太复杂了。

Brians 我认为可行,但它的作用是,因为它循环了 Spacebox N 次,它创建了 N^2 个盒子,并且在不同的行上,而我在一行上只需要 N 个盒子。有没有什么办法可以修补代码来解决这个问题,因为它看起来很有希望?

再次感谢大家的抽空!

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;

这段代码完全按照我想要的方式工作,所以我认为它终于解决了:耶! :)