包体和主程序。简单赋值 (Ada)

Package bodies and main programs. Simple assignment (Ada)

我卡在 Ada 里了。我应该创建一个具有特定 Flag_Type 的包,可以写入和读取以打印一个简单的标志。我想我已经设法使包广告和包主体 adb 正确,但我在主程序的命令上遇到了困难。

首先是第一个,输出应该是这样的:

Enter the flag name: Italys flag
Enter the flag height: 2
Enter the stripes width: 3
Enter the flags colors: GWR
Italys flag
+---------+
|GGGWWWRRR|
|GGGWWWRRR|
+---------+

现在,我的包裹 ADS 如下所示:

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

package Flagdrawer is

   type Flag_Type is private;


     procedure Get(Item: out Flag_Type);
   procedure Put(Item: in Flag_Type);

   private
   type Flag_Type is
      record

     Flag_Name: String(1..20);
     L : Integer;
     Flag_Height : Integer;
     Flag_Width : Integer;
     Flag_Colors : String(1..3);

      end record;
end Flagdrawer;

我的包体是这样的:

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

package body Flagdrawer is

   procedure Get(Item: out Flag_Type) is
   begin

      Get_Line(Item.Flag_Name, Item.L);
      Get(Item.Flag_Height);
      Get(Item.Flag_Width);
      Get(Item.Flag_Colors);

   end Get;

   procedure Put(Item: in Flag_Type) is

     Real_Width : Integer;

   begin
      Real_Width := Item.Flag_Width *3;
      Put(Item.Flag_Name(1..Item.L));
      New_Line;
      Put("+");
      for I in 1..Real_Width loop
     Put("-");
      end loop;
      Put_Line("+");

      for J in 1..Item.Flag_Height loop
     Put("!");
     for K in 1..Item.Flag_Width loop
        Put(Item.Flag_Colors(1));
        end loop;
        for L in 1..Item.Flag_Width loop
           Put(Item.Flag_Colors(2));
        end loop;
        for M in 1..Item.Flag_Width loop
           Put(Item.Flag_Colors(3));
        end loop;
        Put_Line("!");
      end loop;

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

   end Put;

end Flagdrawer;

然后我非常缺少的主程序如下所示:

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

procedure Tenta_Flagdrawah is

   F: Flag_Type;

begin

  Put_line("Enter the flags name (1): ");   
  Put_Line("Enter the flags height (2): ");
  Put_Line("Enter the stripes' width (3): ");
  Put_Line("Enter the RGB for the flag's colors (4): ");
  Get(F);

  New_Line;
  Put(F);

end Tenta_Flagdrawah;

我只习惯于具有一个特定输入的赋值,比如说 Get(F),其中 F 是 Flag_Type,现在它分布在多个变量上,我不知道如何合并它们。

过去我从这里得到了很好的回应,有没有人可以给我一些提示,告诉我我错在哪里?我知道我的主程序严重缺乏,但我不知道如何编码。

在此先感谢您的帮助!


编辑

我找到了一个(有点)有效的解决方案,它在我直接交给西蒙赖特的这个主程序中被注释掉了,因为我不太明白你的声明是什么意思。我把它们放在我的 MP 中,我不断得到 "actual for item must be a variable"。我尝试使用 Item.Name 代替,但它声称其前缀无效。你觉得我哪里做错了?

主程序.adb

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

procedure Tenta_Flagdrawah is

   F: Flag_Type;

subtype Color_String is String (1 .. 3);

procedure Get (Item : out Flag_Type;
               Name : in String;
               Height : in Natural;
               Stripe_Width : in Natural;
               Colors : in Color_String) is
begin

      Put("Enter the flag's name: ");
      Get(Name);
      Put("Enter the flag's height: ");
      Get(Height);

   end Get;
   begin

--   Put_line("Enter the flags name (1): ");
--   Put_Line("Enter the flags height (2): ");
--   Put_Line("Enter the stripes' width (3): ");
--   Put_Line("Enter the RGB for the flag's colors (4): ");
--   Get(F);


   New_Line;
   Put(F);

