Перейти к основному содержанию

9. Циклы

Цикл это конструкция, которая позволяет много раз выполнить некоторый код, до тех пор, пока не будет выполнено определенное условие.

В Rust есть 3 вида циклов: for, while, loop.

Цикл while (пока)

Цикл while выполняется до тех пор, пока истинно некое условие, которое вы задали.

Общий синтаксис:

 while condition {
	body_of_loop;
}

Т.е. пока условие выполняется, выполняем тело цикла. Выполнили, опять проверяем условие на соответствие.

Разумно применять цикл while, когда ваш код должен достичь какой-то цели, и после каждой итерации вы проверяете не достигнута ли цель, например:

fn main() {
	let mut n: i8 = 14;
	while n >= 0 {
		n -= 5;
		println!("{n}");
	}
}
Результат: 9 4 -1

Объявляем переменную n и присваиваем ей значение 14. В начале выполнения цикла проверяем, что n у нас неотрицательное число. Далее выполняем тело цикла, в котором уменьшаем n на 6. Снова проверяем условие и выполняем цикл до тех пор пока n не станет отрицательным. Цикл выполнился 3 раза, n получило значение -1

Бесконечный цикл

Бывает, что нам необходим бесконечный цикл, например, когда наша программа считывает нажатия клавиатуры и реагирует на них. Мы можем организовать такой цикл с помощью конструкции while true {}. Но это как-то не идеально, поэтому в Rust есть специальный бесконечный цикл.

Бесконечный цикл loop (петля)

Общий синтаксис:

loop {
    body_of_loop;
}

Если вы запустите следующий пример, то сразу нажимайте клавиши Ctrl_F2 или красный квадратик остановки программы (в Pycharm). Иначе, цикл будет выполняться бесконечно.

fn main() {
	let mut v = 1;
	loop {
		v = v + 1;
		println!("{}", v);
	}
}

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

Выход из цикла оператором break

Break означает прекращение.

Находясь внутри любого из циклов (while, loop, for) мы можем прервать его выполнение и перейти к следующему блоку кода. Обычно проверяется некоторое условие и после того, как произойдет запланированное событие, вызывается оператор break.

fn main() {
	let mut x = 0;
	loop {
		x += 1;
		println!("{}", x);
		if x == 999 {break}
	}
}

Когда x достигнет значения 999, при проверке этого факта командой break прервется выполнение цикла.

Прерывание исполнения цикла continue

Оператор continue (продолжение), находящийся внутри цикла, пропускает выполнение последующих операторов в теле цикла и возвращает в начало цикла.

В этом примере мы распечатываем числа от 1 до 15, но хотим пропустить число 13:

fn main() {
	let mut x = 0;
	while x < 15 {
		x += 1;
		if x == 13 {continue}
		println!("{}", x);
	}
}

Макрос println! будет пропущен один раз и наша последовательность не будет содержать 13.

Continue также применимо для любого из циклов (while, loop, for)

Цикл for

И в цикле while и в цикле loop компилятор не может знать сколько раз выполнится цикл. Соответственно, они называются неопределенными. В отличии от них цикл for это определенный цикл. В нем заранее известно количество итераций.

Используя цикл for вы заранее определяете некий итерируемый список или объект по элементам которого будет проходить цикл. Например:

fn main() {
	for i in 0..5 {
		print!("{} ", i);
	}
}
Результат: 0 1 2 3 4

Дословный перевод: Для переменной i, принимающей значения от 0 до 5 не включительно, выполнить код в скобках {}.

Здесь переменная i принимает по порядку значения от нуля до 4 из указанного диапазона.

Обратите внимание. Из указанного диапазона первое число включается, а последнее исключается!

Достичь того же результата можно используя другое обозначение диапазона: for i in 0..=4 {}.

Общий синтаксис цикла for:

for variable in range {
    body_of_loop;
}

Цикл for удобен когда нам нужно произвести определенное количество итераций, причем в вычислениях мы можем использовать и переменную цикла. И диапазон мы можем указать произвольный, например, от 5 до 9.

Реверс цикла

Иногда нам требуется пройти цикл с конца до начала. Изменение диапазона in 5..0 не сработает, цикл не выполнится ни разу. Для прохождения цикла в обратном порядке существует полезный метод .rev().

fn main() {
	for i in (0..5).rev() {
		print!("{} ", i);
	}
}
Результат: 4 3 2 1 0

Цикл for с методом enumerate

Ещё больше возможностей цикл for дает при использовании метода .enumerate(). Мы можем использовать не только переменную, которая принимает значения из указанного диапазона, но и порядковый номер итерации. Простой пример:

fn main() {
	for (count, variable) in (7..10).enumerate() {
		println!("Итерация: {}, переменная = {}", count, variable);
	}
}
Результат: Итерация: 0, переменная = 7 Итерация: 1, переменная = 8 Итерация: 2, переменная = 9

Особенно полезен будет этот метод, когда мы начнем изучать более сложные объекты, которые могу итерироваться: массивы и векторы.

Нюанс по именованию переменных

Допустим, вы написали цикл for i in 0..9 {} просто для выполнения 9 итераций, а сама переменная i не будет нужна. Компилятор это пропустит, но напишет предупреждение. В таком случае можно поставить перед переменной символ подчеркивания _i или даже заменить i на символ подчеркивания _. Ваш цикл с безымянной переменной будет выглядеть так: for _ in 0..9 {}.

Для просмотра заданий и решений, а также публикации своих решений необходимо зарегистрироваться на сайте.

Всё бесплатно, мы просто хотим с вами познакомиться и понять насколько актуально то, что мы делаем.

© Клют И. А., 2022. Копирование контента возможно только с письменного разрешения автора.