首页 文章

Ada:如何在获取整数时管理Data_error异常

提问于
浏览
2

我试图让用户从菜单中选择一个模式

  • 睡觉

现在我可以使用该调用获得整数输入

ada.integer_text_io.get(integer_variable);

这里的主要问题是,如果我插入非数字字符串(例如字符串),则会引发以下异常

raised ADA.IO_EXCEPTIONS.DATA_ERROR : a-tiinio.adb:89 instantiated at a-inteio.ads:18

我已经尝试接收一个字符,检查它是否是一个整数,然后将其转换为整数,但后来我意识到我需要得到大于1位整数的输入,所以字符方法将无法工作 .

如果我收到一个字符串,那么我无法检查它是否是一个整数(除非我扫描整个字符串以查看它的所有字符是否都是整数...)

除扫描整个字符串外还有其他解决方案吗?或者可能是一种异常处理技术,可能会阻止程序终止并再次询问正确的整数?

-CH

3 回答

  • 1

    几乎所有在Ada中将字符串解析为某种标量值的标准方法都会在读取无效字符串时产生某种异常 . 这没有任何问题 . 只需处理异常 .

    即使您编写了自己的字符串解析为整数例程,您也必须以某种方式处理用户输入无效字符串的情况 . 对?

    我想唯一涉及的是"technique"是你可以把异常处理程序放在子程序上,甚至是你在代码中内联的 declare ... begin ... end 块上 . 这样,只有块中的代码被中止 . 通常我更喜欢看到使用的子程序 . 所以你会得到类似的东西:

    function User_Integer return Integer is
    begin
        loop
            begin
                ada.integer_text_io.get(integer_variable);
                return integer_variable;
            exception
                when ADA.IO_EXCEPTIONS.DATA_ERROR =>
                    Ada.Text_IO.Put_Line ("Try a number from 1 to 3, Sherlock");
                    Print_Menu;
            end;
        end loop;
    end User_Integer;
    

    现在,就这种情况而言,对于快速而肮脏的Ada菜单,我通常不会像上面那样做数字菜单 . 而是,创建一个枚举类型 . 这样,您可以通过菜单类型循环使用 'image 打印菜单选项,当您使用 'valueAda.Text_IO.Enumeration_IO 时,Ada将处理文本解析 .

    type Menu_Selection_Option is (Eat, Drink, Sleep);
    package Menu_IO is new Ada.Text_IO.Enumeration_IO (Menu_Selection_Option);
    function User_Selection return Integer is
    begin
        loop
            declare
                Selection : Menu_Selection_Option;
            begin
                Menu_IO.Get(Selection);
                return Selection;
            exception
                when ADA.IO_EXCEPTIONS.DATA_ERROR =>
                    Ada.Text_IO.Put_Line ("Unrecognized option. Try again Sherlock");
                    Print_Menu;
            end;
        end loop;
    end User_Selection;
    

    关于这一点的好处是,当菜单选项列表发生变化时,您不必更改菜单打印代码或解析代码 .

  • 5

    用于请求此类用户输入的主要Ada编程习惯使用Get_Line:

    procedure Get_Line(Item : out String;   Last : out Natural);
    

    要么

    function Get_Line return String;
    

    既然用户的响应是在字符串中,您可以快速扫描非数字字符,或使用Integer'Value属性将其转换为整数(将调用包装在合适的异常处理程序中) . 例如:

    loop
       Put_Line("What do you want to do?");
       Display_Options;
       declare
          What_To_Do : Positive;
          Response : String(1..20);
          Last     : Natural;
       begin
          Get_Line(Response, Last);
          exit when Last = 0;
    
          What_To_Do := Integer'Value(Response(1 .. Last));  --' Buggy highlight fix
          Go_Do_Something(What_To_Do);
    
       exception
          when Data_Error =>
             Put_Line("Invalid response, try again...");
       end;
    end loop;
    

    这个成语的附加优点是你也可以接受非数字输入,例如Quit的'Q'或“Quit”;并且还可以进行任何可能需要的字符预处理,例如up-casing .

  • 4

    您可以在循环内处理异常,以便在输入整数之前重复请求输入,或者在结束时正常退出...

相关问题