Циклы while и for
При написании скриптов зачастую встаёт задача сделать однотипное действие много раз.
Например, вывести товары из списка один за другим. Или просто перебрать все числа от 1 до 10 и для каждого выполнить одинаковый код.
Для многократного повторения одного участка кода предусмотрены циклы.
Циклы for…of и for…in
Небольшое объявление для продвинутых читателей.
В этой статье рассматриваются только базовые циклы: while , do..while и for(..;..;..) .
Если вы пришли к этой статье в поисках других типов циклов, вот указатели:
- См. for…in для перебора свойств объекта.
- См. for…of и Перебираемые объекты для перебора массивов и перебираемых объектов.
В противном случае, продолжайте читать.
Цикл «while»
Цикл while имеет следующий синтаксис:
while (condition) < // код // также называемый "телом цикла" >
Код из тела цикла выполняется, пока условие condition истинно.
Например, цикл ниже выводит i , пока i < 3 :
let i = 0; while (i < 3) < // выводит 0, затем 1, затем 2 alert( i ); i++; >
Одно выполнение тела цикла по-научному называется итерация. Цикл в примере выше совершает три итерации.
Если бы строка i++ отсутствовала в примере выше, то цикл бы повторялся (в теории) вечно. На практике, конечно, браузер не позволит такому случиться, он предоставит пользователю возможность остановить «подвисший» скрипт, а JavaScript на стороне сервера придётся «убить» процесс.
Любое выражение или переменная может быть условием цикла, а не только сравнение: условие while вычисляется и преобразуется в логическое значение.
Например, while (i) – более краткий вариант while (i != 0) :
let i = 3; while (i) < // когда i будет равно 0, условие станет ложным, и цикл остановится alert( i ); i--; >
Фигурные скобки не требуются для тела цикла из одной строки
Если тело цикла состоит лишь из одной инструкции, мы можем опустить фигурные скобки :
let i = 3; while (i) alert(i--);
Цикл «do…while»
Проверку условия можно разместить под телом цикла, используя специальный синтаксис do..while :
do < // тело цикла >while (condition);
Цикл сначала выполнит тело, а затем проверит условие condition , и пока его значение равно true , он будет выполняться снова и снова.
let i = 0; do < alert( i ); i++; >while (i < 3);
Такая форма синтаксиса оправдана, если вы хотите, чтобы тело цикла выполнилось хотя бы один раз, даже если условие окажется ложным. На практике чаще используется форма с предусловием: while(…) .
Цикл «for»
Более сложный, но при этом самый распространённый цикл — цикл for .
Выглядит он так:
for (начало; условие; шаг) < // . тело цикла . >
Давайте разберёмся, что означает каждая часть, на примере. Цикл ниже выполняет alert(i) для i от 0 до (но не включая) 3 :
for (let i = 0; i < 3; i++) < // выведет 0, затем 1, затем 2 alert(i); >
Рассмотрим конструкцию for подробней:
часть | ||
---|---|---|
начало | let i = 0 | Выполняется один раз при входе в цикл |
условие | i < 3 | Проверяется перед каждой итерацией цикла. Если оно вычислится в false , цикл остановится. |
тело | alert(i) | Выполняется снова и снова, пока условие вычисляется в true . |
шаг | i++ | Выполняется после тела цикла на каждой итерации перед проверкой условия. |
В целом, алгоритм работы цикла выглядит следующим образом:
Выполнить начало → (Если условие == true → Выполнить тело, Выполнить шаг) → (Если условие == true → Выполнить тело, Выполнить шаг) → (Если условие == true → Выполнить тело, Выполнить шаг) → .
То есть, начало выполняется один раз, а затем каждая итерация заключается в проверке условия , после которой выполняется тело и шаг .
Если тема циклов для вас нова, может быть полезным вернуться к примеру выше и воспроизвести его работу на листе бумаги, шаг за шагом.
Вот в точности то, что происходит в нашем случае:
// for (let i = 0; i < 3; i++) alert(i) // Выполнить начало let i = 0; // Если условие == true → Выполнить тело, Выполнить шаг if (i < 3) < alert(i); i++ >// Если условие == true → Выполнить тело, Выполнить шаг if (i < 3) < alert(i); i++ >// Если условие == true → Выполнить тело, Выполнить шаг if (i < 3) < alert(i); i++ >// . конец, потому что теперь i == 3
Встроенное объявление переменной
В примере переменная счётчика i была объявлена прямо в цикле. Это так называемое «встроенное» объявление переменной. Такие переменные существуют только внутри цикла.
for (let i = 0; i < 3; i++) < alert(i); // 0, 1, 2 >alert(i); // ошибка, нет такой переменной
Вместо объявления новой переменной мы можем использовать уже существующую:
let i = 0; for (i = 0; i < 3; i++) < // используем существующую переменную alert(i); // 0, 1, 2 >alert(i); // 3, переменная доступна, т.к. была объявлена снаружи цикла
Пропуск частей «for»
Любая часть for может быть пропущена.
Для примера, мы можем пропустить начало если нам ничего не нужно делать перед стартом цикла.
let i = 0; // мы уже имеем объявленную i с присвоенным значением for (; i < 3; i++) < // нет необходимости в "начале" alert( i ); // 0, 1, 2 >
Можно убрать и шаг :
let i = 0; for (; i
Это сделает цикл аналогичным while (i < 3) .
А можно и вообще убрать всё, получив бесконечный цикл:
При этом сами точки с запятой ; обязательно должны присутствовать, иначе будет ошибка синтаксиса.
Прерывание цикла: «break»
Обычно цикл завершается при вычислении условия в false .
Но мы можем выйти из цикла в любой момент с помощью специальной директивы break .
Например, следующий код подсчитывает сумму вводимых чисел до тех пор, пока посетитель их вводит, а затем – выдаёт:
let sum = 0; while (true) < let value = +prompt("Введите число", ''); if (!value) break; // (*) sum += value; >alert( 'Сумма: ' + sum );
Директива break в строке (*) полностью прекращает выполнение цикла и передаёт управление на строку за его телом, то есть на alert .
Вообще, сочетание «бесконечный цикл + break » – отличная штука для тех ситуаций, когда условие, по которому нужно прерваться, находится не в начале или конце цикла, а посередине или даже в нескольких местах его тела.
Переход к следующей итерации: continue
Директива continue – «облегчённая версия» break . При её выполнении цикл не прерывается, а переходит к следующей итерации (если условие все ещё равно true ).
Её используют, если понятно, что на текущем повторе цикла делать больше нечего.
Например, цикл ниже использует continue , чтобы выводить только нечётные значения:
for (let i = 0; i < 10; i++) < // если true, пропустить оставшуюся часть тела цикла if (i % 2 == 0) continue; alert(i); // 1, затем 3, 5, 7, 9 >
Для чётных значений i , директива continue прекращает выполнение тела цикла и передаёт управление на следующую итерацию for (со следующим числом). Таким образом alert вызывается только для нечётных значений.
Директива continue позволяет избегать вложенности
Цикл, который обрабатывает только нечётные значения, мог бы выглядеть так:
for (let i = 0; i < 10; i++) < if (i % 2) < alert( i ); >>
С технической точки зрения он полностью идентичен. Действительно, вместо continue можно просто завернуть действия в блок if .
Однако мы получили дополнительный уровень вложенности фигурных скобок. Если код внутри if более длинный, то это ухудшает читаемость, в отличие от варианта с continue .
Нельзя использовать break/continue справа от оператора „?“
Обратите внимание, что эти синтаксические конструкции не являются выражениями и не могут быть использованы с тернарным оператором ? . В частности, использование таких директив, как break/continue , вызовет ошибку.
Например, если мы возьмём этот код:
if (i > 5) < alert(i); >else
…и перепишем его, используя вопросительный знак:
(i > 5) ? alert(i) : continue; // continue здесь приведёт к ошибке
…то будет синтаксическая ошибка.
Это ещё один повод не использовать оператор вопросительного знака ? вместо if .
Метки для break/continue
Бывает, нужно выйти одновременно из нескольких уровней цикла сразу.
Например, в коде ниже мы проходимся циклами по i и j , запрашивая с помощью prompt координаты (i, j) с (0,0) до (2,2) :
for (let i = 0; i < 3; i++) < for (let j = 0; j < 3; j++) < let input = prompt(`Значение на координатах ($,$)`, ''); // Что если мы захотим перейти к Готово (ниже) прямо отсюда? > > alert('Готово!');
Нам нужен способ остановить выполнение, если пользователь отменит ввод.
Обычный break после input лишь прервёт внутренний цикл, но этого недостаточно. Достичь желаемого поведения можно с помощью меток.
Метка имеет вид идентификатора с двоеточием перед циклом:
labelName: for (. )
Вызов break в цикле ниже ищет ближайший внешний цикл с такой меткой и переходит в его конец.
outer: for (let i = 0; i < 3; i++) < for (let j = 0; j < 3; j++) < let input = prompt(`Значение на координатах ($,$)`, ''); // если пустая строка или Отмена, то выйти из обоих циклов if (!input) break outer; // (*) // сделать что-нибудь со значениями. > > alert('Готово!');
В примере выше это означает, что вызовом break outer будет разорван внешний цикл до метки с именем outer .
Таким образом управление перейдёт со строки, помеченной (*) , к alert('Готово!') .
Можно размещать метку на отдельной строке:
outer: for (let i = 0; i
Директива continue также может быть использована с меткой. В этом случае управление перейдёт на следующую итерацию цикла с меткой.
Метки не позволяют «прыгнуть» куда угодно
Метки не дают возможности передавать управление в произвольное место кода.
Например, нет возможности сделать следующее:
break label; // не прыгает к метке ниже label: for (. )
Директива break должна находиться внутри блока кода. Технически, подойдет любой маркированный блок кода, например:
label: < // . break label; // работает // . >
…Хотя в 99.9% случаев break используется внутри циклов, как мы видели в примерах выше.
К слову, continue возможно только внутри цикла.
Итого
Мы рассмотрели 3 вида циклов:
- while – Проверяет условие перед каждой итерацией.
- do..while – Проверяет условие после каждой итерации.
- for (;;) – Проверяет условие перед каждой итерацией, есть возможность задать дополнительные настройки.
Чтобы организовать бесконечный цикл, используют конструкцию while (true) . При этом он, как и любой другой цикл, может быть прерван директивой break .
Если на данной итерации цикла делать больше ничего не надо, но полностью прекращать цикл не следует – используют директиву continue .
Обе этих директивы поддерживают метки, которые ставятся перед циклом. Метки – единственный способ для break/continue выйти за пределы текущего цикла, повлиять на выполнение внешнего.
Заметим, что метки не позволяют прыгнуть в произвольное место кода, в JavaScript нет такой возможности.
Циклы. While, do while, for, чем отличаются?
while - выполняется пока заданное выражение правда (проверка перед одним циклом выполнения)
while do - выполняется пока заданное выражение правда (проверка после одного цикла выполнения)
for - создано для выполнения кода n-ное количество раз
Вообще недавно видел забавную картинку, которая хорошо это дело демонстрирует
Спойлер
Ярослав Иванов @space2pacman
Rikonardo, ну вы то че))while и do while одинаковые. Разница в том что последний запускает тело цикла без проверки на первой итерации.
Ярослав Иванов, ну по крайней мере нам на курсах c# рассказали, что do while проводит проверку после пробега кода внутри (итерации), а while сначала проверяет, а потом выполняет
Ярослав Иванов @space2pacman
Rikonardo, все верно) только это на первых итерациях. Потом они идентичны)
while, do while, for
Прошу объяснить понятными определениями..
Решения вопроса 1
Программист на «си с крестами» и не только
While — сначала проверь, потом сделай, и так по кругу.
Do — сначала сделай, потом проверь, и так по кругу.
Отличаются они только случаем, когда условие не выполняется: while не пройдёт, а do пройдёт один раз.
// Пример 1. // верно while (впереди свободно) шаг; // неверно — можно врезаться в препятствие, если нельзя сделать ни шагу do шаг while (впереди свободно); // Пример 2. // Неверно — пока у вас в руках нет рубашки, условие цикла некорректно while (рубашка грязная) возьми рубашку; // верно do возьми рубашку; while (рубашка грязная);
Циклы for, foreach и прочие — это разновидность цикла while (не do!!), сделанная для специального сценария: пройти некий набор объектов.
Ответ написан более трёх лет назад
Комментировать
Нравится 5 Комментировать
Ответы на вопрос 4
Учим yii: https://youtu.be/-WRMlGHLgRg
Слишком очевидный ответ, если посмотреть на примеры: www.php.su/learnphp/cs/?cycles
Допустим у Вас есть коробочка в которой хранятся бутылочки с "пивасиком" и бутылочки с "молоком"
Если Ваш батя попросил протереть все бутылки из коробочки - это foreach
Если каждую бутылку, пока в коробке не закончится пивасик - это while
Если каждую бутылку, пока протертых бутылок с пивасиком станет 4 - это тоже while
Если каждую бутылку, пока в коробке не закончится пивасик, но раз уж взял бутылку последнюю с молоком, то будь любезен протри - это do-while
Если с 3-й по 12-ю - это for
Если только с молоком - это мамка, а не батя
Ответ написан более трёх лет назад
Нравится 10 3 комментария
Ярослав Иванов @space2pacman
Аналогия с пивасиком как раз ему зайдёт))) только надо ещё разбавить нецензурными словами.
Вы, учитель года :))
iMaximus, видимо нет, автор просил для детей 3-х лет, я старался. А ответами он отметил варианты 18+, со всякими взрослыми словечками 🙂
Вообще, эти три цикла взаимозаменяемы, т.е. если есть программа, написана с помощью одного из них, то она всегда может быть переписана с помощью любого другого. Но по правилам хорошего стиля и для удобства рекомендации следующие:
for используется, когда число итераций известно (есть переменная или константа, которая определяет это количество).
while и do-while используются, когда число итераций заранее неизвестно.
while используется, когда существует возможность, что цикл не выполнится ни разу, а do-while следует использовать, если известно, что как минимум одна итерация всегда требуется.
Для примера:
for - выведите N чисел на экран (N определяет число итераций).
while - алгоритм Евклида для вычисления НОД (если одно из чисел 0, то итераций не будет)
do-while - реализация игры "Угадай число". (всегда требуется хотя бы одна попытка, то точное их число неизвестно).
Ответ написан более трёх лет назад
Комментировать
Нравится 4 Комментировать
Test automation engineer
Нам в школе так обьяснили:
while - в зависимости от условия тело цикла может быть не выполнено ни разу.
do while - тело цикла будет выполнено минимум один раз.
ну а for - будет выполняется для выбраных элементов последовательности (какие это будут элементы - указывается в условии). Тут можно задать периодичность, например, для каждого второго элемента.
Ответ написан более трёх лет назад
Комментировать
Нравится 3 Комментировать
Как - то, почитал я ответы коллег, и остался разочарован. Понятно, что вопрос не простой, а очень простой, но можно и по аккуратнее в изложении. В общем, мои 5 копеек.
Любой цикл - это кусок кода, который обычно называют телом цикла, и который мы желаем выполнить несколько раз. Количество повторений может быть заданно заранее, например: цикл от 0 до 10, зависеть от данных, например: для каждого элемента массива или зависеть от значения, которое мы в теле цикла вычисляем, например: пока f(x) > 0 выполнять. По крайней мере, во всех известных мне языках программирования, есть оператор досрочного выхода из цикла.
while. Цикл с предварительным условием. Выполняется пока условие истинно. Проверка происходит до исполнения тела цикла. Если условие изначально ложно, то тело не выполнится ни разу. Если условие ни когда не станет ложным, то мы получим бесконечный цикл. Распространенные ошибки новичков, при использовании этого цикла:
- условие не зависит от переменных, которые изменяются в теле цикла, и оно всегда получается истинным
- условие ни когда не станет ложным, в силу его свойств, например: X * X >= 0 всегда верно
Пример на php:
$i = 1; while ($i
do . while. Цикл с постусловием. Отличие от предыдущего в том, что тело цикла исполняется хотя бы один раз, и после этого происходит проверка условия выхода из цикла. К типичным ошибкам предыдущего вида циклов добавляется то, что этот цикл гарантированно исполняется один раз, что не всегда желательно.
В этом примере цикл отработает один раз, не смотря на то, что условие ложно:
$i = 0; do < echo $i; >while ($i > 0);
for. Чаще всего этот оператор описывает цикл с фиксированным количеством повторений. Вот так он может выглядеть, например, для php:
for ($i = 1; $i
но есть языки, где этот - же оператор используется для описания цикла, перебирающего множество значений, например элементы массива. К возможным подводным камням этого вида циклов следует отнести порчу значения счетчика итераций. Изменять его, например для досрочного выхода из цикла, считается плохим стилем программирования, и в особо тяжелых случаях может приводить к трудно диагностируемым ошибкам.
Различия между циклами for и while
В цикле for i in range(n) в переменную i будет поочередно записываться каждое значение из диапазона range(n) , например:
In [1]: for i in range(3): . print(i) . 0 1 2
Сначала i принимает значение 0 , затем 1 , и так пока не дойдем до n .
Также циклом for можно пройтись по любому итерабельному объекту, например:
In [4]: array = [1, 2, 3] In [5]: for i in array: . print(i)
В переменную i поочередно будет записаны значения из списка array .
In [2]: i = 0 In [3]: while i < 3: . print(i) . i += 1 . 0 1 2
На каждой итерации мы проверяем меньше ли переменная i чем 3 , если это так, то выводим значение переменной i и прибавляем к ней единицу, повторяем это пока проверка на i < 3 не вернёт False . Мы по сути говорим, пока что-то истинно, то выполняй какие то действия.
Помните пример с циклом for когда мы проходили по списку? С while дело обстоит иначе, нам нужно вытягивать из списка элементы по их индексам, т.е в условие будет выглядеть так: while i < len(array) , функция len(iterable) вернёт нам кол-во элементов в списке, на примере того же array :
In [6]: i = 0 In [7]: while i < len(array): . print(array[i]) . i += 1
Чтобы определить бесконечный цикл while , нужно указать такое условие, которое всегда истинно, например while True .
С циклом for все сложнее, бесконечный цикл явно указать нельзя, так как цикл for закончит свою работу тогда, когда пройдет по всем элементам объекта, следовательно нужно ему передать такой объект, в котором бесконечно элементов, тут нам помогут генераторы, говорить о них детально я не буду, так как тема довольно обширная, лишь покажу небольшой пример с модулем itertools :
In [11]: from itertools import count In [12]: for i in count(): . print(i) # 1, 2, 3, 4 .
Таким образом мы определили бесконечный цикл for , count также принимает 2 необязательных аргумента, start число с которого начнём итерацию, и step собственно шаг.
Тут Вы можете найти немного задачек на циклы для практики.
Чем отличается FOR от WHILE?
Привет всем. Только начал изучать PHP. В учебнике идет 2 подряд описания кода программы, которая выводит одно и тоже, но с разными циклами.
'; $number++; > ?>
В чем разница как выводить, если результат один? Или я чего-то не понимаю?
- Вопрос задан более трёх лет назад
- 11872 просмотра
1 комментарий
Оценить 1 комментарий
Immortal_pony @Immortal_pony Куратор тега PHP
В копилку вариантов:
foreach (range(0, 9) as $i) < echo "Вывод строки. 10 раз
"; >
Решения вопроса 1
В чем разница как выводить, если результат один?
- for(буквально "для") - применяется когда нужно что-то выполнить в определенном диапазоне. то есть на человеческом языке это будет звучать примерно как: "для такого диапазона мы делаем что-то".
- while(буквально "пока") - применяется когда нужно что-то выполнять неопределенное кол-во раз до выполнение конкретного условия. то есть на человеческом языке это будет звучать примерно как: "делать что-то пока не выполнится условие".
Ответ написан более трёх лет назад
Нравится 7 5 комментариев
BadassRolf @BadassRolf Автор вопроса
Спасибо, что разъяснили. Теперь стало понятней.
У вас нет более понятного учебника? А то по которому я учусь что-то подводит.
abbrakadabbra @abbrakadabbra
DevMan возможно ошибаюсь, но в while при неправильном условии легко попасть на бесконечный цикл, в то же время в for этого не произойдет. Повторяю, возможно ошибаюсь, но такое у меня не раз получалось именно с while.