首页 > 解决方案 > 如何将我的 Ada 程序拆分为单独的文件

问题描述

我有个问题; 我必须做这个项目,我不知道如何将代码分成几部分。我需要将“任务主体缓冲区”(位于末尾)部分与其余部分分开。我附上了我已经完成的设计模板。一切正常,但我需要分离方面的帮助,拜托。非常感谢您的帮助。

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; 
with Ada.Numerics.Discrete_Random;
procedure Simulation is
   Number_Of_Products: constant Integer := 5;
   Number_Of_Assemblies: constant Integer := 3;
   Number_Of_Consumers: constant Integer := 2;
   subtype Production_Time_Range is Integer range 3 .. 6;
   subtype Consumption_Time_Range is Integer range 4 .. 8;
   subtype Product_Type is Integer range 1 .. Number_Of_Products;
   subtype Assembly_Type is Integer range 1 .. Number_Of_Assemblies;
   subtype Consumer_Type is Integer range 1 .. Number_Of_Consumers;
   Product_Name: constant array (Product_Type) of String(1 .. 8)
     := ("Product1", "Product2", "Product3", "Product4", "Product5");
   Assembly_Name: constant array (Assembly_Type) of String(1 .. 9)
     := ("Assembly1", "Assembly2", "Assembly3");
   package Random_Consumption is new
     Ada.Numerics.Discrete_Random(Consumption_Time_Range);
   package Random_Assembly is new
     Ada.Numerics.Discrete_Random(Assembly_Type);
   type My_Str is new String(1 ..256);

   -- Producer produces determined product
   task type Producer is
      -- Give the Producer an identity, i.e. the product type
      entry Start(Product: in Product_Type; Production_Time: in Integer);
   end Producer;

   -- Consumer gets an arbitrary assembly of several products from the buffer
   task type Consumer is
      -- Give the Consumer an identity
      entry Start(Consumer_Number: in Consumer_Type;
            Consumption_Time: in Integer);
   end Consumer;

   -- In the Buffer, products are assemblied into an assembly
   task type Buffer is
      -- Accept a product to the storage provided there is a room for it
      entry Take(Product: in Product_Type; Number: in Integer);
      -- Deliver an assembly provided there are enough products for it
      entry Deliver(Assembly: in Assembly_Type; Number: out Integer);
   end Buffer;

   P: array ( 1 .. Number_Of_Products ) of Producer;
   K: array ( 1 .. Number_Of_Consumers ) of Consumer;
   B: Buffer;

   task body Producer is
      package Random_Production is new
    Ada.Numerics.Discrete_Random(Production_Time_Range);
      G: Random_Production.Generator;   --  generator liczb losowych
      Product_Type_Number: Integer;
      Product_Number: Integer;
      Production: Integer;
   begin
      accept Start(Product: in Product_Type; Production_Time: in Integer) do
     Random_Production.Reset(G);    --  start random number generator
     Product_Number := 1;
     Product_Type_Number := Product;
     Production := Production_Time;
      end Start;
      Put_Line("Started producer of " & Product_Name(Product_Type_Number));
      loop
     delay Duration(Random_Production.Random(G)); --  symuluj produkcjÄ
     Put_Line("Produced product " & Product_Name(Product_Type_Number)
            & " number "  & Integer'Image(Product_Number));
     -- Accept for storage
     B.Take(Product_Type_Number, Product_Number);
     Product_Number := Product_Number + 1;
      end loop;
   end Producer;

   task body Consumer is
      G: Random_Consumption.Generator;  --  random number generator (time)
      G2: Random_Assembly.Generator;    --  also (assemblies)
      Consumer_Nb: Consumer_Type;
      Assembly_Number: Integer;
      Consumption: Integer;
      Assembly_Type: Integer;
      Consumer_Name: constant array (1 .. Number_Of_Consumers)
    of String(1 .. 9)
    := ("Consumer1", "Consumer2");
   begin
      accept Start(Consumer_Number: in Consumer_Type;
             Consumption_Time: in Integer) do
     Random_Consumption.Reset(G);   --  ustaw generator
     Random_Assembly.Reset(G2); --  też
     Consumer_Nb := Consumer_Number;
     Consumption := Consumption_Time;
      end Start;
      Put_Line("Started consumer " & Consumer_Name(Consumer_Nb));
      loop
     delay Duration(Random_Consumption.Random(G)); --  simulate consumption
     Assembly_Type := Random_Assembly.Random(G2);
     -- take an assembly for consumption
     B.Deliver(Assembly_Type, Assembly_Number);
     Put_Line(Consumer_Name(Consumer_Nb) & ": taken assembly " &
            Assembly_Name(Assembly_Type) & " number " &
            Integer'Image(Assembly_Number));
      end loop;
   end Consumer;

   task body Buffer is
      Storage_Capacity: constant Integer := 30;
      type Storage_type is array (Product_Type) of Integer;
      Storage: Storage_type
    := (0, 0, 0, 0, 0);
      Assembly_Content: array(Assembly_Type, Product_Type) of Integer
    := ((2, 1, 2, 1, 2),
        (2, 2, 0, 1, 0),
        (1, 1, 2, 0, 1));
      Max_Assembly_Content: array(Product_Type) of Integer;
      Assembly_Number: array(Assembly_Type) of Integer
    := (1, 1, 1);
      In_Storage: Integer := 0;

      procedure Setup_Variables is
      begin
     for W in Product_Type loop
        Max_Assembly_Content(W) := 0;
        for Z in Assembly_Type loop
           if Assembly_Content(Z, W) > Max_Assembly_Content(W) then
          Max_Assembly_Content(W) := Assembly_Content(Z, W);
           end if;
        end loop;
     end loop;
      end Setup_Variables;

      function Can_Accept(Product: Product_Type) return Boolean is
     Free: Integer;     --  free room in the storage
     -- how many products are for production of arbitrary assembly
     Lacking: array(Product_Type) of Integer;
     -- how much room is needed in storage to produce arbitrary assembly
     Lacking_room: Integer;
     MP: Boolean;           --  can accept
      begin
     if In_Storage >= Storage_Capacity then
        return False;
     end if;
     -- There is free room in the storage
     Free := Storage_Capacity - In_Storage;
     MP := True;
     for W in Product_Type loop
        if Storage(W) < Max_Assembly_Content(W) then
           MP := False;
        end if;
     end loop;
     if MP then
        return True;        --  storage has products for arbitrary
                        --  assembly
     end if;
     if Integer'Max(0, Max_Assembly_Content(Product) - Storage(Product)) > 0 then
        -- exactly this product lacks
        return True;
     end if;
     Lacking_room := 1;         --  insert current product
     for W in Product_Type loop
        Lacking(W) := Integer'Max(0, Max_Assembly_Content(W) - Storage(W));
        Lacking_room := Lacking_room + Lacking(W);
     end loop;
     if Free >= Lacking_room then
        -- there is enough room in storage for arbitrary assembly
        return True;
     else
        -- no room for this product
        return False;
     end if;
      end Can_Accept;

      function Can_Deliver(Assembly: Assembly_Type) return Boolean is
      begin
     for W in Product_Type loop
        if Storage(W) < Assembly_Content(Assembly, W) then
           return False;
        end if;
     end loop;
     return True;
      end Can_Deliver;

      procedure Storage_Contents is
      begin
     for W in Product_Type loop
        Put_Line("Storage contents: " & Integer'Image(Storage(W)) & " "
               & Product_Name(W));
     end loop;
      end Storage_Contents;

   begin
      Put_Line("Buffer started");
      Setup_Variables;
      loop
     accept Take(Product: in Product_Type; Number: in Integer) do
       if Can_Accept(Product) then
          Put_Line("Accepted product " & Product_Name(Product) & " number " &
        Integer'Image(Number));
          Storage(Product) := Storage(Product) + 1;
          In_Storage := In_Storage + 1;
       else
          Put_Line("Rejected product " & Product_Name(Product) & " number " &
            Integer'Image(Number));
       end if;
     end Take;
     Storage_Contents;
     accept Deliver(Assembly: in Assembly_Type; Number: out Integer) do
        if Can_Deliver(Assembly) then
           Put_Line("Delivered assembly " & Assembly_Name(Assembly) & " number " &
              Integer'Image(Assembly_Number(Assembly)));
           for W in Product_Type loop
          Storage(W) := Storage(W) - Assembly_Content(Assembly, W);
          In_Storage := In_Storage - Assembly_Content(Assembly, W);
           end loop;
           Number := Assembly_Number(Assembly);
           Assembly_Number(Assembly) := Assembly_Number(Assembly) + 1;
        else
           Put_Line("Lacking products for assembly " & Assembly_Name(Assembly));
           Number := 0;
        end if;
     end Deliver;
     Storage_Contents;
      end loop;
   end Buffer;

begin
   for I in 1 .. Number_Of_Products loop
      P(I).Start(I, 10);
   end loop;
   for J in 1 .. Number_Of_Consumers loop
      K(J).Start(J,12);
   end loop;
end Simulation;

标签: ada

解决方案


您应该了解 Ada 包(包简介)。我在您的代码中看到至少两个广泛的概念分类:产品/组件和模拟生产线(生产者和消费者)。将产品和组件的定义分离到一个包中,将任务定义(工厂工作)分离到另一个包中。

编辑:我已经花时间对您的代码进行分区。分区揭示了更好地组织代码的机会。例如,我将任务类型 Buffer 更改为名为 Buffer 的任务。您的代码只需要此任务的一个实例。

套餐:

-----------------------------------------------------------------------
-- Notice that there is no relationship between products and
-- assemblies in the data definitions. That relationship is established
-- in the Buffer task type defined in the Tasks package;
-----------------------------------------------------------------------

package Products_Assemblies is
   Number_Of_Products: constant Integer := 5;
   Number_Of_Assemblies: constant Integer := 3;
   subtype Product_Type is Integer range 1 .. Number_Of_Products;
   subtype Assembly_Type is Integer range 1 .. Number_Of_Assemblies;
   Product_Name: constant array (Product_Type) of String(1 .. 8)
     := ("Product1", "Product2", "Product3", "Product4", "Product5");
   Assembly_Name: constant array (Assembly_Type) of String(1 .. 9)
     := ("Assembly1", "Assembly2", "Assembly3");
end Products_Assemblies;

请注意,此包不映射产品和组件之间的关系。这种关系通常最好建立为数据结构。二、产品类型可以更明确地实现为枚举类型

type Product_Type is (Product1, Product2, Product3, Product4, Product5);

同样 Assembly_Type 可以实现为

type Assembly_Type is (Assembly1, Assembly2, Assembly3);

枚举类型的枚举名称值可以使用 'Image 属性显示为字符串。

任务包规范:with products_assemblies;使用 Products_Assemblies;

package Tasks is
   Number_Of_Consumers  : constant Integer := 2;

   subtype Consumer_Type is Integer range 1 .. Number_Of_Consumers;


   -- Producer produces determined product
   task type Producer is
      -- Give the Producer an identity, i.e. the product type
      entry Start (Product : in Product_Type; Production_Time : in Integer);
   end Producer;

   -- Consumer gets an arbitrary assembly of several products from the buffer
   task type Consumer is
      -- Give the Consumer an identity
      entry Start (Consumer_Number : in Consumer_Type; Consumption_Time : in Integer);
   end Consumer;

   -- In the Buffer, products are assemblied into an assembly
   task Buffer is
      -- Accept a product to the storage provided there is a room for it
      entry Take (Product : in Product_Type; Number : in Integer);
      -- Deliver an assembly provided there are enough products for it
      entry Deliver (Assembly : in Assembly_Type; Number : out Integer);
   end Buffer;
end Tasks;

请注意,这是我将 Buffer 从任务类型更改为任务的地方。

Task package body:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Numerics.Discrete_Random;

package body tasks is

   subtype Production_Time_Range is Integer range 3 .. 6;

   subtype Consumption_Time_Range is Integer range 4 .. 8;

   package Random_Consumption is new Ada.Numerics.Discrete_Random
     (Consumption_Time_Range);

   package Random_Assembly is new Ada.Numerics.Discrete_Random (Assembly_Type);
   type My_Str is new String (1 .. 256);

   task body Producer is
      package Random_Production is new Ada.Numerics.Discrete_Random
        (Production_Time_Range);
      G : Random_Production.Generator;   --  generator liczb losowych
      Product_Type_Number : Integer;
      Product_Number      : Integer;
      Production          : Integer;
   begin
      accept Start (Product : in Product_Type; Production_Time : in Integer) do
         Random_Production.Reset (G);    --  start random number generator
         Product_Number      := 1;
         Product_Type_Number := Product;
         Production          := Production_Time;
      end Start;
      Put_Line ("Started producer of " & Product_Name (Product_Type_Number));
      loop
         delay Duration (Random_Production.Random (G)); --  symuluj produkcjÄ
         Put_Line
           ("Produced product " & Product_Name (Product_Type_Number) &
              " number " & Integer'Image (Product_Number));
         -- Accept for storage
         Buffer.Take (Product_Type_Number, Product_Number);
         Product_Number := Product_Number + 1;
      end loop;
   end Producer;

   task body Consumer is
      G                                             : Random_Consumption.Generator;  --  random number generator (time)
      G2                                            : Random_Assembly.Generator;    --  also (assemblies)
      Consumer_Nb                                   : Consumer_Type;
      Assembly_Number                               : Integer;
      Consumption                                   : Integer;
      Assembly_Type                                 : Integer;
      Consumer_Name                                 : constant array
        (1 .. Number_Of_Consumers) of String (1 .. 9) :=
        ("Consumer1", "Consumer2");
   begin
      accept Start (Consumer_Number : in Consumer_Type;
                    Consumption_Time           : in Integer) do
         Random_Consumption.Reset (G);   --  ustaw generator
         Random_Assembly.Reset (G2); --  też
         Consumer_Nb := Consumer_Number;
         Consumption := Consumption_Time;
      end Start;
      Put_Line ("Started consumer " & Consumer_Name (Consumer_Nb));
      loop
         delay Duration
           (Random_Consumption.Random (G)); --  simulate consumption
         Assembly_Type := Random_Assembly.Random (G2);
         -- take an assembly for consumption
         Buffer.Deliver (Assembly_Type, Assembly_Number);
         Put_Line
           (Consumer_Name (Consumer_Nb) & ": taken assembly " &
              Assembly_Name (Assembly_Type) & " number " &
              Integer'Image (Assembly_Number));
      end loop;
   end Consumer;

   task body Buffer is
      Storage_Capacity : constant Integer := 30;
      type Storage_type is array (Product_Type) of Integer;
      Storage          : Storage_type := (0, 0, 0, 0, 0);
      Assembly_Content : array (Assembly_Type, Product_Type) of Integer :=
        ((2, 1, 2, 1, 2), (2, 2, 0, 1, 0), (1, 1, 2, 0, 1));
      Max_Assembly_Content : array (Product_Type) of Integer;
      Assembly_Number      : array (Assembly_Type) of Integer := (1, 1, 1);
      In_Storage           : Integer                          := 0;

      procedure Setup_Variables is
      begin
         for W in Product_Type loop
            Max_Assembly_Content (W) := 0;
            for Z in Assembly_Type loop
               if Assembly_Content (Z, W) > Max_Assembly_Content (W) then
                  Max_Assembly_Content (W) := Assembly_Content (Z, W);
               end if;
            end loop;
         end loop;
      end Setup_Variables;

      function Can_Accept (Product : Product_Type) return Boolean is
         Free         : Integer;     --  free room in the storage
         -- how many products are for production of arbitrary assembly
         Lacking      : array (Product_Type) of Integer;
         -- how much room is needed in storage to produce arbitrary assembly
         Lacking_room : Integer;
         MP           : Boolean;           --  can accept
      begin
         if In_Storage >= Storage_Capacity then
            return False;
         end if;
         -- There is free room in the storage
         Free := Storage_Capacity - In_Storage;
         MP   := True;
         for W in Product_Type loop
            if Storage (W) < Max_Assembly_Content (W) then
               MP := False;
            end if;
         end loop;
         if MP then
            return True;        --  storage has products for arbitrary
            --  assembly
         end if;
         if Integer'Max (0,
                         Max_Assembly_Content (Product) - Storage (Product)) >
           0 then
            -- exactly this product lacks
            return True;
         end if;
         Lacking_room := 1;         --  insert current product
         for W in Product_Type loop
            Lacking (W) :=
              Integer'Max (0, Max_Assembly_Content (W) - Storage (W));
            Lacking_room := Lacking_room + Lacking (W);
         end loop;
         if Free >= Lacking_room then
            -- there is enough room in storage for arbitrary assembly
            return True;
         else
            -- no room for this product
            return False;
         end if;
      end Can_Accept;

      function Can_Deliver (Assembly : Assembly_Type) return Boolean is
      begin
         for W in Product_Type loop
            if Storage (W) < Assembly_Content (Assembly, W) then
               return False;
            end if;
         end loop;
         return True;
      end Can_Deliver;

      procedure Storage_Contents is
      begin
         for W in Product_Type loop
            Put_Line
              ("Storage contents: " & Integer'Image (Storage (W)) & " " &
                 Product_Name (W));
         end loop;
      end Storage_Contents;

   begin
      Put_Line ("Buffer started");
      Setup_Variables;
      loop
         accept Take (Product : in Product_Type; Number : in Integer) do
            if Can_Accept (Product) then
               Put_Line
                 ("Accepted product " & Product_Name (Product) & " number " &
                    Integer'Image (Number));
               Storage (Product) := Storage (Product) + 1;
               In_Storage        := In_Storage + 1;
            else
               Put_Line
                 ("Rejected product " & Product_Name (Product) & " number " &
                    Integer'Image (Number));
            end if;
         end Take;
         Storage_Contents;
         accept Deliver (Assembly : in Assembly_Type; Number : out Integer) do
            if Can_Deliver (Assembly) then
               Put_Line
                 ("Delivered assembly " & Assembly_Name (Assembly) &
                    " number " & Integer'Image (Assembly_Number (Assembly)));
               for W in Product_Type loop
                  Storage (W) := Storage (W) - Assembly_Content (Assembly, W);
                  In_Storage  := In_Storage - Assembly_Content (Assembly, W);
               end loop;
               Number                     := Assembly_Number (Assembly);
               Assembly_Number (Assembly) := Assembly_Number (Assembly) + 1;
            else
               Put_Line
                 ("Lacking products for assembly " & Assembly_Name (Assembly));
               Number := 0;
            end if;
         end Deliver;
         Storage_Contents;
      end loop;
   end Buffer;
end tasks;

最后,我提供了一个“主要”程序来测试这些包:

with Tasks; use Tasks;
with Products_Assemblies; use Products_Assemblies;

procedure Simulation_Main is
   P : array (1 .. Number_Of_Products) of Producer;
   K : array (1 .. Number_Of_Consumers) of Consumer;

begin
   for I in 1 .. Number_Of_Products loop
      P (I).Start (I, 10);
   end loop;
   for J in 1 .. Number_Of_Consumers loop
      K (J).Start (J, 12);
   end loop;
end Simulation_Main;

此版本编译无误并运行。没有内置方法可以终止模拟。您可能需要考虑提供一种干净的方法来关闭所有内容。您可能还想查看您的一些设计。例如,Producer 任务类型的 Start 条目的 Production_Time 参数从不在任务中使用。它被分配给一个局部变量,然后被忽略。


推荐阅读