#5 — Циклы в Си и операторы в них
За счёт циклов вы можете создавать повторяющийся код множество раз подряд. В языке Си существует несколько циклов, а также операторов в них. За урок мы научимся работать с циклами в Си.
Видеоурок
В языке Си, как и в большинстве других языков, существует 3 вида циклов. Каждый из них выполняет одну и ту же роль, но записывается по-разному. Рассмотрим все три цикла.
Цикл For
В цикле for все условия записываются в одном месте, что очень удобно во многих случаях. Стандартная запись такого цикла выглядит следующим образом:
for (int i = 0; i < 10; i++) printf("%d\n", i);
В объявлении цикла записывается следующее: переменная цикла, её начальное значение и диапазон. В примере выше будут выведены числа от 0 до 10.
Если в теле цикла всего одна строка кода, то фигурные скобки можно пропустить и не записывать их.
Цикл While
Суть цикла while не особо отличается от цикла for . Единственное отличие заключается в способе записи цикла. В while необходимо прописать лишь условие, а все остальные параметры записываются вне цикла:
int i = 1; // Создание переменной while (i
Цикл Do While
Цикл схож с циклом while по форме написания, но при этом работает немного по-другому. Цикл do..while будет выполнен один раз сто процентов, а дальше проверит условие и если оно верно, то цикл будет выполняться дальше:
int x = 13; do < x--; printf("%d\n", i); >while (x > 10);
Как видно из примера, цикл изначально неверный, но это не мешает ему сработать один раз.
Операторы для работы в циклах
Существует два основных оператора для работы в циклах:
- Оператор break - служит для выхода из цикла полностью;
- Оператор continue - пропускает лишь одну итерацию и не выходит из цикла.
Весь код будет доступен после подписки на проект!
Задание к уроку
Необходимо оформить подписку на проект, чтобы получить доступ ко всем домашним заданиям
Большое задание по курсу
Вам необходимо оформить подписку на сайте, чтобы иметь доступ ко всем большим заданиям. В задание входит методика решения, а также готовый проект с ответом к заданию.
PS: подобные задания доступны при подписке от 1 месяца
Инструкции и циклы C# if — учебник по условной логике
В этом руководстве описано, как написать код C#, который проверяет переменные и изменяет путь выполнения на основе этих переменных. Вы напишете код C# и сможете просмотреть результаты его компиляции и выполнения. Это руководство содержит ряд уроков, в которых рассматриваются конструкции ветвления и циклов в C#. В рамках этих занятий вы ознакомитесь с основами языка C#.
Чтобы вставить фрагмент кода в режим фокусировки , используйте сочетание клавиш ( CTRL + v или cmd + v ).
Предварительные требования
Для работы с руководством вам потребуется компьютер, настроенный для разработки в локальной среде. Инструкции по установке и общие сведения о разработке приложений в .NET см. в статье Настройка локальной среды .
Если вы предпочитаете выполнять код без настройки локальной среды, ознакомьтесь с интерактивной версией этого руководства в браузере.
Принятие решений с помощью оператора if
Создайте каталог с именем branches-tutorial. Сделайте его текущим, выполнив следующую команду:
dotnet new console -n BranchesAndLoops -o .
В шаблонах C# для .NET 6 используются операторы верхнего уровня. Приложение может не соответствовать коду, приведенному в этой статье, если вы уже выполнили обновление до .NET 6. Дополнительные сведения см. в статье Новые шаблоны C# для создания инструкций верхнего уровня.
Пакет SDK для .NET 6 также добавляет набор неявных global using директив для проектов, использующих следующие пакеты SDK:
- Microsoft.NET.Sdk
- Microsoft.NET.Sdk.Web
- Microsoft.NET.Sdk.Worker
Эти неявные директивы global using включают наиболее распространенные пространства имен для соответствующего типа проектов.
Эта команда создает консольное приложение .NET в текущем каталоге. Откройте файл Program.cs в любом редакторе и замените содержимое следующим кодом:
int a = 5; int b = 6; if (a + b > 10) Console.WriteLine("The answer is greater than 10.");
Чтобы выполнить этот код, введите dotnet run в окне консоли. На консоли должно появиться сообщение "Ответ больше 10". Измените объявление b , чтобы сумма была меньше 10:
int b = 3;
Введите dotnet run еще раз. Так как ответ меньше 10, никакие данные не выводятся. Проверяемое условие имеет значение false. У вас еще нет кода для выполнения, так как вы написали только одну из возможных ветвей для оператора if — ветвь true.
Вероятнее всего, при изучении C# (как и любого другого языка программирования) вы будете допускать ошибки в коде. Компилятор найдет ошибки и сообщит о них. Внимательно просмотрите выходные данные ошибки и код, вызвавший ошибку. Как правило, сведения о причине ошибки можно найти в сообщении об ошибке компилятора.
В первом примере показаны возможности if и логические типы. Логическое значение — это переменная, которая может иметь одно из двух значений: true или false . Логические переменные в C# определяются особым типом — bool . Оператор if проверяет значение bool . Если значение true , выполняется оператор, следующий после if . В противном случае он пропускается. Этот процесс проверки условий и выполнения операторов на основе этих условий предоставляет широкие возможности.
Объединение операторов if и else
Чтобы выполнить разный код в ветвях true и false, создайте ветвь else , которая будет выполняться, если условие имеет значение false. Попробуйте создать ветвь else . Добавьте две последние строки из приведенного ниже кода (первые четыре должны быть уже добавлены):
int a = 5; int b = 3; if (a + b > 10) Console.WriteLine("The answer is greater than 10"); else Console.WriteLine("The answer is not greater than 10");
Оператор после ключевого слова else выполняется, только если проверяемое условие имеет значение false . Объединив операторы if и else с логическими условиями, вы получите все необходимые возможности для обработки условий true и false .
Отступы под операторами if и else предназначены только для удобства чтения. В языке C# необязательно ставить отступы или пробелы. Операторы после ключевого слова if или else будут выполняться на основе условия. Во всех строках в примерах кода, представленных в этом руководстве, отступы традиционно соответствуют потоку управления операторов.
Так как отступ не обязателен, используйте скобки < и >, если нужно указать несколько операторов в блоке кода, который выполняется в зависимости от условий. Программисты C# обычно используют эти фигурные скобки во всех предложениях if и else . Следующий пример аналогичен тому, который вы создали. Измените код выше, чтобы он соответствовал следующему коду:
int a = 5; int b = 3; if (a + b > 10) < Console.WriteLine("The answer is greater than 10"); >else
Все примеры кода в следующих разделах руководства содержат фигурные скобки в соответствии с принятой практикой.
Можно проверить более сложные условия. Добавьте следующий код после написанного кода:
int c = 4; if ((a + b + c > 10) && (a == b)) < Console.WriteLine("The answer is greater than 10"); Console.WriteLine("And the first number is equal to the second"); >else
Символ == позволяет проверить равенство. С помощью == обозначается отличие проверки равенства от назначения, которое показано в a = 5 .
&& представляет оператор and. То есть для выполнения оператора в ветви true оба условия должны иметь значение true. В этих примерах также показано, что в каждой условной ветви можно задать несколько операторов. Нужно лишь заключить их в скобки < и >. Вы также можете использовать для || представления "или". Добавьте следующий фрагмент после написанного кода:
if ((a + b + c > 10) || (a == b)) < Console.WriteLine("The answer is greater than 10"); Console.WriteLine("Or the first number is equal to the second"); >else
Измените значения a , b и c , а также переключитесь между && и || для изучения. Так вы лучше поймете, как работают операторы && и || .
Вы завершили первый этап. Прежде чем перейти к следующему разделу, переместим текущий код в отдельный метод. Это упростит начало работы с новым примером. Поместите существующий код в метод ExploreIf() . Вызовите этот метод в начале программы. После внесения этих изменений код должен выглядеть так:
ExploreIf(); void ExploreIf() < int a = 5; int b = 3; if (a + b >10) < Console.WriteLine("The answer is greater than 10"); >else < Console.WriteLine("The answer is not greater than 10"); >int c = 4; if ((a + b + c > 10) && (a > b)) < Console.WriteLine("The answer is greater than 10"); Console.WriteLine("And the first number is greater than the second"); >else < Console.WriteLine("The answer is not greater than 10"); Console.WriteLine("Or the first number is not greater than the second"); >if ((a + b + c > 10) || (a > b)) < Console.WriteLine("The answer is greater than 10"); Console.WriteLine("Or the first number is greater than the second"); >else < Console.WriteLine("The answer is not greater than 10"); Console.WriteLine("And the first number is not greater than the second"); >>
Закомментируйте вызов ExploreIf() . Это поможет упорядочить выходные данные в этом разделе.
//ExploreIf();
// запускает комментарий в C#. Комментарии — это любой текст, который должен быть сохранен в исходном коде, но не должен выполняться как код. Компилятор не создает исполняемый код из комментариев.
Использование циклов для повторения операций
В этом разделе циклы используются для повторения операторов. Добавьте следующий код после вызова ExploreIf :
int counter = 0; while (counter < 10) < Console.WriteLine($"Hello World! The counter is "); counter++; >
Оператор while проверяет условие и выполняет инструкцию или блок инструкций, следующий после while . Он многократно проверяет условие, выполняя эти инструкции до тех пор, пока условие не будет false.
В этом примере представлен еще один новый оператор. Объект ++ после переменной counter представляет собой оператор инкремента. Он добавляет 1 к значению counter и сохраняет это значение в переменной counter .
Напишите такой код, при выполнении которого значение условия цикла while изменится на false. В противном случае будет создан бесконечный цикл, в котором выполнение программы никогда не закончится. Это не показано в примере, так как нужно принудительно закрыть программу, нажав клавиши CTRL+C, или другим способом.
В цикле while условие проверяется, прежде чем выполнить код, который следует после while . А в цикле do . while сначала выполняется код, а потом проверяется условие. Цикл do while показан в следующем примере кода.
int counter = 0; do < Console.WriteLine($"Hello World! The counter is "); counter++; > while (counter < 10);
Этот цикл do и цикл while , приведенный выше, выводят одинаковый результат.
Работа с циклом for
Цикл for широко используется в C#. Выполните этот код:
for (int index = 0; index < 10; index++) < Console.WriteLine($"Hello World! The index is "); >
Этот цикл работает так же, как циклы while и do , которые вы использовали ранее. Оператор for состоит из трех частей, которые отвечают за его работу.
Первая часть — для инициализатора: int index = 0; объявляет index переменной цикла и задает для ее начальное значение 0 .
Последняя часть — для итератора: index++ определяет, как изменится переменная цикла после выполнения блока, следующего после оператора for . В нашем случае определяется, что значение index должно увеличиваться на 1 каждый раз, когда выполняется блок.
Поэкспериментируйте. Попробуйте использовать следующие варианты.
- Измените инициализатор, чтобы цикл начинался с другого значения.
- Измените условие, чтобы цикл заканчивался другим значением.
По окончании попробуйте самостоятельно написать код, чтобы применить полученные знания.
Есть еще одна циклическая инструкция, которая не рассматривается в этом руководстве: оператор foreach . Оператор foreach повторяет выполнения для каждого элемента в последовательности элементов. Чаще всего он используется с коллекциями, поэтому он рассматривается в следующем руководстве.
Создание вложенных циклов
Цикл while , do или for можно вложить в другой цикл, чтобы создать матрицу, комбинируя каждый элемент во внешнем цикле с каждым элементом во внутреннем цикле. Давайте сделаем это для получения набора из буквенно-цифровых пар, представляющих строки и столбцы.
Один цикл for может создавать строки:
for (int row = 1; row < 11; row++) < Console.WriteLine($"The row is "); >
Другой цикл может создавать столбцы:
for (char column = 'a'; column < 'k'; column++) < Console.WriteLine($"The column is "); >
Можно вложить один цикл внутрь другого для формирования пар:
for (int row = 1; row < 11; row++) < for (char column = 'a'; column < 'k'; column++) < Console.WriteLine($"The cell is (, )"); > >
Как видите, внешний цикл увеличивается на единицу при каждом полном выполнении внутреннего цикла. Измените порядок вложенности строк и столбцов и просмотрите изменения самостоятельно. По завершении поместите код, приведенный в этом разделе, в метод ExploreLoops() .
Объединение ветвей и циклов
Теперь, когда вы ознакомились с оператором if и конструкциями цикла на языке C#, попытайтесь написать код C# для поиска суммы всех целых чисел от 1 до 20, которые делятся на 3. Вот несколько подсказок:
- оператор % позволяет получить остаток от операции деления;
- оператор if предоставляет условие, которое позволяет определить, будет ли число учитываться в сумме;
- цикл for позволяет повторить последовательность шагов для всех чисел от 1 до 20.
Попробуйте самостоятельно. Затем проверьте результат. Вы должны получить ответ "63". Один из возможных ответов можно увидеть в полном примере кода в GitHub.
Вы ознакомились с руководством по ветвям и циклам.
Теперь вы можете перейти к ознакомлению с руководством Массивы и коллекции в своей среде разработки.
Дополнительные сведения об этих понятиях см. в следующих статьях:
- Инструкции выбора
- Инструкции итерации
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Что такое цикл в с
Циклы позволяет выполнить одно действие множество раз в зависимости от определенного условия. В языке Си есть следующие типы циклов:
Цикл for
Цикл for имеет следующее формальное определение:
for (инициализация; условие; приращение;) < // тело цикла >
заголовок цикла состоит из трех частей. Первая часть - инициализация выполняется один раз при начале выполнения цикла и представляет установку начальных условий, как правило, это инициализация счетчиков - специальных переменных, которые используются для контроля за циклом.
Вторая часть - условие , при соблюдении которого выполняется цикл. Зачастую в качестве условия используется операция сравнения, и если она возвращает ненулевое значение (то есть условие истинно), то выполняется тело цикла, а затем вычисляется выражение_3 .
Третья часть - приращение задает изменение параметров цикла. Обычно здесь происходит увеличение счетчиков цикла.
Рассмотрим стандартный цикл for и для этого выведем числа с 0 до 5 на консоль:
#include int main(void) < for (int i = 0; i < 6; i++) < printf("%d", i); >return 0; >
Первая часть объявления цикла - int i = 0 - создает и инициализирует счетчик i. Счетчик необязательно должен представлять тип int. Это может быть и другой числовой тип, например, float. И перед выполнением цикла его значение будет равно 0. В данном случае это то же самое, что и объявление переменной.
Вторая часть - условие, при котором будет выполняться цикл. В данном случае цикл будет выполняться, пока i не достигнет 6.
И третья часть - приращение счетчика на единицу. Опять же нам необязательно увеличивать на единицу. Можно уменьшать: i--. Можно изменять на другое значение: i+=2.
В итоге блок цикла сработает 6 раз, пока значение i не станет равным 6. И каждый раз это значение будет увеличиваться на 1.
012345
Каждый отдельный проход цикла называется итерацией. То есть в примере выше было 6 итераций.
Усложним цикл и выведем квадраты чисел от 0 до 8:
#include int main(void) < for (int i = 0; i < 9; i++) < printf("%d * %d = %d \n", i, i, i * i); >return 0; >
Здесь блок цикла сработает 9 раз, пока значение i не станет равным 9. И каждый раз это значение будет увеличиваться на 1.
0 * 0 = 0 1 * 1 = 1 2 * 2 = 4 3 * 3 = 9 4 * 4 = 16 5 * 5 = 25 6 * 6 = 36 7 * 7 = 49 8 * 8 = 64
Необязательно указывать все три выражения в определении цикла, мы можем одно или даже все их них опустить:
int i = 1; for ( ; i
Формально определение цикла осталось тем же, только теперь первое и третье выражения в определении цикла отсутствуют: for (; i < 9;) . Переменная-счетчик определена и инициализирована вне цикла, а ее приращение происходит в самом цикле.
Можно определять вложенные циклы. Например, выведем таблицу умножения:
#include int main(void) < for (int i=1; i < 10; i++) < for(int j = 1; j < 10; j++) < printf("%d \t", i * j); >printf("\n"); > return 0; >
Цикл do..while
В цикле do..while сначала выполняется код цикла, а потом происходит проверка условия в инструкции while . И пока это условие истинно, то есть не равно 0, то цикл повторяется.
do < // действия цикла >while (условие);
#include int main(void) < int i = 6; do < printf("%d", i); i--; >while (i > 0); return 0; >
Здесь код цикла сработает 6 раз, пока i не станет равным нулю. Но важно отметить, что цикл do гарантирует хотя бы единократное выполнение действий, даже если перед первым выполнением условие в инструкции while не будет истинно. То есть мы можем написать:
int i = -1; do < printf("%d", i); i--; >while (i > 0);
Хотя у нас переменная i меньше 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 переходим к следующей итерации цикла. А если число нечетное, то складываем его с остальными нечетными числами.
Циклы в языке C: while, do-while, for. Инкремент и декремент
Прежде, чем изучать циклы, следует познакомиться с часто используемым в языке C способом увеличения/уменьшения значений переменных на единицу. Конечно, в Си работают такие формы изменения значений как, например, a += 1 или a -= 1 . Однако чаще используют операции инкрементирования (оператор инкремента ++ ) и декрементирования (оператор декремента -- ): i++ или ++i , i-- или --i . В результате этих операций переменные увеличиваются или уменьшаются на единицу.
Запомните, когда вы видите выражения типа ++i или i++ , то в результате их выполнения значение i меняется. Не надо делать вот так: i = ++i . Это совершенно лишнее.
Когда знак инкремента или декремента стоит перед переменной, то перед нами префиксная форма операции ( ++i , --i ), а когда после переменной, то постфиксная форма ( i++ , i-- ). Когда эти выражения не участвуют в построении более сложных выражений, то между префиксной и постфиксной формами никакой разницы нет: что i++ , что ++i — без разницы, в результате мы получим значение i на единицу больше.
Однако когда эти выражения участвуют в построении более сложных, то разница между префиксной и постфиксной формами появляется и заключается в следующем: переменная над которой производится операция инкрементирования или декрементирования в постфиксной форме сначала используется в сложном выражении как есть, и только потом увеличивается на единицу; если мы имеем дело с префиксной формой, то переменная сначала изменяется, а затем используется. Например, код:
int a, b, c, d; /* выражение означает, что всем переменным присваивается 0 */ a = b = c = d = 0; printf("a=%d, b=%d, c=%d, d=%d\n", a, b, c, d); c = ++a; d = b++; printf("a=%d, b=%d, c=%d, d=%d\n", a, b, c, d);
, выведет на экране:
a=0, b=0, c=0, d=0 a=1, b=1, c=1, d=0
Объясняется такой результат так:
- значение переменной a было увеличено на единицу, после чего это значение было присвоено переменной c ;
- значение переменной b было сначала присвоено переменной d и только потом увеличено на единицу.
Еще один пример:
int x, y; x = y = 0; printf("%d\n", x++ > 0); printf("%d\n", ++y > 0);
На экране будет выведено:
Это результат логических выражений, где 0 означает ложь, а 1 — истину. В данном случае, когда x сравнивается с нулем, то его значение еще не увеличено, а когда сравнивается у , то его значение уже больше нуля.
Применять операторы инкремента и декремента можно также к переменным вещественного типа.
Цикл while
Цикл while в языке программирования C работает также как и в других языках программирования. По аналогии с условным выражением в инструкции if , условное выражение при while заключается в круглые скобки. Если тело цикла включает несколько выражений разделяемых точкой с запятой, то все тело заключается в фигурные скобки.
- Присвойте переменной star значение 0. Пока значение star не достигнет 55 выводите на экран в строку по одной звездочке ( * ).
- С помощью цикла while запрограммируйте вывод на экран цифровых кодов и значений таблицы символов ASCII от 31 до 127 включительно. При этом после каждого десятого символа осуществляйте переход на новую строку. (Подсказка: чтобы переходить на новую строку, в цикле while надо использовать инструкцию if , в условии которой остаток 1 от деления на 10 сравнивается с нулем.)
- Используя внешний и вложенный циклы while организуйте вывод таблицы умножения на экран.
1 Операция нахождения остатка от деления в языке C обозначается знаком процента % .
Цикл do-while
Цикл do-while отличается от while лишь тем, что его тело будет выполнено хотя бы один раз независимо от условия выполнения цикла. Синтаксис цикла do-while можно описать так (фигурные скобки необязательны, если выражение только одно):
do < выражение1; …; >while (логич_выражение);
Этот цикл называют циклом с постусловием. Его используют реже обычного while . В принципе почти всегда можно обойтись без do-while , но в определенных ситуациях его использование упрощает код. Допустим требуется вывести на экран отдельные цифры числа. Любое число состоит хотя бы из одной цифры, даже число 0. Можно решить эту задачу с использованием цикла while :
while (a > 0) { printf("%d\n", a % 10); a = a / 10; }
Но в этом случае, если a равно 0, то цикл не выполнится ни разу. Пришлось бы перед циклом использовать инструкцию if , в которой сравнивать переменную с 0. Использование же цикла do-while решает эту проблему, т. к. его тело один раз выполнится даже при нулевом значении переменной:
do { printf("%d\n", a % 10); a = a / 10; } while (a > 0);
Цикл for
Представим синтаксис заголовка цикла for языка программирования C так:
for (часть1; часть2; часть3)
Заголовок цикла for включает три части, разделенных точкой с запятой; причем каждая часть может быть сложной, т. е. состоять из нескольких выражений, разделенных простой запятой. В первой части обычно указываются переменные и часто их начальные значения; во второй – с помощью логического(их) выражения(й) задаются условия, при которых выполняется тело цикла; в третью часть помещаются выражения, которые выполняются в конце каждой итерации цикла (чаще всего здесь изменяется значение переменной, заданной в первой части заголовка).
Вот так будет выглядеть программный код, выводящий таблицу символов на экран, в котором используется цикл 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-версия