成为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的能力?这甚至可以吗?
非常感谢..
答案 0 :(得分:2)
由于直到运行时才确定'Stiffness_Ratio',编译器无法在编译时计算'Actual_Stiffness'的值。您必须将“Actual_Stiffness”变为非常量变量,并在“Stiffness_Ratio”具有值后通过计算对其进行初始化。 (只要刚度比在计算实际刚度时具有值,您甚至可以将其保持为函数中的常量。)
这是大多数编程语言的标准。
所以,回答你的问题:
不,您无法根据需要将Actual_Stiffness定义为常量。
适度接近的近似值是您在此过程之外确定Stiffness_Ratio值,并将该值作为参数传递给过程。但是,Actual_Stiffness仅在程序持续时间内保持不变,而不是一直持续。
另一方面,这可能更有用;有人可以在不同的时间运行具有多个刚度比值的程序,从而在一次运行中进行多次模拟。
答案 1 :(得分:0)
在Ada中,在函数中间声明变量是完全可能和合理的。与基于C的语言的唯一区别是,必须这样做才能使作用域明确。您可以在任何地方开始作用域:
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;
例如,考虑以下Euclid的Greatest Common Divisor算法的非递归实现:
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;