问题
I created a simple Ada program that allows a user to populate an array with a maximum of 100 non negative and non zero integers and then prints them out. When I call the function to print out the numbers it prints them out but at the same time it also prints out a bunch of strange and seemingly random numbers. What mistake have I made in my code that is causing the program to output such strange results? This is my first time writing in Ada. For example when I populate the empty array with the numbers [1,2,3,4,5] is prints out this:
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
I am using the gnatmake compiler on ubuntu and when compiling the source code it doesn't give me any error/warning messages.
Here is my source code, I know that I probably don't need to use seperate functions but I implemented them anyways for learning purposes.
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;
回答1:
In mkarr
, you use a 0 or negative value to mark the end of the input, but you don't store that value in the array. If whatever garbage is stored in the array after the end of the values you entered happens to be positive, there's no way to tell that it's not a valid value.
In printarr
, if you encounter a 0 or negative value you don't print it -- but you continue printing the remaining positive values (which are garbage).
If you store a sentinel value in mkarr
, and quit printing in printarr
when you encounter the sentinel, the program should work.
Some other notes:
A
and K
are used only inside mkarr
. They should be local to mkarr
.
You never use Ada.Containers.Vectors
. You can delete the corresponding with
and use
directives.
For more advanced usage, you can have mkarr
return an array containing only the entered data, by making Vector
an unconstrained array type and returning a slice. It's still easier to define a fixed-length array inside mkarr
. Allowing arbitrarily many inputs is tricker -- but Ada.Containers
is probably a good way to do that. (Disclaimer: I haven't looked at Ada.Containers
.)
回答2:
Expanding on Keith’s answer: You want a variable-length result, so the more Ada-like way is to use an "unconstrained array":
type Vector is array (Positive range <>) of Integer;
This means that you can create instances of the array of any size you like, so long as the bounds are positive: 1 .. 100, 42 .. 43 etc. You can even create a zero-length array by specifying the last bound (called ’Last
) to be less than the first (called ’First
). In this special circumstance, you’re allowed to use a ’Last
outside the range of the index type (in this case, 0, or even -42 if you want to confuse people!).
function mkarr return Vector is
We have to have an actual array to accumulate the values, so set an upper limit of 100.
Result : Vector (1 .. 100);
We need to know how many elements there are.
Last : Natural := Result'First - 1;
More or less as before,
K : Integer;
begin
Ada.Text_IO.Put
("enter numbers to fill array, negative or 0 will stop process: ");
for I in Result'Range loop
We can return an array with at most Result’Length
elements.
Ada.Integer_Text_IO.Get (K);
if K > 0 then
We can add one more element.
Last := Last + 1;
Result (Last) := K;
else
There are fewer than 100 elements, so return just that slice.
return Result (Result'First .. Last);
end if;
end loop;
We’ve accumulated 100 results, so return all of them.
return Result;
end mkarr;
回答3:
As noted here, your example mentions Ada.Containers.Vectors with no further reference to the package. If you pursue such a solution, discussed here, you might first instantiate the generic package Vectors
to get a resizable container of integers:
package Integer_Container is new Vectors (Natural, Integer);
Your function to make an array can then declare a Vector
named A
and initialize its elements and length to specific values:
function Make_Array (Size : Count_Type) return Vector is
A : Vector := To_Vector (New_Item => -1, Length => Size);
…
You can use Iteration in Ada 2012 to simplify your data collection in Make_Array
:
for E of A loop
Get (K);
if K > 0 then
E := K;
else
exit;
end if;
end loop;
Similarly, a procedure Print_Array (A : in Vector)
might loop like this:
for E of A loop
Put (E, 4);
end loop;
A typical usage might look something like this:
Print_Array (Make_Array (42));
Additional details may be found here and here.
来源:https://stackoverflow.com/questions/61568595/printing-array-of-integers-generates-weird-output-in-ada