#exception #input #ada
#исключение #ввод #ada
Вопрос:
Я только начал изучать 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" amp; Score'Image (a));
else
Put_Line ("Bad range of input");
end if;
end Main;
Разве я не должен использовать «диапазон» для проверки ввода, а скорее некоторые if с>, < ограничениями?
Мой другой подход заключался в том, чтобы попробовать это с исключениями, но он также не работает так, как я хочу:
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" amp; Score'Image (a));
exit;
exception
when Ada.IO_Exceptions.Data_Error =>
Put_Line("Bad range of input");
end;
end loop;
end Main;
Я считаю, что проблема в моем непонимании этого языка, но я надеюсь, что для этого есть какое-то простое решение, спасибо за любую помощь.
Комментарии:
1. Посмотрите на отчет, когда программа завершается сбоем. Может ли быть так, что присвоение
a
вызывает Constraint_Error, но вы обрабатываете Data_Error ??2. Да, это Constraint_Error! Я изменил строку, проверяющую исключение, на
Ada.IO_Exceptions.Constraint_Error
, но теперь я получаю сообщение об ошибке, что Constraint_Error не объявлен в IO_Exceptions. Как я должен его включить?3. Это в системе, поэтому уже видно.
When Constraint_Error =>
4. Спасибо, я этого не знал, это решило мою проблему. Еще раз спасибо 🙂
5. @obeeey просто хотел добавить дополнительную информацию: значение ‘Valid полезно для проверки «непроверенных» операций, где диапазоны и ограничения не всегда проверяются. Как и при использовании Unchecked_Conversion, я склонен переносить свои вызовы в Unchecked_Conversion, чтобы затем вызвать ‘Valid впоследствии, чтобы убедиться, что я не ввел неверные данные. Ada достаточно хорош, чтобы перехватить его позже, но мне нравится улавливать проблемы в источнике, если это возможно.
Ответ №1:
Теперь вы знаете магическое заклинание, которое работает, но я сомневаюсь, что вы понимаете, почему оно работает или почему ваши другие заклинания не сработали. Я расскажу об этом в болезненных педагогических подробностях в надежде, что некоторые из них могут быть полезными или представлять интерес.
В Ada, когда вы объявляете тип, тип является анонимным, а имя ( Score
), которое вы указываете, является именем первого именованного подтипа. Подтип с первым именем может иметь ограничения, которые не применяются к анонимному базовому типу. Для некоторых типов, включая целочисленные типы, можно ссылаться на анонимный базовый тип с 'Base
помощью .
Поскольку вы объявили Score
using 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'
in From
(2).
HTH