В программировании порой необходимо выполнить набор инструкций определенное количество раз. Возможное решение — скопировать код. Но есть проблема: количество этих наборов мы можем либо не знать, либо их может быть очень много (10000, к примеру).
Решение проблемы — циклы. В программировании циклы используются для многократного выполнения блока кода. Цикл работает до тех пор, пока заданное условие истинно.
Цикл for
Для инициализации цикла используется ключевое слово for.
Синтаксис цикла
for (счетчик; условие; итератор)
// тело цикла
>
- В цикле for три переменные: счетчик , условие и итератор .
- Объявление счетчика происходит в самом начале и лишь раз. Обычно он инициализируется сразу после объявления.
- Затем проверяется условие. Условие — булево выражение. То есть, возвращает true или false .
- Если условие определяется как true :
• Выполняются инструкции внутри цикла.
• После этого инициализируется итератор — обычно изменяется значение этой переменной.
• Условие проверяется снова.
• Процесс повторяется до тех пор, пока условие не будет определено как false . - Если условие определится как false , цикл завершается.
Блок-схема работы цикла
Пример 1. Итерации цикла for
using System; namespace Loop < class ForLoop < public static void Main(string[] args) < for (int i=1; i», i); > > > >
Вывод:
Цикл for C#: итерация 1
Цикл for C#: итерация 2
Цикл for C#: итерация 3
Цикл for C#: итерация 4
Цикл for C#: итерация 5
В этой программе:
- счетчик — int = 1 ,
- условие — i
- итератор — i++ ,
После запуска программы происходит следующее:
- Объявляется и инициализируется переменная i . Ей присваивается значение 1.
- После этого проверяется условие i
- Если проверка условия возвращает `true`, выполняется тело цикла. Оно печатает строку «Цикл for C#: итерация 1».
- Затем определяется значение итератора ( i++ ). Значение i увеличивается до 2.
- Условие ( i
- Когда значение i станет равняться 6, условие оценится как false . Следовательно, цикл завершится.
Пример 2. Вычисляем сумму первых n натуральных чисел
using System; namespace Loop < class ForLoop < public static void Main(string[] args) < int n = 5, sum = 0; for (int i=1; iConsole.WriteLine(«Сумма первых натуральных чисел = «, n, sum); > > >
Вывод:
Сумма первых 5 натуральных чисел = 15
В этой программе объявляются две переменные — sum и n . Их значения равны 0 и 5 соответственно. Значение счетчика i в самом начале равно 1.
Внутри цикла значение переменной sum увеличивается на i — sum = sum + i . Цикл продолжается до тех пор, пока значение счетчика i меньше или равно n .
Давайте посмотрим, что происходит на каждой итерации цикла.
Цикл for. Что это. Что делает. Пример. Синтаксис. Циклы. Урок #16.
Изначально i = 1, sum = 0 и n = 5.
Итерация
Значение i
Значение sum
То есть, финальное значение sum будет равняться 15.
[edit] Keywords
The expression statement used as loop-statement establishes its own block scope, distinct from the scope of init-clause , unlike in C++:
for (int i = 0; ; ) { long i = 1; // valid C, invalid C++ // . }
It is possible to enter the body of a loop using goto. When entering a loop in this manner, init-clause and cond-expression are not executed. (If control then reaches the end of the loop body, repetition may occur including execution of cond-expression .)
[edit] Example
Run this code
#include #include enum { SIZE = 8 }; int main(void) { int array[SIZE]; for(size_t i = 0 ; i SIZE; ++i) array [i] = rand() % 2; printf(«Array filled!n»); for (size_t i = 0; i SIZE; ++i) printf(«%d «, array[i]); putchar(‘n’); }
Array filled! 1 0 1 1 1 1 0 0
Цикл while
В отличие от цикла do цикл while сразу проверяет истинность некоторого условия, и если условие истинно, то есть не равно 0, то код цикла выполняется:
while(условие) < // выполняемые инструкции, если условие истинно >
Например, выведем на консоль все числа от 6 до 1:
#include int main(void) < int i = 6; while (i >0) < printf(«%d n», i); i—; >return 0; >
Здесь, пока истинно условие i > 0 , будут выполняться действия цикла — printf(«%d n», i) и i—
Операторы continue и break
Иногда возникает необходимость выйти из цикла до его завершения. В этом случае можно воспользоваться оператором break . Например:
int i = 1; for ( ; ; ) < printf(«%d * %d = %d n», i, i, i * i); i++; if (i >5) break; >
Здесь когда значение переменной i достигнет 5, осуществляется выход из цикла с помощью оператора break .
В отличие от оператора break , оператор continue производит переход к следующей итерации. Например, нам надо посчитать сумму только нечетных чисел из некоторого диапазона:
#include int main(void) < int result = 0; for (int i=0; iprintf(«result = %d», result); // 25 return 0; >
Чтобы узнать, четное ли число, мы получаем остаток от целочисленного деления на 2, и если он равен 0, то с помощью оператора continue переходим к следующей итерации цикла. А если число нечетное, то складываем его с остальными нечетными числами.
Цикл for
Представим синтаксис заголовка цикла for языка программирования C так:
for (часть1; часть2; часть3)
Вот так будет выглядеть программный код, выводящий таблицу символов на экран, в котором используется цикл for :
unsigned char a; for (a = 31; a 128; a++) { if (a % 10 == 0) printf(«n»); printf(«%4d-%c», a, a); } printf(«n»);
Напишите программу с использованием цикла for , выводящую на экран таблицу умножения (Подсказка: как и в случае с while следует использовать два цикла — внешний и вложенный.)
Операторы break и continue
Оператор break позволяет прервать выполнение цикла, а continue — прервать текущую итерацию (проход) цикла. Почти всегда можно обойтись без этих операторов, но иногда их использование позволяет упростить программный код и сделать его более понятным.
Рассмотрим пару примеров. Допустим, требуется проверить массив на наличие в нем хотя бы одного элемента со значением 0. Как только ноль будет обнаружен проверять оставшуюся часть массива уже нет смысла. Поэтому, чтобы не выполнять лишних итераций, используется оператор break .
#define N 10 int arr[N] = {6, 5, -4, 3, -7, 2, 7, 0, 3, 9}; int new_arr[N], i, j; for (i=0; iN; i++) { if (arr[i] == 0) { printf(«nIt contains zero»); break; } // не обязательно printf(«%d «, arr[i]); } printf(«n»);
Второй пример. Требуется из одного массива скопировать в другой только числа, которые больше 0. Можно с помощью continue прерывать итерацию цикла, если очередной элемент меньше либо равен нулю.
for(i=0, j=0; iN; i++) { if (arr[i] 0) continue; new_arr[j] = arr[i]; printf(«%d «, new_arr[j]); j++; } printf(«n»);
В данном случае использование continue совсем не очевидно с точки зрения надобности, т. к. легко можно обойтись без него, если изменить условие при if на противоположное, удалить continue , а оставшийся код поместить в тело оператора if .
Курс с решением задач:
pdf-версия
C Урок 6. Условные циклы while, do while, for
На данном уроке мы познакомимся с циклами. Иногда их называют «петлями».
Циклы в коде нам порой требуются для того, чтобы некоторый его участок выполнить какое-то количество раз. Причём это количество может быть заранее известно, либо неизвестно. Если неизвестно, то количество зависит от некоторых условий.
Начнём с цикла типа while, так как, я считаю, что из всех трёх рассматриваемых нами в данном занятии видов циклов он самый простой.
Выглядит цикл с оператором while примерно вот так
Данный цикл состоит из оператора, условия в скобках и тела с инструкциями и командами. В тело цикла мы попадаем только тогда, когда условие в скобках будет истинным или будет иметь положительный результат.
То есть если мы, например в скобках напишем просто единичку (1), то цикл наш станет бесконечным. Это конечно в теории. Цикл можно окончить, если где-то в теле применить определённые команды, с которыми мы будем знакомиться позже. Не всё сразу.
Давайте попробуем работу цикла на практике. Конечно, пока будем выполнять только простейшие операторы, чтобы было понятнее.
Проект создадим с именем MYPROG06 из проекта прошлого занятия.
Из тела функции main() в файле main.c удалим весь код, кроме команды возврата значения, останется у нас вот это
int main()
return 0 ; //Return an integer from a function
Объявим и сразу инициализируем целочисленную переменную
А теперь добавим наш цикл
printf ( «i = %drn» , i ) ;
Тело цикла будет многократно повторяться до тех пор, пока значение переменной i будет положительным, то есть будет иметь результат больший или равный нулю.
Попробуем собрать наш код и запустить приложение. Посмотрим на результат работы нашей программы
Как видим, наш счётчик досчитал от 10 до 1 в обратную сторону, так как у нас внутри цикла применено декрементирование. Причём, так как декрементирование происходит после вывода результата в консоль, то как только i становится равным нулю, мы в тело цикла больше не попадаем, а перепрыгиваем его полностью и переходим к команде return 0.
Думаю, для начала нам будет понятно, как работает цикл с оператором while (кстати с английского переводится «пока»).
Следующий тип цикла — это цикл с двумя операторами do while.
Такой цикл выглядит уже вот таким образом
Здесь всё происходит подобным образом, но, в отличие от первого варианта, здесь мы хотя бы раз в тело цикла все равно попадаем. А истинность (или положительный результат) условия проверяется только после того, как мы выполнили все инструкции в теле цикла. И, если условие не выполнится (окажется ложным), то мы уже повторно проходить тело цикла не будем, а «провалимся» вниз на следующую инструкцию, находящуюся в коде после цикла.
Казалось, бы, зачем нужен такой тип цикла. Хочется вспомнить даже поговорку «Начала делать блины, разогрела сковороду, а оказалось, что молока и муки нет». Поэтому данным типом цикла мы в нашей жизни пользуемся гораздо реже, чем первым вариантом, но иногда приходится. Например, возьмём ситуацию на проверку правильности ввода пароля. Проверка введённого пароля происходит в цикле и, если он совпал с настоящим, то мы выходим из цикла, а если нет (в этом случае правильность условия будет — несовпадение пароля), то повторяем ввод, то есть повторно входим в условие цикла. Если будет цикл первого типа, то мы ни разу не сможем проверить правильность ввода пароля. Это одна из ситуаций и таких много.
Давайте данный цикл попробуем на деле.
Зададим сначала те же условия, что и в предыдущем участке кода, но уже применим второй тип цикла, не забыв, конечно, вернуть состояние переменной
printf ( «=========================rn» ) ;
printf ( «i = %drn» , i ) ;
Соберём код и посмотрим результат, который в нашем случае окажется таким же как и в случае применения цикла первого типа
Теперь давайте попробуем задать в условии обеих циклов такое условие, которое никогда не бывает истинным, например обычный ноль (0)
while ( 0 )
Соберём код и посмотрим результат
Мы видим, что в первом случае (до двойных чёрточек) у нас вообще ничего не вывелось в консоль, потому что условие не выполнилось и мы вообще ни разу не попали в тело цикла, а во втором случае один раз тело цикла было выполнено. Теперь мы знаем разницу между этими двумя типами циклов.
Третий тип цикла — это цикл for. Данный цикл как правило используется тогда. когда заранее известно количество повторений. Но это классический вариант. А вообще, сфера использования данных циклов очень велика. Мы ещё встретимся в наших уроках с этим разнообразием различных вариантов циклов.
Цикл for выглядит следующим образом
Здесь немного посложнее. Но не сильно. Данный тип цикла работает следующим образом. Сначала, ещё не входя в тело цикла, сразу выполняется инструкция под названием «инициализация», затем проверяется истинность условия, и если оно истинно, то мы входим в тело цикла, выполняем все инструкции, затем выполняется инструкция, стоящая в третьей позиции под названием «модификация», снова проверяется условие, и, если оно истинно, то мы опять входим в тело цикла и выполняем там все инструкции, и так до тех пор, пока после выполнения инструкции под названием «модификация» наше условие не перестанет выполняться. Как только оно станет ложным или не будет иметь положительный результат, мы больше не входим в тело цикла, «перепрыгиваем» его и выполняем инструкции, находящиеся уже после тела цикла.
Думаю, что объяснил вполне популярно. Я старался описать не слишком заумно, чтобы было понятно всем.
Давайте теперь проверим работу данного типа цикла на практике и добавим в нашу функцию main() следующий код
Инкременты и декременты
Перед изучением for и иных «петлей» в СИ, каждый разработчик должен изучить инкременты и декременты. Без них создание программных кодов станет невозможным даже для новичков.
При работе с «петлями» в разработке ПО приходится часто пользоваться увеличением и уменьшением значений переменных на единицу. В C функционируют такие формы изменения как a +=1 и a -= 1, но чаще всего сделать необходимые операции помогают инкременты (++) и декременты (—).
Выражения типа ++i и i++ позволяют поменять исходное значение. Пользоваться записями типа I = ++i нет никакой необходимости. Это лишнее. Достаточно заполнить следующие правила и условия:
- Если знак декремента или инкремента стоит перед переменной, перед клиентом будет префиксная форма операции. В противном случае – постфиксная.
- В «классических» выражениях сделать инкремент и декремент можно как постфиксной записью, так и префиксной. Разницы между ними нет.
- Когда соответствующие записи участвуют в построении более сложных, необходимо учесть, что в постфиксной форме, переменная, с которой требуется сделать какие-либо действия в сложном выражении сначала используется «как есть», а затем уже увеличивается/уменьшается на единицу. В префиксной записи сначала реализовываются изменения, а затем переменная будет применяться.
Инкременты и декременты применяются не только в циклах. Они встречаются при работе с переменными вещественного типа в СИ и C++.
Классификация
Циклы в СИ и C++ бывают нескольких видов. Всего их три:
- с параметром (счетчиком);
- с постусловием;
- с предусловием.
Особое внимание необходимо уделить циклу с параметром – for. Он встречается в большинстве языков разработки и позволяет реализовывать не только простые алгоритмы, но и достаточно сложные инструкции.
Цикл while
Создать цикл и использовать его в программном коде удается несколькими способами. Первый вариант – это «петля» с предусловием. Используется тогда, когда количество раз выполнения цикла известно заранее.
Форма записи в СИ:
Здесь сначала происходит проверка инструкции, написанной в while, а затем – реализация инструкций. Тело цикла, заключенное в фигурные скобки, будет выполняться до тех пор, пока заданное условие на выходе получает логическое значение истины (равняется true).
С постусловием
Создать «петлю» в программном коде на C++ и Си можно, используя постусловие. Он напоминает предыдущий вариант в обоих языках разработки. при его реализации один проход цикла будет выполняться всегда, независимо от имеющегося условия.
Соответствующий фрагмент позволяет сначала выполнить код цикла в СИ, затем – проверить условия, записанные в инструкции while. Пока оно истинно (не равно 0), алгоритм будет повторяться снова и снова.
Вот – наглядный пример кода:
#include stdio.h int main (void) < int i = 6; do < printf(«%d», i); i—; >while (i > 0); return 0; >
Функция (исходный код) будет работать 6 раз – до тех пор, пока значение переменной i не достигнет 0. «Петля» с do всегда гарантирует выполнение прописанных в теле действий один раз. Это относится даже к ситуациям, при которых первый же результат проверки заданного условия не является истиной.
С параметром
Наиболее простой и распространенный метод, помогающий создавать «петли» – это функция со счетчиком. За нее отвечает оператор for в языке C и C++. Соответствующая запись встречается в большинстве языков разработки. Обозначается при помощи for всегда.
При помощи for можно создать цикл тогда, когда известно точное количество итераций. Они будут известны еще до непосредственного запуска программного обеспечения.
Синтаксическая конструкция for в СИ:
В C++ запись for будет следующей:
Цикл for СИ – это функция, которая включает в себя несколько частей:
- Первая — инициализация. Она осуществляется всего один раз, в самом начале for. Представлена установкой начальных условий. Обычно выражена счетчиками – специальными переменными (h int), используемыми для контроля за циклом.
- Вторая – условие. Оно формирует требование, которое при значении истины (true или 1) будет реализовывать то, что написано в for. В виде условия часто используется операция сравнения.
- Третья – приращение. Является необязательным. Используется в for для определения «шага». Указывает, на сколько система делает увеличение или уменьшение заданного значения переменной при следующей итерации.
Если не указывать приращение, оно будет стандартным – +1. Ниже – пример использования for в C:
- Сначала происходит инициализация счетчика i, значение которого равно 0. I 10 тоже допускается, но в «классическом» примере параметр изначально равняется нулю. Так проще разобраться с принципами работы for.
- Счетчик представляем тип int. Можно воспользоваться любым другим числовым.
- Далее пишется условие, при котором выполняется тело цикла. В заданном примере – до i = 6.
- Последний этап – это приращение. В представленном фрагменте оно будет равно +1. Для уменьшения используется запись i—.
Выше – результат реализации цикла с for, фрагмент которого написан ранее. Для C++ можно рассмотреть такой код:
Соответствующий фрагмент используется для счета суммы всех чисел в пределах от 1 до 1 000.
Цикл с постусловием do. while
Общая форма записи
do <
БлокОпераций;
> while (Условие);
Цикл do…while — это цикл с постусловием, где истинность выражения, проверяющего Условие проверяется после выполнения Блока Операций , заключенного в фигурные скобки. Тело цикла выполняется до тех пор, пока выражение, проверяющее Условие , не станет ложным, то есть тело цикла с постусловием выполнится хотя бы один раз.
Использовать цикл do…while лучше в тех случаях, когда должна быть выполнена хотя бы одна итерация, либо когда инициализация объектов, участвующих в проверке условия, происходит внутри тела цикла.
Пример на Си . Проверка, что пользователь ввел число от 0 до 10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf
#include
#include // для использования функции system()
int main()
int num; // объявляем целую переменную для числа
system( «chcp 1251» ); // переходим на русский язык в консоли
system( «cls» ); // очищаем экран
do printf( «Введите число от 0 до 10: » ); // приглашение пользователю
scanf( «%d» , // ввод числа
> while ((num 10)); // повторяем цикл пока num 10
printf( «Вы ввели число %d» , num); // выводим введенное значение num — от 0 до 10
getchar(); getchar();
return 0;
>
Параметрический цикл for
Общая форма записи
for (Инициализация; Условие; Модификация)
БлокОпераций;
>
for — параметрический цикл (цикл с фиксированным числом повторений). Для организации такого цикла необходимо осуществить три операции:
- Инициализация — присваивание параметру цикла начального значения;
- Условие — проверка условия повторения цикла, чаще всего — сравнение величины параметра с некоторым граничным значением;
- Модификация — изменение значения параметра для следующего прохождения тела цикла.
Эти три операции записываются в скобках и разделяются точкой с запятой ; ;. Как правило, параметром цикла является целочисленная переменная.
Инициализация параметра осуществляется только один раз — когда цикл for начинает выполняться.
Проверка Условия повторения цикла осуществляется перед каждым возможным выполнением тела цикла. Когда выражение, проверяющее Условие становится ложным (равным нулю), цикл завершается.
Модификация параметра осуществляется в конце каждого выполнения тела цикла. Параметр может как увеличиваться, так и уменьшаться.
Пример на Си : Посчитать сумму чисел от 1 до введенного k
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf
#include
int main()
int k; // объявляем целую переменную key
int sum = 0; // начальное значение суммы равно 0
printf( «k = » );
scanf( «%d» , // вводим значение переменной k
for ( int i=1; i // цикл для переменной i от 1 до k с шагом 1
sum = sum + i; // добавляем значение i к сумме
>
printf( «sum = %dn» , sum); // вывод значения суммы
getchar(); getchar();
return 0;
>