[英]Constant declaration in Ada
作为 Ada 的新手,我正在探索它的语法和规则,我想提请注意接下来给出的代码。 在这里,我试图设置一个变量 Actual_Stiffness 来保持一个常量值。 它的价值由产品给出:
Actual_Stiffness := Stiffness_Ratio * Stiffness_Total
其中 Stiffness_Total 已在规范文件 Material_Data.ads 中定义为常量 Long_Float,而 Stiffness_Total 的值已在广告文件中设置。
WITH Ada.Text_IO;
WITH Ada.Long_Float_Text_IO;
WITH Material_Data;
USE Material_Data;
PROCEDURE sample IS
Stiffness_Ratio : Long_Float;
Actual_Stiffness : CONSTANT Long_Float := Stiffness_Ratio * Stiffness_Total;
BEGIN -- main program
Ada.Text_IO.Put("Enter stiffness ratio: ");
Ada.Long_Float_Text_IO.Get(Item => Stiffness_Ratio);
Ada.Long_Float_Text_IO.Put(Item => Stiffness_Ratio);
--Ada.Text_IO.New_Line;
--Ada.Long_Float_Text_IO.Put(Item => Actual_Stiffness);
--Ada.Text_IO.New_Line;
--Ada.Long_Float_Text_IO.Put(Item => Stiffness_Total);
END sample;
在编译时,我收到警告消息
警告:“Stiffness_Ratio”可能在具有值之前被引用
在运行程序时,Actual_Stiffness 没有得到正确的值。 我可以将 Actual_Stiffness 定义为一个 Long_Float(不添加 CONSTANT),然后在程序中的 BEGIN 之后从产品 Actual_Stiffness := Stiffness_Ratio * Stiffness_Total 中获取它的值,此时 Stiffness_Ratio 已经获得了一个值。 这将是正确的做法。
我的问题是:
我已将 Stiffness_Total 定义为具有规定值的常量 Long_Float。 如何将 Actual_Stiffness 定义为常量(因为它不会在程序中改变),同时保持用户能够在终端交互输入 Stiffness_Ratio 的能力? 这甚至可能做到吗?
非常感谢..
由于 'Stiffness_Ratio' 直到运行时才确定,编译器无法按照您的要求在编译时计算 'Actual_Stiffness' 的值。 您必须将 'Actual_Stiffness' 设为非常量变量,并在 'Stiffness_Ratio' 具有值后使用计算对其进行初始化。 (您甚至可以将其作为函数内的 CONSTANT 保留,只要刚度比在计算实际刚度时具有值。)
这是大多数编程语言的标准。
所以,回答你的问题:
不,您不能根据需要将 Actual_Stiffness 定义为常量。
一个适度接近的近似值是在此过程之外确定 Stiffness_Ratio 值,并将该值作为参数传递到过程中。 但是 Actual_Stiffness 仅在程序持续时间内保持不变,而不是所有时间。
另一方面,这可能更有用; 有人可以在不同时间运行具有多个刚度比值的程序,从而在一次运行中进行多次模拟。
在 Ada 中,在函数中间声明变量是完全可能且合理的。 就像在所有其他编程语言(至少是 Java、C、C++、C#、python)中一样,您可以在任何地方显式地创建作用域:
declare
A : My_Type := Val;
begin
Use(A);
end;
这意味着您的常量可以在收到运行时值后声明:
WITH Ada.Text_IO;
WITH Ada.Long_Float_Text_IO;
WITH Material_Data;
USE Material_Data;
PROCEDURE sample IS
Stiffness_Ratio : Long_Float;
BEGIN -- main program
Ada.Text_IO.Put("Enter stiffness ratio: ");
Ada.Long_Float_Text_IO.Get(Item => Stiffness_Ratio);
Ada.Long_Float_Text_IO.Put(Item => Stiffness_Ratio);
--Ada.Text_IO.New_Line;
declare
Actual_Stiffness : CONSTANT Long_Float := Stiffness_Ratio * Stiffness_Total;
begin
Ada.Long_Float_Text_IO.Put(Item => Actual_Stiffness);
end;
--Ada.Text_IO.New_Line;
--Ada.Long_Float_Text_IO.Put(Item => Stiffness_Total);
END sample;
例如,考虑以下欧几里德最大公约数算法的非递归实现:
function GCD(X,Y : Integer) return Integer is
begin
declare
X : Integer := GCD.X;
Y : Integer := GCD.Y;
begin
while Y /= 0 loop
declare
temp : Integer := X;
begin
X := Y;
Y := temp mod Y;
end;
end loop;
return X;
end;
end GCD;
在 GCD 中,参数 X 和 Y 始终是常量,因为它们被声明为in
。 这是为了避免混淆; 如果我们允许对变量赋值,程序员可能会认为他造成了副作用,就像如果参数被标记out
。
在这种情况下,John Barnes 在 Ada 2012 中编程建议在函数本身的范围内声明一个具有不同名称的变量。 在第 194 页,第 11.2 节:
function Sum(List: Cell_Ptr) return Integer is
Local: Cell_Ptr := List;
(...)
这让程序员能够引用 List,常量和未更改的初始值。 在上面给出的 GCD 程序的情况下,在循环体中引用该值会导致不正确的行为。
通过添加具有同名变量的内部作用域来隐藏 X 和 Y 意味着我们需要显式包含变量的作用域才能犯这个错误。 尝试将循环体中的X := Y
更改为X := GCD.Y
,并观察 GCD(91,21) 现在返回 21 而不是 7。
最后,请注意,可以通过预先添加标签来为内部作用域命名:
Inner:
declare
X : Integer := 0;
begin
Use(Inner.X); -- explicitly the X in that scope
end Inner;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.