Printing array of integers generates weird output in Ada

六眼飞鱼酱① 提交于 2020-05-16 05:53:06

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!