如何使用Put_Line方法输出整数?

17

我无法编译此程序,因为 Put_Line 方法似乎无法输出整数变量和字符串。我查看了在线源代码,当他们这样做时它能正常工作,所以我错在哪里了。谢谢你的帮助。

with Ada.Text_IO;                       use Ada.Text_IO;
with Ada.Integer_Text_IO;           use Ada.Integer_Text_IO;

procedure MultiplicationTable is

    procedure Print_Multiplication_Table(Number :in Integer; Multiple :in Integer) is
        Result : Integer;   
    begin
        for Count in 1 ..Multiple
        loop
            Result := Number * Count;
            Put_Line(Number & " x " & Count & " = " & Result);
        end loop; 
    end Print_Multiplication_Table;
    Number  :   Integer;
    Multiple    :   Integer;

begin
    Put("Display the multiplication of number: ");
    Get(Number);
    Put("Display Multiplication until number: ");
    Get(Multiple);
    Print_Multiplication_Table(Number,Multiple);
end MultiplicationTable;`
4个回答

14
问题在于你正在使用 & 来连接字符串和整数。 请尝试以下方法之一:
将 put 参数中的 Number 替换为 Integer'Image(Number)
或者将 Put_Line 拆分为所需的组件,例如:
-- Correction to Put_Line(Number & " x " & Count & " = " & Result);
Put( Number );
Put( " x " );
Put( Count );
Put( " = " );
Put( Result);
New_Line(1);

为什么要使用New_Line(1);而不是只用New_Line;呢? - Keith Thompson
@Keith -- 老实说:我不记得默认值是1还是根本不存在默认值,但我记得有一个参数。 - Shark8

5

试试这个:

Put_Line(Integer'Image(Number) & " x " & Integer'Image(Count) & " = " & Integer'Image(Result));

1
我相信除非作者需要以特定格式输出数字,如前导零、小数位精度等,否则这是迄今为止最好的解决方案。在这里清楚地了解使用的类型和调用的过程。 - mulander
必须考虑到此处提到的前导字符,详见此处 - trashgod
1
那个前导字符可能看起来很麻烦;但是想一想,如果要在等宽列格式(用于有符号数字)中显示标志...相比于根据给定值的符号有条件地添加' '或'-'前缀,从字符串中获取第一个+1..最后一个字符可能更容易和更短。 - Shark8

5

您已经使用了 withuse 从句导入了 Ada.Integer_Text_IO,但实际上您并没有使用它。

将其更改为:

Put_Line(Number & " x " & Count & " = " & Result);

转换为:

Put(Number); Put(" x "); Put(Count); Put(" = "); Put(Result); New_Line;

(通常我不会在一行上放置多个语句,但在这种情况下是有意义的。)

请注意,Integer'Image 在非负整数前加了一个空格,这是我一直感到非常烦恼的事情;除非你要求,否则 Ada.Integer_Text_IO.Put 不会这样做。

您可以定义重载的 "&" 函数,类似于这样:

function "&"(Left: String; Right: Integer) return String is
begin
    return Left & Integer'Image(Right);
end "&";

function "&"(Left: Integer; Right: String) return String is
begin
    return Integer'Image(Left) & Right;
end "&";

这将使您最初的Put_Line调用有效,但多个Put调用可能更好看一些。

为什么多个Put行更可取?从C背景中来看,printf风格最受欢迎,其次是连接。然后就有了并发问题,多次调用Put会引入这个问题。当观察到Put已经有了类似的机制时,在打印任务上引入一个如此小的问题似乎过于冗余。 - Assimilater
Ada没有printf,而且很难实现类似于printf的类型安全解决方案。整数不能使用连接(除非您重载"&"运算符)。如果您想要特殊格式(填充、数字基数等),可以在每个Put调用中应用它。故意选择了短名称Put,以便多次调用不会过于冗长。Put引入了什么并发问题? - Keith Thompson
多个任务输出到控制台,不能保证在调用“Put”之间不会发生上下文切换。这是并发问题的经典例子,需要像操作系统课程中使用的互斥工具(如互斥锁和信号量)来解决。 - Assimilater

0

在Keith Thompson的答案(以及另一个问题的评论)的基础上,这里是一个完整的Ada程序,可以使用&Put_Line输出字符串和整数,但不会像Integer'Image一样添加空格:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure Main is

function lstrip(S: String) return String is
begin
    if S(S'First) = ' ' then
        return S(S'First+1 .. S'Last);
    else
        return S;
    end if;
end;

function "&"(Left: String; Right: Integer) return String is
begin
    return Left & lstrip(Integer'Image(Right));
end "&";

function "&"(Left: Integer; Right: String) return String is
begin
    return lstrip(Integer'Image(Left)) & Right;
end "&";

begin
   Put_Line("x=" & 42);
end Main;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接