Поведение различается между строкой # to_i и ядром # Integer
Причина, по которой ваш обработчик исключений никогда не вызывается, заключается в том, что String # to_i не вызывает исключение, даже если оно может 'обнаружить правильное целое число в объекте String.В таких случаях он просто возвращает 0
.
. Для сравнения, поведение Kernel # Integer более сложное, но ожидается, что оно вызовет ArgumentError или TypeError, если содержимое строкине строго соответствовать числовому представлению.
Таким образом, чтобы минимально реорганизовать существующий код, чтобы вызвать исключение для нечисловых входных данных:
begin
print 'Enter something: '
x = Integer gets
rescue => err
# Do something other than just print err on STDERR, which is the
# default behavior anyway. Perhaps send it to STDOUT instead.
puts "I received an exception: #{err}"
# After handling, re-raise the original exception with or without
# passing the original exception object. `raise` and `raise err`
# will do the same thing here.
raise
# For more advanced uses, you can also do something else like raise
# a different exception (e.g. TypeError), or modify the exception
# object stored in err and raise that modified object instead.
end
Следующие пользовательские входные данные будут преобразованы чисто:
Код будет обрабатывать даже начальные / конечные пробелы,переводы строк и возврат каретки в большинстве случаев без каких-либо дополнительных усилий с вашей стороны.Однако:
Введите что-то: один
ArgumentError: недопустимое значение для Integer (): "one \ n"
Введите что-то: "1"
ArgumentError: недопустимое значение для Integer (): "\" 1 \ "\ n"
Введите что-то: nil
ArgumentError: недопустимое значение для Integer (): "nil \ n"
В общем, вы можете использовать ядро # Integer для полученияисключение, когда это необходимо, что значительно упрощает ваш код.Тем не менее, см. Предостережения ниже.
Предостережения
В этих примерах это не требуется, но вы можете также при необходимости очистить ввод с помощью #strip, #chomp или других строковых преобразований.Ваш пробег в этом отношении будет сильно различаться в зависимости от вашего реального варианта использования, но, хотя Kernel # Integer обычно делает правильные вещи, а Ruby рекомендует полагаться на исключения для обработки нестандартных крайних случаев, зачастую неразумно доверять вводимым пользователем данным.
Стоит также отметить, что как String # to_i, так и Kernel # Integer могут работать со значениями, отличными от пользовательского ввода, в этом случае известно, что Integer(nil)
повысит значение:
Integernil
TypeError: невозможно преобразовать nil в целое число
Это может быть важно.Опять же, ваш пробег может отличаться.