Условия и ввод/вывод
Предпосылки: Переменные и типы (переменные, присваивание, примитивные типы).
← Переменные и типы | Циклы →
Маркетплейс: менеджер открывает карточку продавца и хочет понять, можно ли проводить выплату. У продавца есть имя, баланс и признак блокировки:
name = "Alice"
balance = 1580
blocked = falseПрограмма из предыдущей заметки умеет хранить эти три значения и считать. Но выплату нужно проводить не всегда: заблокированному продавцу переводить нельзя, продавцу с нулевым балансом — бессмысленно. Для человека правило «если заблокирован — пропустить» очевидно сразу. В коде его нужно записать явно.
Ветвление: if и else
if позволяет выполнить один блок кода или другой в зависимости от условия:
if blocked
puts "Продавец заблокирован, выплата отменена"
else
puts "Можно проводить выплату"
endЕсли blocked истинно, выполняется первый блок. Иначе — блок после else. puts здесь печатает строку в терминал, чтобы менеджер увидел решение; подробнее — в разделе «Ввод и вывод» ниже.
Условие — это выражение, которое даёт true или false. У нас переменная blocked уже логическая, поэтому её можно поставить прямо в if. Но чаще условие — это сравнение:
balance > 0
balance == 0
name != ""== проверяет равенство. >, <, >=, <=, != сравнивают значения. Результат такого сравнения — true или false, то самое, что if умеет различать.
Составные условия
Одного сравнения часто мало. Менеджер хочет проводить выплату, только если продавец активен и баланс положителен:
if !blocked && balance > 0
puts "Можно проводить выплату"
else
puts "Выплата невозможна"
end&& означает «и»: оба условия должны быть истинны. || означает «или»: достаточно одного. ! означает «не» и переворачивает результат. !blocked читается как «не заблокирован».
Составные условия удобно строить, комбинируя все три операции. Например, если у маркетплейса есть VIP-продавцы, которым разрешено уходить в минус до -500, правило можно записать так:
vip = true
if !blocked && (balance > 0 || vip && balance > -500)
puts "Можно проводить выплату"
endСкобки здесь задают порядок проверки, как в арифметике.
Несколько вариантов подряд
Пока что менеджер видел два ответа — «можно» и «нельзя». В жизни причин отказа несколько, и хочется показывать точную:
if blocked
puts "Продавец заблокирован"
elsif balance == 0
puts "Нулевой баланс, выплачивать нечего"
elsif balance < 0
puts "Отрицательный баланс, сначала пополнение"
else
puts "Можно проводить выплату"
endelsif позволяет перечислить несколько взаимоисключающих случаев. Проверка идёт сверху вниз. Как только найден первый подходящий вариант, остальные блоки пропускаются — и это важно: если продавец заблокирован, программа уже не будет смотреть на баланс, потому что первая ветка закрыла вопрос.
В ассемблере то же ветвление строилось из CMP и условных переходов. Здесь условие видно прямо в тексте, и читать его проще: не нужно помнить, что именно сравнивали в предыдущей строке и куда ведёт прыжок.
Ввод и вывод
До сих пор значения name, balance и blocked были записаны прямо в коде. Но карточку продавца менеджер открывает не ту, что автор придумал заранее. Программа должна уметь получать данные извне — от пользователя, из файла, из сети — и возвращать результат наружу.
Вывод — показать результат человеку. В Ruby для этого используют puts (от put string — «вывести строку»):
puts "Итоговый баланс: 1580"
puts balanceВ терминале появится две строки: сначала готовый текст, потом число из переменной.
Ввод — прочитать данные от пользователя. В Ruby для этого используют gets (от get string — «получить строку»). Менеджер вводит имя продавца, а программа обращается к нему по имени:
puts "Имя продавца:"
name = gets
puts "Карточка: "
puts nameПосле gets в переменную попадает не только то, что напечатал пользователь, но и символ перехода на следующую строку — тот самый, что Enter добавляет в конец. В коде этот символ записывается как \n. Если просто напечатать name, это почти не видно, но при попытке сравнить такую строку с чем-то подобная мелочь ломает всё. Представим, что менеджер вводит статус продавца:
puts "Статус (active/blocked):"
status = gets
if status == "active"
puts "Продавец активен"
else
puts "Продавец неактивен или неизвестен"
endМенеджер вводит active, жмёт Enter — и видит «неактивен». Причина в том, что в status лежит не "active", а "active\n". Условие status == "active" честно возвращает false: строки разные.
Лекарство — метод chomp, который отрезает служебный перевод строки с конца ввода:
puts "Статус (active/blocked):"
status = gets.chomp
if status == "active"
puts "Продавец активен"
else
puts "Продавец неактивен или неизвестен"
endТеперь в status лежит ровно "active", сравнение срабатывает, менеджер получает правильный ответ. Дальше такую же очистку ввода делают почти всегда, пока это не становится привычкой.
Карточка продавца замкнулась: данные пришли через ввод, условие выбрало нужную ветку, результат ушёл на вывод.
А теперь менеджер хочет проверить не одного продавца, а всех сразу — тысячу карточек подряд, одинаковой логикой. Писать тысячу копий if вручную не вариант. Нужен способ сказать коду: «повтори эту проверку для каждого». Этим занимаются циклы.
Sources
- Thomas, D. et al., 2023, Programming Ruby 3.3. Pragmatic Bookshelf.
- Sammet, J., 1969, Programming Languages: History and Fundamentals. Prentice-Hall.
← Переменные и типы | Циклы →