Условия и ввод/вывод

Предпосылки: Переменные и типы (переменные, присваивание, примитивные типы).

Переменные и типы | Циклы

Программа из предыдущей заметки умеет хранить данные и считать. Но она всё ещё идёт по шагам без выбора: если в коде есть строка расчёта, она выполнится всегда. Для человека условие вроде «уволен пропустить расчёт» очевидно сразу. Для программы его нужно записать явно.

Ветвление: if и else

Ветвление позволяет выполнить один блок кода или другой в зависимости от условия:

status = "active"
 
if status == "active"
  puts "Считаем зарплату"
else
  puts "Пропускаем расчёт"
end

if проверяет условие. Если оно истинно, выполняется первый блок. Если ложно, выполняется блок после else.

Условие — это выражение, которое даёт true или false:

salary = 1500
bonus = 300
 
salary > 1000
bonus == 0
salary + bonus > 2000

== проверяет равенство. >, <, >=, <=, != сравнивают значения.

Составные условия

Одного сравнения часто мало. Нужно проверить несколько фактов сразу:

if status == "active" && salary > 0
  puts "Можно считать налог"
end

&& означает «и»: оба условия должны быть истинны. || означает «или»: достаточно одного. ! означает «не» и переворачивает результат:

if !is_fired || has_special_contract
  puts "Сотрудник получает выплату"
end

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

Несколько вариантов подряд

Если вариантов больше двух, используют elsif:

if salary > 5000
  tax_rate = 0.20
elsif salary > 2000
  tax_rate = 0.15
else
  tax_rate = 0.10
end

Проверка идёт сверху вниз. Как только найден первый подходящий вариант, остальные блоки пропускаются.

В ассемблере то же ветвление строилось из CMP и условных переходов. Здесь условие видно прямо в тексте, и читать его проще: не нужно помнить, что именно сравнивали в предыдущей строке и куда ведёт прыжок.

Ввод и вывод

Условия становятся полезнее, когда программа работает с внешними данными. Пока что мы записывали значения прямо в коде. Реальная программа получает данные от пользователя, из файла или из сети.

Вывод — показать результат человеку. В Ruby для этого используют puts (от put string — «вывести строку»):

puts "Итоговая зарплата: 1587"
puts salary

Ввод — прочитать данные от пользователя. В Ruby для этого используют gets (от get string — «получить строку»):

puts "Введите имя:"
name = gets
puts "Привет:"
puts name

После gets в строку попадает не только то, что напечатал пользователь, но и символ перехода на следующую строку — то, что Enter добавляет в конец. В коде этот символ записывается как \n. Пока это не мешает: важно увидеть сам факт, что программа может взять данные извне.

Теперь можно написать первую интерактивную программу:

puts "Статус сотрудника (active/fired):"
status = gets.chomp
 
if status == "active"
  puts "Считаем зарплату"
else
  puts "Расчёт не требуется"
end

chomp убирает служебный перевод строки из конца ввода, поэтому 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.

Переменные и типы | Циклы