我创建了一个简单的Ada程序,该程序允许用户使用最多100个非负和非零整数填充数组,然后将其打印出来。当我调用该函数以打印数字时,它会打印出它们,但同时它还会打印出一堆奇怪的,看似随机的数字。我在代码中犯了什么错误,导致程序输出了如此奇怪的结果?这是我第一次在Ada写作。例如,当我用数字[1,2,3,4,5]填充空数组时,将输出以下内容:
1
2
3
4
5
32624
911328835
32624
911328836
32624
67043328
134217726
134217726
2013265921
134217726
134217726
134217726
67043328
909181968
32624
2114692683
89452
914381552
32624
1543503876
2
14
2
14
我在ubuntu上使用gnatmake编译器,并且在编译源代码时不会给我任何错误/警告消息。
这是我的源代码,我知道我可能不需要使用单独的函数,但是我还是出于学习目的而实现了它们。
with Ada.Containers.Vectors;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
use Ada.Containers;
procedure thing is
type Vector is array (1..100) of Integer;
A: Vector;--array doesn't need to be completely filled up
K: Integer;
--array filling function below
function mkarr return Vector is --asks user to fill empty array with positive and non zero integers
begin
Ada.Text_IO.Put ("enter numbers to fill array, negative or 0 will stop process: ");
for I in 1..100 loop
Ada.Integer_Text_IO.Get(K);
if K>0 then
A(I) := K;
end if;
if K<=0 then
return A;
end if;
end loop;
return A;
end;
--array printing prodcedure below
procedure printarr(A: in out Vector) is
begin
for I in A'Range loop
if A(I)>0 then
Ada.Integer_Text_IO.Put(A(I));
New_Line(1);
end if;
end loop;
end printarr;
B: Vector := mkarr;
--main method below
begin
printarr(A);
end thing;
答案 0 :(得分:6)
在mkarr
中,您使用0或负值来标记输入的结尾,但是您不将该值存储在数组中。如果在您输入的值的结尾之后数组中存储了任何垃圾,而这些垃圾恰好是正数,则无法断定它不是有效值。
在printarr
中,如果遇到0或负值,则不打印它-但您将继续打印其余的正值(这是垃圾)。
如果您将哨兵值存储在mkarr
中,并且在遇到哨兵时退出在printarr
中的打印,则程序应该可以工作。
其他一些注意事项:
A
和K
仅在mkarr
内部使用。它们应位于mkarr
的本地。
您从不使用Ada.Containers.Vectors
。您可以删除相应的with
和use
指令。
对于更高级的用法,可以通过使mkarr
成为不受约束的数组类型并返回一个切片,来使Vector
返回仅包含输入数据的数组。在mkarr
内定义固定长度的数组仍然更加容易。允许任意输入很多是很麻烦的,但是Ada.Containers
可能是一个很好的方法。 (免责声明:我没有看过Ada.Containers
。)
答案 1 :(得分:3)
在Keith’s answer上展开: 您需要一个可变长度的结果,因此更像Ada的方法是使用“无约束数组”:
type Vector is array (Positive range <>) of Integer;
这意味着您可以创建任意大小的数组实例,只要边界是正数即可:1 .. 100,42 .. 43等。您甚至可以通过指定最后一个边界(称为’Last
)小于第一个边界(称为’First
)。在这种特殊情况下,您可以在索引类型范围之外使用’Last
(在这种情况下,如果要使人们感到困惑,则可以使用0或-42!)。
function mkarr return Vector is
我们必须有一个实际的数组来累加值,所以将上限设置为100。
Result : Vector (1 .. 100);
我们需要知道有多少个元素。
Last : Natural := Result'First - 1;
或多或少,
K : Integer;
begin
Ada.Text_IO.Put
("enter numbers to fill array, negative or 0 will stop process: ");
for I in Result'Range loop
我们可以返回一个最多包含Result’Length
个元素的数组。
Ada.Integer_Text_IO.Get (K);
if K > 0 then
我们可以再添加一个元素。
Last := Last + 1;
Result (Last) := K;
else
少于100个元素,因此仅返回该切片。
return Result (Result'First .. Last);
end if;
end loop;
我们已经累积了100条结果,因此请全部退回。
return Result;
end mkarr;
答案 2 :(得分:1)
如here所述,您的示例提到了Ada.Containers.Vectors
,而没有进一步引用该软件包。如果您采用here所述的解决方案,则可以首先实例化通用包Vectors
,以获得可调整大小的整数容器:
package Integer_Container is new Vectors (Natural, Integer);
然后,您创建数组的函数可以声明一个名为Vector
的{{1}}并将其元素和长度初始化为特定值:
A
您可以在Ada 2012中使用Iteration来简化function Make_Array (Size : Count_Type) return Vector is
A : Vector := To_Vector (New_Item => -1, Length => Size);
…
中的数据收集:
Make_Array
类似地,for E of A loop
Get (K);
if K > 0 then
E := K;
else
exit;
end if;
end loop;
可能会像这样循环:
procedure Print_Array (A : in Vector)
典型用法如下:
for E of A loop
Put (E, 4);
end loop;