Обработка пользовательского ввода — КиберПедия 

Адаптации растений и животных к жизни в горах: Большое значение для жизни организмов в горах имеют степень расчленения, крутизна и экспозиционные различия склонов...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

Обработка пользовательского ввода

2022-09-29 31
Обработка пользовательского ввода 0.00 из 5.00 0 оценок
Заказать работу

 

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

Чтобы лучше понять, как Crystal работает с типами, давайте встроим
код для чтения ввода в ту самую программу, посвященную валюте
и ее относительным курсам обмена. Начнем с чтения целых чисел в массив. Вы можете найти полный исходный код в "getting_input.cr". Консоль позволяет "подбирать" входные данные, но в Playground такого нет. Чтобы это сработало, вам нужно напечатать в терминале (ИКС):

  crystal getting_input.cr

Итак, пользователь отправляет числа, а вы ожидаете, что они будут меньше 256 (в этом случае они соответствуют типу Int8):

 

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

 # "Вводите числа одно за другим, и закончите ввод пустой строкой:"

  arr = [] of Int8

 

Вы начнете с пустого массива, так как вам надо обозначить тип "[ ] of Int8". Есть и другие способы, чтобы указать тип содержимого массива, например, заполнение массива данными при инициализации:

   arr1 = [75, 42, 126]

typeof(arr1) # => Array(Int32)

 

Почему тип определился как 'Int32', когда все эти числа меньше 127? Int32 является целочисленным типом, устанавливаемым по умолчанию. Если вы хотите установить тип Int8 — допустим, в целях повышения производительности — вы должны прописать это явным образом, примерно так:

   arr1 = [75_i8, 42_i8, 126_i8]

   typeof(arr1) # => Array(Int8)

 

(Crystal предлагает суффиксы i8, i16, i32, i64 для положительных и отрицательных целых чисел, и u8, u16, u32, u64 для беззнаковых
целых чисел.) Вы читаете с консоли с помощью gets, которая возвра-
щает все, что она читает, в виде String. Вы можете отобразить вводи-
мые в консоли данные, воспользовавшись внутристроковой вставкой.

  puts "Enter a number:"

num = gets

p "You entered #{num}" # => "You entered 42"

Давайте добавим число в наш массив:

  arr1 << num

Crystal не позволит вам сделать это:

 Error: no overload matches 'Array(Int8)#<<' with type (String | Nil)

 

Теперь уже это должно восприниматься как нечто знакомое. Лучший способ выяснить, что пошло не так, это протестировать тип "num"
(первый комментарий из предыдущей некорректной строки). Вы
можете сделать это двумя способами:

  p typeof(num) # => (String | Nil)

  p num.class # => String

 

Вы видите, что Crystal делает различие между двумя понятиями:

• Тип на стадии компиляции: какой тип видит компилятор, он зада-
ется с помощью «typeof».

• Тип времени выполнения: какой тип объект имеет, когда программа уже запущена; и он определяется методом "class".

 

Кроме того, nil не может быть добавлен к массиву целых чисел. Но почему компилятор считает, что ввод может быть нулем (nil)? Ну
ладно, вместо ввода числа введите "CTRL+D" и посмотрите, что происходит: Тип данных для num — это Nil! Но метод '<<' не может
быть применен к нулю (nil). Вам следует остерегаться такого нулевого ввода.

Есть несколько способов сделать это. Поскольку nil противопоставлен "истине", самое простое — тестирование условным оператором if:

  if num

  arr << num

  end

 

Мы пока не закончили, потому что теперь мы получаем еще одну ошибку:

«no overload matches 'Array(Int8)#<<' with type String»

 

Компилятор теперь знает, что num соответствует строковому (String) типу, но массив может содержать только Int8. Настало время преобразовать входные данные с помощью to_i8:

  if num

  arr << num.to_i8

  p arr # => for example: [42]

  end

 

Теперь Crystal преобразует строку в 8-битное целое число со знаком
(+-). Даже если строка содержит числа (т.е. арабские цифры), то да-
лее возможно несколько вариантов развития событий. Присутствие десятичной запятой приведет к ошибке, как и целые числа за
пределами диапазона от -127 до 128. Нечисловые знаки нарушат это преобразование, как именно — будет рассмотрено ниже в этой главе.

Кроме того, if работает для одиночного пользовательского ввода. Мы
не знаем, сколько чисел будет отправлено, поэтому нам потребуется
цикл. И while подходит идеально: gets самолично возвращает значение, которое может быть проверено как состояние while. Если это значение
не "ноль" или "ложь" (false), то while срабатывает нормально и
добавляет содержимое num в массив.

 

  while num = gets

  arr << num.to_i8

  p arr # => for example: [2, 3, 3, 5]

  end

Запомните, только nil, false или нулевые указатели считаются в Crystal ложными в любом логическом показателе или в выражениях if, unless, while и until. Любое другое значение — включая строку "false" и число 'ноль' — распознается как истина при тестировании выражений.

 

▪ Сокращайте выражения ▪

 

Основанное на правилах истинности\ложности выражение "a ||= b", которое является сокращенной формой для "a || (a = b)", используется
для присвоения b переменной a лишь в том случае, когда a равно нулю:

    mem = nil

    mem ||= 1

    mem  # 1

    mem ||= "Crystal"

    mem  # 1

 

Это обычно используется в "memoization", что означает способность запечатлеть (задержать в памяти) результаты вычислений; в нашем слу-чае возвращается значение 'a', когда 'a' не равно нулю, но в противном случае возвращается b.

 

 

Возвращаясь к нашему вводу, давайте удалим все символы пробела с помощью strip, на всякий случай. Чтобы завершить цикл, проверим, вводит ли пользователь "stop" или просто ENTER, а затем прервем
цикл (break):

while num = gets

  num = num.strip # removes whitespace

  if num == "" || num == "stop"

break

  end

arr << num.to_i8

 end

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

 

▪ read_line ▪

Если тестирование после gets показало, что ввод, не являясь нулевым (отличается от nil), не выглядит элегантно, вы можете также исполь-
зовать метод "read_line". Пользуйтесь им — упражнение read_line.cr показывает, как это сделать.

 


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

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...

Кормораздатчик мобильный электрифицированный: схема и процесс работы устройства...

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



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

0.016 с.