Ada protected Put 过程不写在同一行

Ada protected Put procedure doesn't write in the same line

我的问题是我创建了一个受保护的Safe_Printer;但是当我使用它的过程时,它弄乱了 Put 函数。每次它打印到一个新行。我如何才能避免这种情况?基本上,我想以可读的格式打印我的矩阵。

这是我的代码:

with Ada.Text_IO;
use Ada.Text_IO;

procedure main is

   type Matrix is array(integer range <>, integer range <>) of integer; 

    protected Safe_Printer is
        procedure Put(S: String);
        procedure Put(M: Matrix);
    end Safe_Printer;

    protected body Safe_Printer is

        procedure Put(S: String) is
        begin
            for I in S'range loop
                Put(S(I));
            end loop;
            New_Line;
        end Put;

        procedure Put(M:Matrix) is
        begin
            for I in m'range(1) loop
                for j in m'range(2) loop
                    put(integer'image(m(i,j)) & " ");
                end loop;
                new_line(1);
            end loop;
        end Put;
    end Safe_Printer;

m:Matrix := ((1,2,3),
            (4,5,6));
begin

    Safe_Printer.Put(m);


        for I in m'range(1) loop
            for j in m'range(2) loop
                put(integer'image(m(i,j)) & " ");
            end loop;
         new_line(1);
        end loop;

end main;

我的输出是:

 1
 2
 3

 4
 5
 6

 1  2  3
 4  5  6

因为 'Image 属性 returns a String,您的 Put(M : Matrix) 实现在其内部循环中调用 Safe_Printer.Put(S : String);每个矩阵条目然后得到一个 New_Line。一种解决方案是在 Safe_Printer.Put(M : Matrix):

中显式调用 Put 定义的语言
procedure Put(M : Matrix) is
begin
    for I in M'range(1) loop
        for j in M'range(2) loop
            Ada.Text_IO.Put(integer'image(M(i,j)) & " ");
        end loop;
        New_Line;
    end loop;
end Put;

经测试:

with Ada.Text_IO;
use Ada.Text_IO;

procedure main is

   type Matrix is array(integer range <>, integer range <>) of integer; 

    protected Safe_Printer is
        procedure Put(S : String);
        procedure Put(M: Matrix);
    end Safe_Printer;

    protected body Safe_Printer is

       procedure Put(S : String) is
       begin
           for I in S'range loop
               Put(S(I));
           end loop;
           New_Line;
       end Put;

        procedure Put(M : Matrix) is
        begin
            for I in M'range(1) loop
                for j in M'range(2) loop
                    Ada.Text_IO.Put(integer'image(M(i,j)) & " ");
                end loop;
                New_Line;
            end loop;
        end Put;
    end Safe_Printer;



M : Matrix := ((1,2,3),
               (4,5,6));
begin
    Safe_Printer.Put(M);
end main;

控制台:

$ ./main
 1  2  3 
 4  5  6 

或者,如 @SimonWright ,您可以 "remove the New_Line in Safe_Printer.Put(String)." 您选择的方法将取决于 Safe_Printer 规范中提供的所需效果。还要考虑限制 use 子句的范围。

您不应从受保护的对象中调用 'potentially blocking operation'。对 Text_IO.Put 的调用是一个潜在的阻塞操作。请参阅 Ada 参考手册第 9.5.1 节。我很惊讶你的编译器实际上没有抱怨。

在这种情况下,您可以做的一件事是使用任务而不是受保护的对象。

例如:

with Ada.Text_IO;

procedure Main is

   type Matrix is array (Integer range <>, Integer range <>) of Integer; 

   task Safe_Printer is
      entry Put (S: in String);
      entry Put (M: in Matrix);
   end Safe_Printer;

   task body Safe_Printer is
      S: access String;
      M: access Matrix;
   begin
      loop
         select
            accept Put (S: in String) do
               Safe_Printer.S := new String (S'Range);
               Safe_Printer.S.all := S;
            end;
            Ada.Text_IO.Put_Line (S.all);
         or
            accept Put (M: in Matrix) do
               Safe_Printer.M := new Matrix (M'Range (1), M'Range (2));
               Safe_Printer.M.all := M;
            end;
            for I in M'Range (1) loop
               for J in M'Range (2) loop
                  Ada.Text_IO.Put (Integer'Image (M (I, J)) & " ");
               end loop;
               Ada.Text_IO.New_Line;
            end loop;
         or
            terminate;
         end select;
      end loop;
   end Safe_Printer;

   M: Matrix := ((1,2,3),
                 (4,5,6));
begin
   Safe_Printer.Put (M);
end Main;

这种方法的另一个优点是对 Text_IO.Put[_Line] 的调用实际上是与主任务并行执行的。缺点是(为了安全起见)复制要打印的字符串或矩阵。

此代码的更好版本可能会使用 Unchecked_DeallocationAda.Containers.Indefinite_Holders 来很好地自行清理。

附加问题:您认为 Main 过程中矩阵 M 的数组边界是什么?