JavaRush /Курси /C# SELF /Вкладені цикли та їх застосування

Вкладені цикли та їх застосування

C# SELF
Рівень 4 , Лекція 5
Відкрита

1. Вступ

Почнімо з питання: навіщо взагалі вкладати один цикл в інший? Річ у тім, що наші дані чи задачі часто організовано не просто в одну лінію, а, скажімо, у таблицю, сітку або навіть у багатовимірну структуру. Припустімо, ви хочете вивести на екран таблицю множення, пройтися по двовимірному масиву або перебрати всі пари елементів. Одного циклу тут явно недостатньо — потрібен цикл у циклі.

У програмуванні вкладений цикл — це як два будильники: зовнішній спрацьовує, а всередині нього запускається ще один, який дзвонитиме щоразу, доки перший активний. Тобто, поки триває одна «зовнішня» ітерація, внутрішня повністю проходить свій цикл (і робить це знову й знову для кожної ітерації зовнішнього).

Промовистий приклад — години та хвилини. Години — це зовнішній цикл від 0 до 23, а хвилини — внутрішній цикл від 0 до 59. На кожну зміну зовнішнього циклу внутрішній встигає перебрати всі свої значення.

2. Синтаксис вкладених циклів

У C# синтаксис вкладених циклів не відрізняється від звичайних — ви просто пишете один цикл у тілі іншого. Розгляньмо приклади з for і while:


for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 4; j++)
    {
        Console.Write($"{i},{j} ");
    }
    Console.WriteLine();
}
Вкладені цикли for для виведення координат

Тут зовнішній цикл керує змінною i (від 0 до 2), а внутрішній — змінною j (від 0 до 3). Для кожного значення i внутрішній цикл повністю проходить від j=0 до j=3. Якщо ви виконаєте цей код, побачите акуратну таблицю координат:

0,0 0,1 0,2 0,3 
1,0 1,1 1,2 1,3 
2,0 2,1 2,2 2,3 

Аналогічний приклад із використанням while:

int i = 0;
while (i < 3)
{
    int j = 0;
    while (j < 4)
    {
        Console.Write($"{i},{j} ");
        j++;
    }
    Console.WriteLine();
    i++;
}

Зверніть увагу: під час кожного проходу зовнішнього циклу змінну внутрішнього циклу (j) слід щоразу ініціалізувати заново, інакше ви побачите лише один рядок!

3. Приклади роботи вкладених циклів

Приклад 1: виведення шахової дошки (8×8)

Перше завдання — вивести на екран класичну шахову дошку у вигляді чорних і білих клітинок (нехай # — чорна, _ — біла). Зробімо це за допомогою вкладених циклів for:


for (int row = 0; row < 8; row++)
{
    for (int col = 0; col < 8; col++)
    {
        if ((row + col) % 2 == 0)
            Console.Write("_");
        else
            Console.Write("#");
    }
    Console.WriteLine();
}
Вкладені цикли для виведення шахової дошки

Результат:

_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_

Важливий момент: вкладеність гарантує, що для кожного рядка (row) ми повністю проходимо всі стовпці (col). Без вкладеності ми не отримали б структуру дошки — лише один рядок або один стовпець.

Приклад 2: таблиця множення

Класична задача для вкладених циклів! Давайте виведемо таблицю множення 1–9:


for (int i = 1; i <= 9; i++)
{
    for (int j = 1; j <= 9; j++)
    {
        Console.Write($"{i * j,3} ");
    }
    Console.WriteLine();
}
Вкладені цикли для виведення таблиці множення

Форматування ${i * j,3} додає відступи, щоб таблиця виглядала акуратно.

Результат:

   1   2   3   4   5   6   7   8   9
  2   4   6   8  10  12  14  16  18 
  3   6   9  12  15  18  21  24  27 
  4   8  12  16  20  24  28  32  36 
...
  9  18  27  36  45  54  63  72  81 

4. Вкладені цикли та керування ними — нюанси

Про вплив break і continue у вкладених циклах

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


for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 5; j++)
    {
        if (j == 3)
            break; // виходимо лише з внутрішнього циклу!
        Console.Write($"{i},{j} ");
    }
    Console.WriteLine();
}
break виходить лише з внутрішнього циклу

Результат:

0,0 0,1 0,2 
1,0 1,1 1,2 
2,0 2,1 2,2 

Якщо вам потрібно вийти одразу з двох вкладених циклів (наприклад, терміново завершити пошук під час першого збігу в таблиці), зазвичай використовують прапорець або спеціальний прийом (наприклад, return — якщо все відбувається всередині методу).

5. Візуалізація вкладених циклів

Іноді важко «побачити» послідовність виконання вкладених циклів. Погляньмо на блок-схему:

Візуалізація вкладених циклів

У табличній формі: скільки ітерацій загалом буде, якщо i від 1 до 3, а j — від 1 до 4?

i j (перебирається для кожного i) Ітерацій внутрішнього циклу
1 1, 2, 3, 4 4
2 1, 2, 3, 4 4
3 1, 2, 3, 4 4
Усього: 3 × 4 = 12

6. Помилки та підводні камені під час роботи з вкладеними циклами

Поширена помилка — неправильно ініціалізувати змінну внутрішнього циклу. Наприклад, оголосити її поза зовнішнім циклом і не скидати на кожному кроці. У результаті внутрішній цикл може не виконуватися взагалі або виконуватися неправильно.

int j = 0;
for (int i = 0; i < 3; i++)
{
    while (j < 4) // Ой! j уже міг дорівняти 4 після першої ітерації.
    {
        Console.Write($"{i},{j} ");
        j++;
    }
    Console.WriteLine();
}

Тут цикл відпрацює лише один раз. Не забувайте ініціалізувати змінні внутрішніх циклів всередині зовнішніх!

Крім того, якщо випадково написати два вкладені цикли з однаковими змінними, компілятор повідомить про помилку: таку змінну вже оголошено.


for (int i = 0; i < 3; i++)
{
    for (int i = 0; i < 3; i++)
    {
        Console.Write($"{i},{i} ");
    }
    Console.WriteLine();
}
1
Опитування
Цикли, рівень 4, лекція 5
Недоступний
Цикли
Вкладені цикли та їх застосування
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