Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

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

Обработка исключений при некорректном вводе

2022-09-29 63
Обработка исключений при некорректном вводе 0.00 из 5.00 0 оценок
Заказать работу

Вверх
Содержание
Поиск

Конечно, здорово собрать внешний ввод для вашей программы, но иногда эти входные данные могут создавать новые проблемы. Вы,
наверное, знаете слоган "Мусор внутрь, мусор наружу": неправильный ввод может испортить всю дальнейшую обработку. Пользуясь нашим предыдущим примером, предположим, что пользователь вводит строку, такую как "abc", когда программа ожидает целое число; иначе говоря, строку, которая не может быть преобразована в целое число. Что
случится тогда?

Что-то ужасное: ошибка во время выполнения или исключительная ситуация (ЧП). Как и профессиональным программистам, вам надлежит избегать этого любой ценой.

  <= Invalid Int8: abc (ArgumentError)

 0x451477: *CallStack::unwind:Array(Pointer(Void)) at??

0x465a92: to_i8 at /opt/crystal/src/string.cr 358:5

...

Вы всегда должны остерегаться «опасного» ввода. Лучший способ управиться с этим — сделать простой тест "to_i8?", чтобы увидеть, начинается ли строка с допустимого числа. Если нет, тестовая про-
верка возвращает ноль (nil):

  if num.to_i8?

arr << num.to_i8

else

puts "Input is not an integer."

  end

Теперь вы получите замечательное сообщение об ошибке, и никаких отказов во время выполнения! (Как и в Ruby, в Crystal есть соглашение,
что методы с именами, оканчивающимися на "?", возвращают ноль (nil), если ничего не найдено.) Если ошибочность такова, что вам желательно остановить программу с помощью собственного сообщения об ошибке, используйте "raise":

  if num.to_i8?

arr << num.to_i8

else

raise "Input is not an integer."

  end

 

Применение этой техники к нашему конвертеру валют дает нам следующее:

types_and_control_flow/curr_conv2.cr

if rate.to_f?

rates[curr] = rate.to_f

else

puts "rate is no decimal number"

  end

 

Используя элементарный "puts", эту программу не остановить. Альтернативой будет использование begin-rescue, механизма для обработки исключительных ситуаций:

 

types_and_control_flow/getting_input_exception.cr

puts "Enter the numbers one by one, and end with an empty line:"

  arr = [] of Int8

while number = gets

number = number.strip # removes leading or trailing whitespace

if number == "" || number == "stop"

break

  end

begin

arr << number.to_i8

rescue

puts "integer bigger than 255"

  end

 end

p arr # => for example: [78, 56, 12]

 

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

Выполнение обработчика исключений, подобного этому, влечет за
собой резервирование оперативной памяти, и обычно это происходит медленно, как в ЯП Java или Ruby. Вам лучше попытаться избежать
этого с помощью простых тестов, таких как "to_i?" или даже "to_f?",
если возможно.

Если вам действительно необходимо использовать begin-rescue, минимизируйте количество кода между begin и rescue, чтобы избе-
жать и чрезмерного потребления памяти, и потенциально сложной логики. Используйте исключения только для исключительных слу-
чаев, но не для ожидаемых событий!

Как и в Ruby, этот механизм может также иметь ветви "else" и
"ensure". И в rescue вы можете использовать объект исключения "ex":

 

  begin

  # some dangerous code here

  # possibly your own raise "..."

rescue ex

  # execute if an exception is raised

p ex.message

else

  # execute if an exception isn't raised

ensure

  # this will always be executed

puts "Cleanup..."

end

 

Сцепливание методов

По-видимому, вам нравится красивый код — в противном случае вы
бы не продолжали чтение этой книги. Преобразование данных часто требует предсказуемой последовательности методов. Одна из прелестей языка Crystal в том, что вы можете соединять несколько методов в
цепочку для создания более удобочитаемого кода. Метод может быть вызван для любого объекта, относительно которого он определен, и этот объект может быть результатом другого вызова какого-то метода.

Взгляните на следующие примеры:

types_and_control_flow/chaining.cr

 result = (42..47).to_a # => [42, 43, 44, 45, 46, 47]          (1)

 .sort { |n, m| m <=> n } # => [47, 46, 45, 44, 43, 42]     (2)

 .reject { |n| n.odd? } # => [46, 44, 42]                     (3)

 .map { |n| n * n } # => [2116, 1936, 1764]                  (4)

 .select { |n| n % 4 == 0 } # => [2116, 1936, 1764]            (5)

 .tap { |arr| puts "#{arr.inspect}" } # => [2116, 1936, 1764]       (6)

 .sort! # => [1764, 1936, 2116]                                       (7)

 .any? { |num| num > 2000 } # => true                                (8)

 

 1) Диапазон преобразуется в массив с "to_a".

 2) Массив сортируется в обратном порядке (< = > это оператор сравнения).

 3) Все нечетные числа исключаются с помощью "reject".

 4) Функция "map" принимает другую функцию в качестве аргумента, чтобы возвести все элементы в квадрат.

 5) Выбираются все числа, делящиеся на 4.

 6) Метод "tap" касание передает объект в блок и возвращает его — полезно для отладки или сжатия кода.

 7) Массив сортирует себя.

 8) Проверка функцией "any?" содержит ли массив число больше 2000.

 

 

Вы также имеете в своем распоряжении "reduce", который накапливает результат выполнения вычислений над элементами коллекции, в приведенном ниже случае — сумму (sum) всех чисел массива arr:

types_and_control_flow/chaining.cr

sum = (42..47).to_a

.reduce(0) { |sum, num| sum + num }

# => 267 (= 42 + 43 +... + 47)

Метод reduce привносит функциональный подход в математические вычисления, производимые в Crystal.

Вы можете именовать свои методы в той самой манере, характерной для ЯП Ruby:

• Методы, которые заканчиваются на "!" (вроде sort!), по условию изменяют объект, для которого они вызваны. (Обычно метод "pp!" показывает более полное выражение, чем "pp".)

• Методы, которые заканчиваются на "?" (такие как any?), задают логический вопрос и возвращают true или false.

 


Поделиться с друзьями:

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...



© cyberpediasu.com 2017-2026 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.012 с.