我的问题是我创建了受保护的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
答案 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_Deallocation
或Ada.Containers.Indefinite_Holders
来很好地清理自身。
奖金问题:您认为M
过程中矩阵Main
的数组边界是什么?