Exception Ada:获取整数时如何管理数据错误异常

Exception Ada:获取整数时如何管理数据错误异常,exception,input,integer,ada,Exception,Input,Integer,Ada,例如,我试图让用户从菜单中选择一种模式 吃 喝 睡眠 现在我可以通过调用获取整数输入 ada.integer_text_io.get(integer_variable); 这里的主要问题是,如果我插入一个非数字字符串(如字符串),将引发以下异常 raised ADA.IO_EXCEPTIONS.DATA_ERROR : a-tiinio.adb:89 instantiated at a-inteio.ads:18 我尝试接收一个字符,检查它是否是整数,然后将其转换为整数,但后来我意识到我需要

例如,我试图让用户从菜单中选择一种模式

  • 睡眠
  • 现在我可以通过调用获取整数输入

    ada.integer_text_io.get(integer_variable);
    
    这里的主要问题是,如果我插入一个非数字字符串(如字符串),将引发以下异常

    raised ADA.IO_EXCEPTIONS.DATA_ERROR : a-tiinio.adb:89 instantiated at a-inteio.ads:18
    
    我尝试接收一个字符,检查它是否是整数,然后将其转换为整数,但后来我意识到我需要为大于1位的整数获取输入,所以character方法无法工作

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

    除了扫描整个字符串,还有其他解决方案吗? 或者是一种异常处理技术,它可以防止程序终止并再次请求一个正确的整数


    -CH

    您可以处理异常,或者在循环内重复请求输入直到输入整数,或者在结束时优雅地退出…

    请求此类用户输入的主要Ada编程习惯用法使用Get\u Line:

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

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

    循环
    放线(“你想做什么?”);
    显示选项;
    声明
    做什么:积极的;
    响应:字符串(1..20);
    最后:自然;
    开始
    获取_行(响应,最后一个);
    当Last=0时退出;
    做什么:=整数值(响应(1..Last));--小车高光修正
    去做某事(做什么);
    例外
    当数据错误=>
    放置行(“无效响应,请重试…”);
    结束;
    端环;
    

    这个习惯用法的另一个优点是,您也可以接受非数字输入,例如'Q'表示退出,或'Quit';还可以执行任何可能需要的字符预处理,如大小写。

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

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

    我想唯一涉及的“技术”是,您可以在子例程上,甚至在
    声明上放置异常处理程序。。。开始。。。结束内联放入代码中的块。这样,只有块中的代码被中止。一般来说,我更喜欢使用子程序。所以你会得到这样的结果:

    函数用户\u Integer返回整数为
    开始
    环
    开始
    ada.integer\u text\u io.get(integer\u变量);
    返回整数_变量;
    例外
    当ADA.IO_EXCEPTIONS.DATA_ERROR=>
    Ada.Text_IO.Put_Line(“尝试从1到3的数字,夏洛克”);
    打印菜单;
    结束;
    端环;
    最终用户_整数;
    
    现在,在这种情况下,对于快速和肮脏的Ada菜单,我通常不会像上面那样使用数字菜单。而是创建一个枚举类型。这样,您就可以通过菜单类型在循环中使用
    'image
    打印菜单选项,并且当您使用
    'value
    Ada.text\u IO.Enumeration\u IO
    时,Ada将处理文本解析

    类型菜单\选择\选项为(吃、喝、睡);
    软件包菜单IO是新的Ada.Text\u IO.Enumeration\u IO(菜单选择选项);
    函数用户_选择返回整数为
    开始
    环
    声明
    选择:菜单\选择\选项;
    开始
    菜单获取(选择);
    返回选择;
    例外
    当ADA.IO_EXCEPTIONS.DATA_ERROR=>
    Ada.Text_IO.Put_Line(“无法识别的选项。请重试Sherlock”);
    打印菜单;
    结束;
    端环;
    最终用户选择;
    

    这样做的好处是,当菜单选项列表更改时,您不必更改菜单打印代码或解析代码。

    Wow!我不知道你可以在一个循环中实现异常!!现在一切正常!令人惊叹的!非常感谢你!但是我需要在函数的循环中有另一个declare、begin和end吗?或者我可以省略declare和begin部分吗?哇!下次在Ada中编程时,我会记住枚举方法!谢谢也许我还停留在过去,但在处理控制台输入时,我总是对直接调用枚举或数值I/O包实例化的Get有点怀疑。过去的编译器在处理错误数据输入时“清除”交互式输入缓冲区的方式不一致。处理这种不一致性是Get_-Line/convert习惯用法在几年前建立的,因为所有Ada编译器似乎至少一致地处理Get_-Line。但最近这可能变得更好、更一致了。@HeartInPice-当异常处理程序运行时,它所在的块将终止。如果将异常处理程序放在函数级,则函数将在处理程序代码完成后结束(最好在其中包含
    return
    语句)。这不是您希望在这里发生的情况,因为这是一个错误条件,所以没有好的值可返回。所以,是的,很遗憾这里需要declare块。@Marc C-事实上,大体上我支持你。如果我是从头开始编码,我会使用Get_Line和Menu_Selection_Option的值而不是Enumeration_IO。主要原因是您可以用它做更复杂的事情(比如打印出用户在异常处理程序中给您的无效输入)。然而,这更接近OQ试图做的事情,它应该能工作
    function Get_Line return String;