Ada.Text_IO.Float_IO.get() 未按预期运行

Ada.Text_IO.Float_IO.get() not behaving as expected

我学习 Ada 大约需要 5 个小时。我制作了一个简单的程序,我将不同的值放入其中并经历了我无法解释的行为。

我的程序可以正常输入,例如 km = 100、升 = 10、结果 = 10.0。

显然错误的输入有效:km = "cat" 导致 "raised ADA.IO_EXCEPTIONS.DATA_ERROR"

但是这种输入组合让我感到困惑:km = 100..10。该程序跳过升输入并显示一个返回到升值 0.10 的结果。当我输入 'cat'.

时,我期待出现约束错误

谁能给我解释一下这个以及 Ada 程序员是如何解决这个问题的,这样 100..10 就会导致错误。

这是我的程序:

--  This program takes km driven and litres consumed to calculate
--  fuel economy.

with Ada.Text_IO;
with Ada.Float_Text_IO;

procedure Main is
   package TIO renames Ada.Text_IO;
   package FIO renames Ada.Float_Text_IO;

   type Km is new Float range 0.01 .. 10_000.00;
   type Litres is new Float range 0.01 .. 10_000.00;

   package Km_IO is new TIO.Float_IO (Km);
   package Litres_IO is new TIO.Float_IO (Litres);

   Entered_Km : Km;
   Entered_Litres : Litres;

   function Fuel_Economy (
                          Entered_Km : in Km;
                          Entered_Litres : in Litres
                         ) return Float is
      --  returns fuel economy normalized to litres per 100 km
   begin
      return Float(Entered_Litres) / Float(Entered_Km) * 100.0;
   end Fuel_Economy;

begin
   TIO.Put_Line ("This program calculates fuel economy.");
   TIO.Put_Line ("Enter km:");
   Km_IO.Get (Entered_Km);
   TIO.Put_Line ("Enter litres:");
   Litres_IO.Get (Entered_Litres);
   TIO.Put ("Your fuel economy is ");
   FIO.Put (Item => Fuel_Economy (Entered_Km, Entered_Litres),
            Fore => 1,
            Aft => 2,
            Exp => 0
           );
   TIO.Put_Line (" litres per 100 km.");
end Main;

精确输出:

此程序计算燃油经济性。

输入公里数:

100..10

输入升:

您的燃油经济性是每 100 公里 0.10 升。

[2018-05-06 14:08:16]进程成功终止,耗时:04.01s


我在 windows 7.

上使用 GPS 2017

非常感谢。

根据 Ada Language Reference Manual A.10.9(15-16),您的 运行-time 库运行正常,因为这两种格式是 Ada.Text_IO.Float_IO.Get:

允许的语法
  • [+|–]数字.[指数]
  • [+|–].数字[指数]

一个解决方案是在读取(前导)数字后丢弃该行的其余部分:

TIO.Put_Line ("Enter km:");
Km_IO.Get (Entered_Km);
TIO.Skip_Line;

另一个不那么直接的方法是检查是否没有遗留任何东西:

TIO.Put_Line ("Enter km:");
Get_Km:
loop
   declare
      Input : constant String := TIO.Get_Line;
      Last : Natural;
   begin
      Km_IO.Get (From => Input, Item => Entered_Km, Last => Last);
      exit Get_Km when Input (Last + 1 .. Input'Length)
        = (Last + 1 .. Input'Length => ' ');
      TIO.Put_Line ("... just the number, please; '"
                      & Input (Last + 1 .. Input'Length)
                      & "' was left over");
   exception
      when others =>
         TIO.Put_Line ("... a number, please");
   end;
end loop Get_Km;

通常有经验的 Ada 用户将整行读入一个字符串(使用函数 Get_Line),然后从该字符串中提取数值。由于像这样的程序通常会循环直到用户输入有效值,因此读入字符串可避免直接数字 I/O 的常见问题,其中无效输入会导致无限循环:

Get_Km : loop
   Handle_Invalid : begin
      Put_Line (Item => "Enter km");
      Get (Item => Entered_Km);

      exit Get_Km;
   exception -- Handle_Invalid
   when others =>
      Put_Line ("Invalid input");
   end Handle_Invalid;
end loop Get_Km;

无效输入保留在缓冲区中,并被Get重复处理。

Wright 展示了这种变体,但通常在丢弃值后留在行中的任何内容,以便可以从带有尾随注释的文件中重定向输入:

13.3 -- km traveled