end Tenta_Flagdrawah;

方法同上一个post(参见),只是添加用户输入逻辑:

main.adb

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is

   Stripes      : constant array (Natural range <>) of Character := "GWR";
   Stripe_Width : constant Positive := 3;

   Width  : constant Natural := 2 + Stripes'Length * Stripe_Width;
   Height : constant Natural := 2 + 2;

   type Screen_X is new Natural range 0 .. Width  - 1;
   type Screen_Y is new Natural range 0 .. Height - 1;

   -------------
   -- Pattern --
   -------------

   function Pattern (X : Screen_X; Y : Screen_Y) return Character is

      Is_Border_LR : constant Boolean :=
        X = Screen_X'First or else X = Screen_X'Last;

      Is_Border_TB : constant Boolean :=
        Y = Screen_Y'First or else Y = Screen_Y'Last;

   begin

      if Is_Border_LR and Is_Border_TB then
         return '+';
      elsif Is_Border_LR then
         return '|';
      elsif Is_Border_TB then
         return '-';      
      else
         return Stripes (Integer (X - Screen_X'First - 1) / Stripe_Width);
      end if;

   end Pattern;

begin

   --  The Render loop.

   for Y in Screen_Y loop
      for X in Screen_X loop
         Put (Pattern (X, Y));
      end loop;
      New_Line;
   end loop;

end Main;

输出

$ ./main
+---------+
|GGGWWWRRR|
|GGGWWWRRR|
+---------+

你的很多麻烦是Get程序;它实现了各个字段的所有文本输入,而不参考主程序正在做什么。

一般来说,在 Flag 之类的 abstract data type 中执行 I/O 并不是好的做法;在调用程序中更好地完成它。 (我可以看出 Put 会很尴尬)。

您可以读取主程序中的参数并提供给Get,

subtype Color_String is String (1 .. 3);
procedure Get (Item : out Flag_Type;
               Name : in String;
               Height : in Natural;
               Stripe_Width : in Natural;
               Colors : in Color_String);

这意味着要制定包装规范(抱歉,我忍不住要整理一下)

package Flagdrawer is

   type Flag_Type is private;

   subtype Color_String is String (1 .. 3);

   procedure Get (Item         :    out Flag_Type;
                  Name         : in     String;
                  Height       : in     Positive;
                  Stripe_Width : in     Positive;
                  Colors       : in     Color_String);

   procedure Put(Item: in Flag_Type);

private
   type Flag_Type is
      record
         Name         : String (1 .. 20);
         Name_Len     : Natural;
         Height       : Positive;
         Stripe_Width : Positive;
         Colors       : Color_String;
      end record;

end Flagdrawer;

并在包体中实现 Get 作为

procedure Get (Item         :    out Flag_Type;
               Name         : in     String;
               Height       : in     Positive;
               Stripe_Width : in     Positive;
               Colors       : in     Color_String) is
begin
   --  Don’t exceed the 20-character limit on the stored Name
   Item.Name_Len := Natural'Min (Item.Name'Length, Name'Length);
   Item.Name (1 .. Item.Name_Len) := Name (Name'First .. Item.Name_Len);
   Item.Height := Height;
   Item.Stripe_Width := Stripe_Width;
   Item.Colors := Colors;
end Get;

主程序是

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Flagdrawer; use Flagdrawer;

procedure Tenta_Flagdrawah is

   F: Flag_Type;

begin
   Put("Enter the flags name: ");
   --  Need a declare block so that Name 
   --  is as long as the user input
   declare
      Name : constant String := Get_Line;
      Height : Positive;
      Stripe_Width : Positive;
      Colors : Flagdrawer.Color_String;
   begin
      Put("Enter the flag's height: ");
      Get (Height);
      Put("Enter the stripes' width: ");
      Get (Stripe_Width);
      Put("Enter the RGB for the flag's colors: ");
      Get (Colors);
      Get(F,
          Name => Name,
          Height => Height,
          Stripe_Width => Stripe_Width,
          Colors => Colors);
   end;

   New_Line;
   Put(F);

end Tenta_Flagdrawah;