Урок 5. Циклы for и while, диапазоны
Цикл повторяет команды несколько раз: вывести числа от 1 до 100, сложить всё введённое, ждать правильного ответа. В Kotlin два основных цикла: for — по заранее известному набору значений, и while — пока верно условие.
for и диапазоны
fun main() {
for (i in 1..3) {
println("Step $i")
}
}Step 1
Step 2
Step 31..3 — диапазон от 1 до 3 включительно. Цикл for (i in 1..3) по очереди кладёт в переменную i каждое число диапазона и выполняет тело цикла. Переменную i объявлять заранее не нужно, и val или var перед ней не пишут.
Диапазоны бывают разные. Чтобы увидеть, какие числа в них входят, удобно превратить диапазон в список — toList():
fun main() {
println((1..5).toList())
println((0 until 5).toList())
println((0..<5).toList())
println((1..10 step 2).toList())
println((10 downTo 1).toList())
println((10 downTo 1 step 3).toList())
println((5..1).toList())
println(('a'..'e').toList())
}[1, 2, 3, 4, 5]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[1, 3, 5, 7, 9]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[10, 7, 4, 1]
[]
[a, b, c, d, e]| Запись | Что значит |
|---|---|
1..5 | от 1 до 5, обе границы входят |
0 until 5 или 0..<5 | от 0 до 4 — правая граница не входит |
1..10 step 2 | с шагом 2: 1, 3, 5, 7, 9 |
10 downTo 1 | обратный отсчёт от 10 до 1 |
5..1 | пустой диапазон — цикл не выполнится ни разу |
Последняя строка — частая ошибка: для счёта назад нужен downTo, а не ...
until удобен для номеров элементов: в списке из 5 элементов номера от 0 до 4, то есть 0 until 5.
Сумма в цикле
Типичная задача — сложить числа от 1 до n:
fun main() {
val n = readln().toInt()
var sum = 0
for (i in 1..n) {
sum += i
}
println(sum)
}1005050Переменная sum объявлена через var до цикла: в цикле она меняется, а после него нужна для вывода.
Перебор строки
for перебирает не только числа, но и символы строки:
fun main() {
val word = "banana"
var count = 0
for (c in word) {
if (c == 'a') {
count++
}
}
println(count)
}3Так же for перебирает элементы списков — об этом в уроке Коллекции.
while
while повторяет тело, пока условие верно. Условие проверяется перед каждым повтором:
fun main() {
var n = 1
while (n < 100) {
n *= 2
}
println(n)
}128Число удваивается: 1, 2, 4, …, 64, 128. При 128 условие n < 100 становится неверным, и цикл заканчивается.
Если условие while никогда не станет неверным, цикл будет крутиться бесконечно, и программа зависнет. Проверьте, что в теле цикла меняется то, от чего зависит условие. Остановить зависшую программу в IntelliJ IDEA — красный квадрат в окне Run, в командной строке — Ctrl+C.
do-while
do { ... } while (условие) сначала выполняет тело, а потом проверяет условие — тело выполнится хотя бы один раз. Удобно для ввода: читать числа, пока не введут 0:
fun main() {
var sum = 0
do {
val x = readln().toInt()
sum += x
} while (x != 0)
println(sum)
}5
3
10
018Переменная x объявлена внутри тела, но в условии while она видна — в Kotlin так можно.
repeat
Если нужно просто повторить действие несколько раз, а номер повтора не важен, есть repeat:
fun main() {
repeat(3) {
println("Hi")
}
}Hi
Hi
Hibreak и continue
break— немедленно выйти из цикла;continue— пропустить остаток тела и перейти к следующему повтору.
fun main() {
for (i in 1..10) {
if (i % 3 == 0) continue
if (i > 7) break
println(i)
}
}1
2
4
5
7Числа 3 и 6 пропущены через continue. На 8 сработал break, и цикл закончился, до 9 и 10 дело не дошло.
Вложенные циклы и метки
Цикл можно поставить внутрь другого. break во внутреннем цикле выходит только из него. Чтобы выйти сразу из обоих, внешнему циклу дают метку — имя со знаком @:
fun main() {
outer@ for (i in 1..5) {
for (j in 1..5) {
if (i * j == 12) {
println("$i * $j = 12")
break@outer
}
}
}
}3 * 4 = 12break@outer выходит из цикла с меткой outer. Без метки программа вывела бы ещё 4 * 3 = 12.
Чего в Kotlin нет
Привычного по C и Java цикла for (int i = 0; i < n; i++) в Kotlin нет. Его заменяют диапазоны:
| C, Java | Kotlin |
|---|---|
for (i = 0; i < n; i++) | for (i in 0 until n) |
for (i = 1; i <= n; i++) | for (i in 1..n) |
for (i = n; i >= 1; i--) | for (i in n downTo 1) |
for (i = 0; i < n; i += 2) | for (i in 0 until n step 2) |
Коротко
for (i in 1..n)— от 1 до n включительно;0 until nи0..<n— без n;step— шаг;downTo— назад.5..1— пустой диапазон: для обратного отсчёта нуженdownTo.while (условие)— пока условие верно;do { } while ()— хотя бы один раз.repeat(n) { }— повторить n раз.break— выход из цикла,continue— к следующему повтору,break@метка— выход из внешнего цикла.