C Language
Итерационные выражения / Циклы: для, пока, делать-пока
Поиск…
Синтаксис
- / * все версии * /
- for ([выражение]; [выражение]; [выражение]) one_statement
- for ([выражение]; [выражение]; [выражение]) {нуль или несколько операторов}
- while (выражение) one_statement
- while (выражение) {нуль или несколько утверждений}
- делать one_statement while (выражение);
- делать {одно или несколько утверждений} while (выражение);
- // с C99 в дополнение к форме выше
- for (declaration; [expression]; [expression]) one_statement;
- for (declaration; [expression]; [expression]) {zero или несколько операторов}
замечания
Итерационное заявление / Петли подразделяются на две категории:
- управляемый итерацией оператор / петли
- управление итерацией с педалью / петлями
Заглавие итерации с управляемой головой / петли
for ([<expression>]; [<expression>]; [<expression>]) <statement>
while (<expression>) <statement>
for ([declaration expression]; [expression] [; [expression]]) statement
Операция итерации с педальным управлением / петли
do <statement> while (<expression>);
Для цикла
Чтобы снова выполнить блок кода заново, на изображение попадают петли. Цикл for
должен использоваться, когда блок кода должен выполняться фиксированное количество раз. Например, чтобы заполнить массив размером n
с помощью пользовательских входов, нам нужно выполнить scanf()
для n
раз.
#include <stddef.h> // for size_t
int array[10]; // array of 10 int
for (size_t i = 0; i < 10; i++) // i starts at 0 and finishes with 9
{
scanf("%d", &array[i]);
}
Таким образом, вызов функции scanf()
выполняется n
раз (10 раз в нашем примере), но записывается только один раз.
Здесь переменная i
является индексом цикла, и ее лучше всего объявить как представленную. Тип size_t
( тип размера ) должен использоваться для всего, что подсчитывает или пересекает объекты данных.
Этот способ объявления переменных внутри for
доступен только для компиляторов, которые были обновлены до стандарта C99. Если по какой-то причине вы все еще придерживаетесь более старого компилятора, вы можете объявить индекс цикла перед циклом for
:
#include <stddef.h> /* for size_t */
size_t i;
int array[10]; /* array of 10 int */
for (i = 0; i < 10; i++) /* i starts at 0 and finishes at 9 */
{
scanf("%d", &array[i]);
}
Пока цикл
В while
цикл используется для выполнения фрагмента кода в то время как условие истинно. В while
цикл должен быть использован , когда блок кода должен быть выполнен переменное число раз. Например, показанный код получает пользовательский ввод, если пользователь вставляет числа, которые не равны 0
. Если пользователь вставляет 0
, условие while больше не является истинным, поэтому выполнение завершает цикл и переходит к следующему коду:
int num = 1;
while (num != 0)
{
scanf("%d", &num);
}
Цикл Do-While
В отличии от for
и в while
петли, do-while
петли проверить истинность условия в конце цикла, что означает , что do
блок будет выполняться один раз, а затем проверить состояние while
в нижней части блока. Это означает, что цикл do-while
while всегда запускается хотя бы один раз.
Например, этот цикл do-while
while будет получать числа от пользователя, пока сумма этих значений больше или равна 50
:
int num, sum;
num = sum = 0;
do
{
scanf("%d", &num);
sum += num;
} while (sum < 50);
петли do-while
относительно редки в большинстве стилей программирования.
Структура и поток управления в цикле for
for ([declaration-or-expression]; [expression2]; [expression3])
{
/* body of the loop */
}
В for
цикла, условие цикла имеет три выражения, все по желанию.
- Первое выражение, выражение
declaration-or-expression
, инициализирует цикл. Он выполняется ровно один раз в начале цикла.
Это может быть либо объявление, либо инициализация переменной цикла, либо общее выражение. Если это объявление, область действия объявленной переменной ограничена оператором for
.
Исторические версии C допускают только выражение, здесь и объявление переменной цикла должно быть помещено перед for
.
- Второе выражение,
expression2
, является условием проверки . Он выполняется сначала после инициализации. Если условиеtrue
, тогда элемент управления входит в тело цикла. Если нет, то он сдвигается за пределы тела цикла в конце цикла. Впоследствии этот conditon проверяется после каждого выполнения тела, а также оператора обновления. Когдаtrue
, управление возвращается к началу тела цикла. Условие обычно предназначено для проверки количества циклов, выполняемых телом цикла. Это основной способ выхода из цикла, другой способ использования операторов перехода . - Третье выражение,
expression3
, является оператором обновления . Он выполняется после каждого выполнения тела цикла. Он часто используется для увеличения переменной, поддерживающей подсчет количества раз, когда тело цикла выполнялось, и эта переменная называется итератором .
Каждый экземпляр выполнения тела цикла называется итерацией .
Пример:
for(int i = 0; i < 10 ; i++)
{
printf("%d", i);
}
Выход:
0123456789
В приведенном выше примере выполняется первое i = 0
, инициализирующее i
. Затем проверяется условие i < 10
, которое считается true
. Элемент управления входит в тело цикла и печатается значение i
. Затем управление переходит к i++
, обновляя значение i
от 0 до 1. Затем условие снова проверяется, и процесс продолжается. Это продолжается до тех пор, пока значение i
станет равным 10. Тогда условие i < 10
оценивает значение false
, после чего элемент управления выходит из цикла.
Бесконечные петли
Цикл называется бесконечным циклом, если элемент управления входит, но никогда не покидает тело цикла. Это происходит, когда тестовое условие цикла никогда не оценивается как false
.
Пример:
for (int i = 0; i >= 0; )
{
/* body of the loop where i is not changed*/
}
В приведенном выше примере переменная i
, итератор инициализируется равным 0. Условие испытания первоначально true
. Однако i
не изменяется нигде в теле, и выражение update пусто. Следовательно, i
останется 0, и условие теста никогда не будет оцениваться как false
, что приведет к бесконечному циклу.
Предполагая, что нет инструкций перехода, другой способ, которым может быть сформирован бесконечный цикл, заключается в явном сохранении условия true:
while (true)
{
/* body of the loop */
}
В цикле for
оператор условия необязателен. В этом случае условие всегда true
пусто, что приводит к бесконечной петле.
for (;;)
{
/* body of the loop */
}
Однако в некоторых случаях условие может сохраняться true
намеренно, с намерением выйти из цикла с помощью инструкции перехода, например break
.
while (true)
{
/* statements */
if (condition)
{
/* more statements */
break;
}
}
Прокрутка Loop и устройство Duff
Иногда прямая петля не может полностью содержаться внутри тела цикла. Это связано с тем, что цикл должен быть загружен некоторыми операторами B. Затем итерация начинается с некоторых операторов A , которые затем следуют за B перед циклом.
do_B();
while (condition) {
do_A();
do_B();
}
Для того, чтобы избежать возможных проблем вырезать / вставить с повторяющимися B дважды в коде, устройство Дафф может быть применен , чтобы начать цикл от середины в while
тело, с помощью переключателя заявление и провалиться поведения.
switch (true) while (condition) {
case false: do_A(); /* FALL THROUGH */
default: do_B(); /* FALL THROUGH */
}
Устройство Duff было изобретено для развертывания цикла. Представьте, что вы применяете маску к блоку памяти, где n
- тип подписанного интеграла с положительным значением.
do {
*ptr++ ^= mask;
} while (--n > 0);
Если n
всегда делится на 4, вы можете легко развернуть это:
do {
*ptr++ ^= mask;
*ptr++ ^= mask;
*ptr++ ^= mask;
*ptr++ ^= mask;
} while ((n -= 4) > 0);
Но, с помощью устройства Даффа, код может следовать за этой разворачивающейся идиомой, которая прыгает в нужное место в середине цикла, если n
не делится на 4.
switch (n % 4) do {
case 0: *ptr++ ^= mask; /* FALL THROUGH */
case 3: *ptr++ ^= mask; /* FALL THROUGH */
case 2: *ptr++ ^= mask; /* FALL THROUGH */
case 1: *ptr++ ^= mask; /* FALL THROUGH */
} while ((n -= 4) > 0);
Такой ручный разворот редко требуется с современными компиляторами, поскольку механизм оптимизации компилятора может разворачивать петли от имени программиста.