Kotlin для початківців: Основи — Цикли та Рекурсія
Архів
22 листопада 2022 р.7 хв читанняВостаннє оновлено 11.01.2026Kotlin для початківців
Цикли та Рекурсії
Тепер же, перейдемо до досить цікавої, але, знову ж, трішки непростої теми — цикли.
Щоб більше зрозуміти, що таке цикли, створім якесь завдання. Наприклад, візьмемо завдання, яке ми вирішували у минулій темі.
Для того, щоб розв'язати рівняння з використанням введення, ми щоразу запускаємо нашу програму.
А що, якщо зробити в нашій програмі нескінченне введення, щоб щоразу не перезапускати нашу програму?
Взагалі, без нашої теми циклів це цілком можна було вирішити наступним чином:
kotlin
fun main() {
println("Введіть число:")
val input: Double = readln().toDouble()
println("Результат: " + input.toString())
return main() // в кінці функції просто викликаємо її ще раз
}
І ось, рішення знайдено!
Подібне називають рекурсією. Простими словами - це поняття оголошення (напису, опису) коду функції через саму себе.
Це як матрьошка, яка в нашому випадку не має кінця.
Що ж, а як тепер завершити нашу програму? Можна, звичайно, це зробити, закривши примусово процес програми через
інструменти системи або IDE, але давайте будемо людьми й зробимо якийсь механізм виходу.
Щоб сильно не морочитися, введемо умову, що для виходу з програми нам потрібно написати «:q».
kotlin
fun main() {
println("Введіть число: (або скористуйтесь :q для виходу):")
val input: String = readln() // створюємо змінну з текстом, тому що нам потрібно перевіряти введення користувача
if(input != ":q") {
val input: Double = input.toDouble() // сила областей видимості!
println("Результат: " + f(input).toString())
main()
}
}
Це так само залишиться рекурсією, тільки вже не нескінченною (у нас з'явилася умова).
Що ж, розглянувши досить простий приклад рекурсії, до якого можна було прийти самому під час спроби розв'язати завдання
з перезапуском рішення рівнянь.
Що тоді таке цикли?
ℹ️ Визначення
Цикли - це засоби мови, які відтворюють рекурсію. Їх також відносять до операторів, називаючи циклічними операторами.
Тож тепер розглянемо, як це можна вирішити іншими засобами мови. Не завжди ж ви створюватимете окремо функції для
'повторення чогось', так?
While
Для полегшення вам життя вигадали досить корисну конструкцію -
while.
Записується так:kotlin
while(boolean) {
// тут дія, що повторюється
}
Подібна конструкція виконує свій вміст у
{}, але перед кожним виконанням дивиться в умову (aka boolean-вираз)
і якщо там true, то зміст виконується, а якщо false - ні.Наш попередній код можна виразити через
while наступним чином:kotlin
fun main() {
var shouldRun: Boolean = true
while(shouldRun) {
println("Введіть число (або скористайтесь :q для виходу):")
val input: String = readln()
if(input == ":q") {
shouldRun = false // при наступному виконанні цикл побачить, що умова `false`
} else {
val input: Double = input.toDouble()
println("Результат: " + f(input).toString())
}
}
}
Ось і наш перший цикл! Але якийсь він складний, вам не здається?
Все це можна спростити скориставшись спеціальними додатковими операторами:
break та continue.Що роблять ці два оператори? Розберімось.
- •
break(можна перекласти як розірвати, обірвати) – примусово закінчує цикл. Тобто навіть якщо умова будеtrueцикл все одно закінчиться. - •
continue(перекладається як продовжити) - закінчує виконання поточного повторення. На відміну відbreak,continue, грубо кажучи, виходить з коду (код після нього не виконується) і переходить відразу до наступного повторення (до перевірки умови та подальшого повторення у разі, якщо тамtrue).
Давайте перепишемо наш код:
kotlin
fun main() {
while(true) { // умова нам не потрібна
println("Введите число (або скористайтесь :q для виходу):")
val input: String = readln()
if(input == ":q") {
break // виходимо з цикло
} else {
val input: Double = input.toDouble()
println("Результат: " + f(input).toString())
continue // взагалі, він необов'язковий у нашому випадку, але для наочності додамо
println("Я не надрукуюсь!") // IDE нам підкаже, що до цієї ділянки коду ми ніколи не дійдемо через continue
}
}
}
Через непотрібність ми викинули змінну
shouldRun, тому що є куди зручніший спосіб з break.Do-while
Одним із підвидів циклу while є
do-while. Крім назви, він відрізняється тим, що в do while спочатку
виконується тіло циклу, а потім перевіряється умова продовження циклу. Через таку особливість do while називають
циклом з постумовою, а звичайний while називають циклом з передумовою.Записується так:
kotlin
do {
// щось
} while(bool)
У такому циклі також існує
break та continue, які ніяк не відрізняються.
Однак, наше завдання можна вирішити через do-while і без них:kotlin
// створимо змінну з повідомленням, щоб потім її перевикористовувати
val numberInputMessage = "Введите число (или :q для выхода):"
// створимо окрему функцію для зручності
private fun requestInput(message: String): String {
println(message)
return readln()
}
fun main() {
var input = requestInput(numberInputMessage)
do {
println("Результат: " + f(input.toDouble()).toString())
input = requestInput(numberInputMessage) // записуємо наступне введення, щоб перевірити після повторення, що було введено
} while(input != ":q") // якщо введення не ":q" програма продовжуватиме працювати
}
Ми створили для зручності функцію та змінну, що поєднувала схожий код. Знову зробили змінну поза циклом і запис
її в кінці циклу (для того, щоб перевіряти після повторення введення користувача).
Це альтернативне рішення, хоч і не найкраще.
For
І тепер перейдемо до не менш важливого виду циклів -
for.
Відмінність цього виду циклів у тому, що він будується не за умови, а на ітераторі.
Що таке ітератор? Ітератор - це вбудована утиліта в мову, яка проходить між якоюсь сумою елементів.
Тобто кожне повторення буде відповідати одному елементу у цій сумі.
У нашому випадку, ця сума елементів буде відповідати діапазону, а елемент — одиниці рахування цього діапазону.Що таке діапазон? Простими словами - інтервал значень будь-якої величини.
Прикладом діапазону може бути [0; 5] (описує інтервал чисел від 0 до 5, включно).
Бувають різні види діапазонів, але поки що ми розглянемо найпростіший варіант із діапазоном цілих чисел.
Як створити такий цикл? Для початку розглянемо прогресію з цілими числами:
kotlin
for(i in 0..5) {
println(i)
}
Тут ми бачимо оператор
in, який працює з ітератором (у нашому випадку, з тим, що його виражає - діапазоном).Цей код надрукує наступне:
plaintext
0
1
2
3
4
5
Досить очевидно працює, чи не так?
Вирішім наступне завдання:
ℹ️ Завдання
Відтворіть функцію степеня для позитивних чисел. Еквівалентно функціїInt.pow(x: Double).
kotlin
fun pow(number: Int, times: Int): Int {
var output = number // створюємо змінну, де зберігається помножене значення
for(i in 1..times) { // через діапазон вказуємо, скільки разів має цикл повторитись
output *= number // множимо те, що вже є, на параметр number
}
return output // повертаємо число в степені
}
Тут нам IDE підкаже, що ідентифікатор не використовується і його бажано замінити на
_.
Річ у тому, що в котліні за код-стилем прийнято, що ідентифікатори, що не використовуються, називають саме так.Що ж до завдання, тут нескладний імперативний варіант рішення.
Вирішім ще одне завдання:
ℹ️ Завдання
Напишіть програму, де користувач вводить будь-яке ціле позитивне число. А програма підсумовує всі числа від 1 до введеного користувачем числа. Тобто, якщо введуть число 4, ми маємо підсумовувати такі числа: 1+2+3+4.
У цьому нам дуже допоможуть діапазони!
kotlin
fun sum(input: Int): Int {
var output: Int = 0 // створюємо тимчасову змінну, що буде зберігати значення, що змінюється в циклі
for(i in 1..input)
output += i // можна прибрати `{}`, бо тут одна послідовність дій
return output
}
Ми створили тимчасову змінну і знову використали діапазони зі змінною
i,
що містить елемент інтервалу цього діапазону на кожну ітерацію (повторення) циклу
(який і відповідає тому, що ми по суті й робимо).І наостанок, вирішимо ще одне завдання:
ℹ️ Завдання
Дані натуральні числа від 1 до 50. Знайти суму з них, які діляться на 5 чи 7.
💡 Згадайте
Перед розв'язанням цієї задачі, згадаємо один з арифметичних операторів -%(залишок від поділу).kotlinfun main() { println(22 % 4) println(4 % 2) }Надрукує2і0, оскільки буде такий залишок після поділу (у першому не ділиться націло, у другому - ділиться).
Наше завдання полягає в тому, щоб знайти числа, що діляться націло на 5 та 7.
Це буде еквівалентно наступному:
kotlin
number % 5 == 0 || number % 7 == 0
Ця умова нам підходитиме. Тепер же залишається тільки зробити цикл та тимчасову змінну в яку ми додаватимемо результат.
kotlin
fun main() {
var temp: Int = 0
for(i in 1..50)
if(i % 5 == 0 || i % 7 == 0)
temp += i
println("Сума: " + temp)
}
Відповіддю у нас має вийти:
436.Kotlin для початківців
Вам також може сподобатися
7 хв читання
Kotlin для початківців: Структури даних — Абстракції
Ускладнимо завдання: у нас є притулок з домашніми тваринами, і нам потрібно зберігати уніфіковану інформацію про кожну тварину.
Читати нотатку
2 хв читання
Kotlin для початківців: Основи — Висновок
У цій частині курсу ми розглянули чимало базових тем, які є вже досить вагомим фактором у вивченні як і котліну, так і інших мов.
Читати нотатку