Цикл for

Категория: Культура кода Автор: Дмитрий Ляпин Опубликовано: 29-08-2010

Метки: , , , , , ,

Примеры в статье приведены на языке Си

Достаточно давно мы опубликовали статью о тернарном операторе. Еще один шедевр, пришедший из языка Си, – цикл for.

Это мощнейшая конструкция, позволяющая организовать любой цикл. Например, можно обойтись без привычного while:

while (<условие>)
{
}

эквивалентно

for (; <условие>;)
{
}

Вот самый обычный пример, вывод на экран чисел от 1 до 100:

for (int i = 1; i <= 100; i++)
{
	printf("%d\r\n", i);
}

А вот пример сложнее (просьба не пугаться тем, кто не знаком с языком Си):

for (node_t* i = get_first(); i != NULL; i = get_next(i)) 
{
	printf("%d\r\n", get_value(i));
}

Это обход списка с помощью функций get_first(), get_next() и get_value().

  • get_first() – получить первый элемент списка; функция возвращает NULL, если список пуст
  • get_next(i) – получить элемент, следующий в списке за i; функция возвращает NULL, если i – последний элемент
  • get_value(i) – получить значение элемента i (в данном примере значение каждого элемента – целое число)
  • node_t – структура, описывающая элемент списка

Общий вид

for (A; B; C)
	D;

Конструкция for состоит из четырех частей:

  1. Инициализация (A)
  2. Условие (B)
  3. Действие после очередной итерации (C)
  4. Тело цикла (D)

Алгоритм

Шаг 1. Инициализация.
Шаг 2. Проверка условия; если истинно – переход к шагу 3; иначе – выход из цикла.
Шаг 3. Выполнения тела цикла.
Шаг 4. Выполнение действия после очередной итерации; переход к шагу 2.

Из Википедии я взял хорошую схему, иллюстрирующую написанный выше текст:

Зачем?

Может возникнуть вопрос – для чего нужен такой цикл? Ведь то же самое можно сделать с помощью более простой конструкции – цикла while:

for (A; B; C)
	D;

эквивалентно

A;
 
while (B)
{
	D;
	C;
}

Ответ лежит в сути циклического процесса. Чаще всего для организации цикла требуется специальная переменная, в самом простом случае – счетчик. Эту переменную нужно инициализировать и производить над ней действия после каждой итерации (например, увеличивать на единицу). Также, конечно, должно быть условие выхода из цикла. Оно может быть связано с этой самой специальной переменной, а может опираться и на другие факторы. Ну и, наконец, что-то нужно делать в самом цикле, то есть выполнять те самые полезные действия, ради которых программисту и потребовалась циклическая конструкция.

Например, если нам нужно вывести на экран числа от 1 до 100, то полезная операция – сам вывод; в то время, как увеличение счетчика на единицу – внутренняя операция организации цикла.

Цикл for позволяет отделить всю служебную часть цикла от самого повторяющегося процесса; резульат – естественность и легкость восприятия, чтения кода, ну и краткость (сестра таланта).

break, continue, return

Эти два оператора позволяют управлять циклическим процессом из самого тела цикла. break влечет мгновенный выход из цикла, continue – переход к следующей итерации (то есть к шагу 4). Кроме того, находясь внутри функции, можно выйти из цикла (равно, как и из самой функции) с помощью оператора return.

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

Когда я учился в университете, на лабараторках по Си преподаватель строго запрещал использовать break, continue и return в теле цикла. Это заставляет лучше продумывать алгоритм, сам цикл.

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

Запись

for ( ; ; )
{
	D;
}

эквивалентна

for ( ; true; )
{
	D;
}

Такой цикл будет выполняться бесконечно, ну или пока вы не прервете его с помощью break или return. Иногда бывает удобно использовать и такой вид.

Примеры

В завершение приведу несколько примеров на разных си-подобных языках.

JavaScript:

for ( ; ; )
{
	alert('Вам нравится моя домашняя страничка?');
}

Это бесконечный цикл, вряд ли вы посетите такую страничку снова.

PHP:

for ($i = 0; $i < count($pathes); $i++)
{
	if (file_exists($pathes[$i] . $fileName))
		return $pathes[$i] . $fileName;
}

Поиск файла по всем возможным путям (указанным в массиве $pathes). Удачный пример с выходом из цикла с помощью оператора return.

C#:

for (IEnumerator<int> it = list.GetEnumerator(); it.MoveNext(); )
{
	Console.WriteLine(it.Current);
}

Пример работы с итератором. Что это такое? Представьте, что в качестве счетчика используется не целочисленная переменная, а целый объект, обладающий набором свойств, имеющий определенное состояние. Так вот, это итератор. Подробнее напишу в другой статье.

А как вы используете цикл for?

Комментарии:

Оставить комментарий!