Перейти до основного вмісту

Цикли

Цикли – це керуючі конструкції, що дозволяють виконувати певну дію кілька разів залежно від певних умов. У C# доступні такі типи циклів:

  • for

  • foreach

  • while

  • do...while

Цикл for

Цикл for має наступне формальне визначення:

for ([дії_перед_виконанням_циклу]; [умова]; [дії_після_виконання])
{
// дії
}

Заява циклу for має три частини. Перша частина оголошення циклу – це дії, які виконуються один раз перед виконанням циклу. Зазвичай тут визначаються змінні, які будуть використовуватися в циклі.

Друга частина – це умова, за якої цикл буде виконуватися. Поки умова є істинною, цикл буде виконуватися.

Третя частина – дії, які виконуються після завершення блоку циклу. Ці дії виконуються кожного разу після завершення блоку циклу.

Після оголошення циклу, самі дії циклу розміщуються в фігурних дужках.

Розглянемо стандартний цикл for:

for (int i = 1; i < 4; i++)
{
Console.WriteLine(i);
}

Тут, перша частина оголошення циклу — int i = 1 — створює та ініціалізує змінну i.

Друга частина — це умова i < 4. Тобто, поки змінна i менша за 4, цикл буде виконуватися.

Третя частина — дії, які виконуються після завершення дій з блоку циклу — збільшує змінну i на одиницю.

Весь процес циклу можна візуалізувати так:

  1. Визначається змінна int i = 1.

  2. Перевіряється умова i < 4. Вона істинна (тому що 1 менше 4), тому виконується блок циклу, а саме інструкція Console.WriteLine(i), яка виводить значення змінної i на консоль.

  3. Блок циклу завершив виконання, тому виконується третя частина оголошення циклу — i++. Після цього змінна i дорівнює 2.

  4. Знову перевіряється умова i < 4. Вона істинна (тому що 2 менше 4), тому блок циклу виконується знову — Console.WriteLine(i).

  5. Блок циклу завершив виконання, тому знову виконується вираз i++. Після цього змінна i дорівнює 3.

  6. Знову перевіряється умова i < 4. Вона істинна (тому що 3 менше 4), тому блок циклу виконується знову — Console.WriteLine(i).

  7. Блок циклу завершив виконання, тому знову виконується вираз i++. Після цього змінна i дорівнює 4.

  8. Знову перевіряється умова i < 4. Тепер вона повертає false, тому що значення змінної i НЕ менше 4, тому цикл завершує виконання. Далі виконується решта програми, яка йде після циклу.

У підсумку, блок циклу буде виконано 3 рази, поки значення i не стане дорівнювати 4. І кожного разу це значення буде збільшуватися на 1. Одне виконання блоку циклу називається ітерацією. Отже, тут цикл виконає три ітерації. Результат програми:

1
2
3

Якщо блок циклу for містить одну інструкцію, ми можемо скоротити його, прибравши фігурні дужки:

for (int i = 1; i < 4; i++)
Console.WriteLine(i);

// або так
for (int i = 1; i < 4; i++) Console.WriteLine(i);

Не обов'язково оголошувати змінну в першій частині циклу та змінювати її значення в третій частині — це можуть бути будь-які дії. Наприклад:

var i = 1;

for (Console.WriteLine("Початок виконання циклу"); i < 4; Console.WriteLine($"i = {i}"))
{
i++;
}

Тут знову цикл запускається, поки змінна i менша за 4, тільки збільшення змінної i відбувається в блоці циклу. Вивід на консоль цієї програми:

Початок виконання циклу

i = 2
i = 3
i = 4

Ми не зобов'язані вказувати всі умови при оголошенні циклу. Наприклад, ми можемо написати його так:

int i = 1;
for (; ;)
{
Console.WriteLine($"i = {i}");
i++;
}

Формально, визначення циклу залишається тим самим, тільки тепер у нас порожні блоки в визначенні: for (; ;). У нас немає ініціалізованої змінної, немає умови, тому цикл буде виконуватися вічно — нескінченний цикл.

Ми також можемо опустити ряд блоків:

int i = 1;
for (; i < 4;)
{
Console.WriteLine($"i = {i}");
i++;
}

Цей приклад по суті еквівалентний першому прикладу: у нас також є змінна-лічильник, тільки вона визначена поза циклом. У нас є умова виконання циклу. І є збільшення змінної в самому блоці for.

Також варто згадати, що в оголошенні циклу можна визначити декілька змінних:

