问题描述
我刚刚开始学习Ada,当用户输入超出变量的声明范围时,我无法弄清楚如何保持程序运行。我想打印有关输入范围错误的信息,然后再次要求用户输入。
这是我的简单代码:
with Ada.Text_IO;
use Ada.Text_IO;
procedure Main is
type score is range 0..100;
a : score;
begin
Put_Line ("Enter value range 0-100: ");
a := score'Value(Get_Line);
if a'Valid then
Put_Line ("You entered" & score'Image (a));
else
Put_Line ("Bad range of input");
end if;
end Main;
我不是应该使用“范围”来检查输入,而是如果某些使用>,
我的另一种方法是尝试使用异常,但这也无法正常工作,
with Ada.Text_IO;
with Ada.IO_Exceptions;
use Ada.Text_IO;
procedure Main is
type score is range 0..100;
a : score;
begin
loop
begin
Put_Line ("Enter value range 0-100: ");
a := score'Value(Get_Line);
Put_Line ("You entered" & score'Image (a));
exit;
exception
when Ada.IO_Exceptions.Data_Error =>
Put_Line("Bad range of input");
end;
end loop;
end Main;
我认为问题是我缺乏对这种语言的了解,但是我希望对此有某种简单的解决方案,谢谢您的帮助。
解决方法
现在您知道一个神奇的咒语有效,但是我怀疑您是否理解它为什么起作用,或者您的其他咒语为何不起作用。我将对此进行详尽的教学细节,希望其中的一些有用或令人感兴趣。
在Ada中,当您声明类型时,该类型是匿名的,并且您提供的名称(Score
)是名字的子类型的名称。名字子类型可能具有不适用于匿名基本类型的约束。对于某些类型,包括整数类型,可以使用'Base
来引用匿名基类型。
自从您使用Score
声明了range
以来,它是一个带符号的整数类型,并且其基本类型(大约)对称于零。所以您的声明等同于
type Score'Base is range -128 .. 127;
subtype Score is Score'Base range 0 .. 100;
(这不是Ada,也不会编译)。
Score'Value
返回值Score'Base
(ARM 3.5 (53)),因此,如果输入"101"
或"-3"
,则Score'Value
将成功并返回适当的值。当您将该值分配给子类型Score
的变量时,将检查该值是否在Score
的范围内;如果失败,将引发Constraint_Error
。如果输入无效的图像,例如"200"
或"xyz"
,则Score'Value
会失败并引发Constraint_Error
。因此,您有两种错误的输入,会导致两种不同的失败,而这两种错误恰巧都会引发相同的异常。
您的第一个版本失败了,因为您从未接触过if
语句。您的第二个版本失败了,因为Ada.Text_IO.Get_Line
从不提高Data_Error
。
在处理数字输入时,我建议将整行读入字符串,然后像完成操作一样从该字符串中解析出值。但是,'Value
将拒绝您可能希望视为有效的某些输入。例如,您可能想要接受"23 skidoo"
并从中获取值23。为此,您可能想为数字(子)类型实例化Ada.Text_IO.Integer_IO
并使用带有Get
参数的String
函数:
package Score_IO is new Ada.Text_IO.Integer_IO (Num => Score);
...
Score_IO.Get (From => "23 skidoo",Item => A,Last => Last);
将A
设置为23,并将Last
设置为'3'
(2)中From
的索引。
HTH