受Ada保护的Put程序不在同一行中写

时间:2018-12-02 15:51:19

标签: ada

我的问题是我创建了受保护的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

2 个答案:

答案 0 :(得分:2)

由于'Image属性返回一个String,因此您对Put(M : Matrix)的实现会在其内部循环中调用Safe_Printer.Put(S : String);然后,每个矩阵条目都会得到一个New_Line。一种解决方案是在Put中显式调用Safe_Printer.Put(M : Matrix)定义的语言:

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 comments,您可以“删除New_Line中的Safe_Printer.Put(String)。”您选择的方法将取决于Safe_Printer规范中提供的期望效果。还可以考虑限制use子句的范围。

答案 1 :(得分:0)

您不应从受保护的对象内调用“潜在阻止操作”。对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来很好地清理自身。

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