Package bodies and main programs. Simple assignment (Ada)

给你一囗甜甜゛ 提交于 2021-01-28 01:34:11

问题


Im stuck in Ada. I'm supposed to create a package with a specific Flag_Type that can be written to and read in order to print a simple flag. Id like to think Ive managed to make the package ads and the package body adb right but I struggle with the commands for the main program.

First is first, the output is supposed to look like this:

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|
+---------+

now, my package ADS looks like this:

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;

My package body looks like this:

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;

and then my sorely lacking main program looks like this:

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;

Im only used to assignments that have one specific input, lets say Get(F) where F is Flag_Type, now its spread out over multiple variables and I dont know how to consolidate them.

I've been getting good responses from here in the past, is there any chance anyone could give me some tips as to where Im at fault? I know my main program is severely lacking but I dont know how to code it.

Thanks in advance for any help!


EDIT

I found a solution that works (sort of) which is commented out of this main program I direct to Simon Wright as I didnt quite get what you meant with your declarations. I put them in my MP and I keep getting "actual for item must be a variable". I tried using Item.Name instead but it claims its an invalid prefix. Where did I go wrong you think?

main program .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;

回答1:


A lot of your trouble is the Get procedure; it implements all the text input for the various fields without reference to whatever the main program’s doing.

In general, it isn’t good practice to do I/O within an abstract data type like Flag; much better to do it in the calling program. (I can see that’d be awkward for Put).

You could read the parameters in the main program and supply them to 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);

This would mean making the package spec (sorry, I couldn’t resist some tidying)

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;

and implementing Get in the package body as

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;

and the main program would be

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;



回答2:


Same method as in the previous post (see here), just add the user input logic:

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;

output

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


来源:https://stackoverflow.com/questions/61974481/package-bodies-and-main-programs-simple-assignment-ada

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