ada - 如何将我的 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 包(包简介)。我在您的代码中看到至少两个广泛的概念分类:产品/组件和模拟生产线(生产者和消费者)。将产品和组件的定义分离到一个包中,将任务定义(工厂工作)分离到另一个包中。
编辑:我已经花时间对您的代码进行分区。分区揭示了更好地组织代码的机会。例如,我将任务类型 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 参数从不在任务中使用。它被分配给一个局部变量,然后被忽略。
推荐阅读
- javascript - 我希望我的 HTML 弹出窗口出现在 JS if 语句中
- javascript - 登录 HTML(或 Javascript)后重定向到上一页
- azure - 将 Azure EventHub 的默认协议从 AMQP 更改为 HTTPS
- c++ - 从可变参数模板创建 std::list unique_ptr
- ionic-framework - 如何让离子卡取剩余高度?
- python - Django + gunicorn 因 POST 请求而超时
- postgresql - 如何使用更多内存在 HPC 集群上的 Singularity 容器中运行 PostgreSQL 服务器
- angular - netlify 在部署 Angular 项目时无法识别 ng
- python - 从 ERC-20 代币地址获取代币的详细信息
- python - 如何将一个数据框的元素与另一个数据框的元素进行比较?