Ада: Как управлять исключением Data_error при получении целых - PullRequest
2 голосов
/ 16 мая 2011

Я пытаюсь заставить пользователя выбрать режим из меню, например

  1. Ешь
  2. Drink
  3. Сон

Теперь я могу получить целочисленный ввод с помощью вызова

ada.integer_text_io.get(integer_variable);

Основная проблема здесь заключается в том, что если я вставлю нецифровую строку (например, строку символов), появится следующее исключение

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

Я пытался получить символ, проверить, является ли он целым числом, затем преобразовать его в целое число, но потом я понял, что мне нужно получить входные данные для целого числа, большего, чем 1 цифра, чтобы метод символа не работал .

Если я получаю строку, то я не могу проверить, является ли она целым числом или нет (если я не сканирую всю строку, чтобы увидеть, являются ли все ее символы целыми числами ...)

Есть ли другое решение, кроме сканирования всей строки? Или, возможно, метод обработки исключений, который может помешать программе завершиться и снова запросить правильное целое число?

-СН

Ответы [ 3 ]

5 голосов
/ 16 мая 2011

Практически все стандартные способы анализа строки в скалярное значение некоторого вида в Ada приведут к некоторому исключению, когда / если будет прочитана неверная строка.В этом нет ничего плохого.Просто обработайте исключение.

Даже если вы написали собственный разбор строк в целочисленных подпрограммах, вам придется каким-то образом обрабатывать ситуацию, когда пользователь вводит недопустимую строку.Правильно?

Полагаю, единственная задействованная "техника" заключается в том, что вы можете устанавливать обработчики исключений в подпрограммах или даже в 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;

Теперь, в этом случае для быстрых и грязных меню Ады я обычно не делаю числовые меню, как указано выше.Вместо этого создайте перечислимый тип.Таким образом, вы можете распечатать пункты меню, используя 'image в цикле по типу меню, и Ада будет обрабатывать анализ текста при использовании 'value или Ada.Text_IO.Enumeration_IO.

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;

NiceДело в том, что вам не нужно менять код печати меню или код синтаксического анализа при изменении списка параметров меню.

4 голосов
/ 16 мая 2011

Преобладающая идиома программирования 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;

Дополнительным преимуществом этой идиомы является то, что вы также можете принимать нечисловые вводы, такие как «Q» для «Выход» или «Выход»; а также выполнить любую предварительную обработку символов, например, использование заглавных букв, которые могут потребоваться.

1 голос
/ 16 мая 2011

Вы можете обработать исключение, либо в цикле, чтобы многократно запрашивать ввод, пока не будет введено целое число, либо ближе к концу, чтобы выйти изящно ...

...