for (int i = 1, j = 1; i < 10; i++, j++)
Console.WriteLine($"{i * j}");

Тут у першій частині оголошення циклу визначаються дві змінні, i та j. Цикл виконується, поки i не дорівнює 10. Після кожної ітерації змінні i та j збільшуються на одиницю. Вивід на консоль програми:

Цикл do..while

Цикл do спочатку виконує код циклу, а потім перевіряє умову в інструкції while. Поки ця умова істинна, цикл повторюється.

do
{
дії циклу
}
while (умова);

Наприклад:

int i = 6;
do
{
Console.WriteLine(i);
i--;
}
while (i > 0);

Тут код циклу буде виконуватись 6 разів, поки i не стане рівним нулю. Але важливо відзначити, що цикл do гарантує принаймні одне виконання дій, навіть якщо умова в інструкції while не є істинною. Тобто, ми можемо написати:

int i = -1;
do
{
Console.WriteLine(i);
i--;
}
while (i > 0);

Навіть якщо у нас змінна i менша за 0, цикл все одно виконається один раз.

Цикл while

На відміну від циклу do, цикл while відразу перевіряє, чи є деяка умова істинною, і якщо умова істинна, то виконується код циклу:

while (умова)
{
дії циклу
}

Наприклад:

int i = 6;
while (i > 0)
{
Console.WriteLine(i);
i--;
}

Цикл foreach

Цикл foreach призначений для перебору набору або колекції елементів. Його загальне визначення:

foreach(тип_даних змінна in колекція)
{
// дії циклу
}

Після оператора foreach в дужках спочатку йде визначення змінної. Потім ключове слово in і далі колекція, елементи якої повинні бути перебрані.

Під час виконання цикл послідовно перебирає елементи колекції та поміщає їх у змінну, щоб ми могли виконувати з ними певні дії в блоці циклу.

Наприклад, візьмемо рядок. Рядок, по суті, є колекцією символів. І .NET дозволяє нам перебрати всі елементи рядка — його символи за допомогою циклу foreach.

foreach(char c in "Tom")
{
Console.WriteLine(c);
}

Тут цикл foreach перебирає всі символи рядка "Tom" та поміщає кожен символ у змінну типу char c. У блоці циклу значення змінної c виводиться на консоль. Оскільки в рядку "Tom" три символи, цикл виконається три рази. Вивід на консоль програми:

T
o
m

Варто зазначити, що змінна, визначена в оголошенні циклу, повинна бути того ж типу, що й елементи колекції, що перебирається. Наприклад, елементи рядка мають тип char — символи. Тому змінна c має тип char. Проте, на практиці не завжди очевидно, якого типу елементи колекції. У цьому випадку ми можемо визначити змінну за допомогою оператора var:

foreach(var c in "Tom")
{
Console.WriteLine(c);
}

Далі ми детальніше розглянемо, що таке колекції в .NET і які колекції можна перебирати за допомогою циклу foreach.

Оператори continue та break

Іноді виникає ситуація, коли нам потрібно вийти з циклу, не чекаючи його завершення. У цьому випадку ми можемо використати оператор break.

Наприклад:

for (int i = 0; i < 9; i++)
{
if (i == 5)
break;
Console.WriteLine(i);
}

Хоча умова циклу говорить про те, що цикл буде виконуватися, поки лічильник i не досягне значення 9, насправді цикл буде виконаний 5 разів. Тому що коли лічильник i досягає значення 5, виконується оператор break, і цикл завершується.

0
1
2
3
4

Тепер поставимо собі інше завдання. Що, якщо ми хочемо, щоб цикл пропустив поточну ітерацію замість того, щоб завершитися під час перевірки. Для цього ми можемо використати оператор continue:

for (int i = 0; i < 9; i++)
{
if (i == 5)
continue;
Console.WriteLine(i);
}

У цьому випадку, коли цикл досягає числа 5, яке не задовольняє умову перевірки, він просто пропустить це число і перейде до наступної ітерації:

0
1
2
3
4
6
7
8

Слід зазначити, що оператори break і continue можна використовувати в будь-яких типах циклів.

Вкладені цикли

Деякі цикли можуть бути вкладеними в інші цикли. Наприклад:

for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
Console.Write($"{i * j} \t");
}
Console.WriteLine();
}

У цьому випадку цикл for (int i = 1; i < 10; i++) виконується 9 разів, тобто має 9 ітерацій. Але в межах кожної ітерації вкладений цикл for (int j = 1; j < 10; j++) виконується дев'ять разів. У результаті ця програма виведе таблицю множення.