Модул 3

Цикли (Loops)

Циклите позволяват на програмата да повтаря действия — от отпечатване на числа до четене на вход, докато потребителят не спре. Кога кой цикъл да изберем и как да избегнем най-честите капани.

Теория

Цикълът кара блок от код да се изпълнява многократно. Без цикли, за да отпечатаме числата от 1 до 100, щяха да ни трябват 100 реда код; с цикъл — три.

for цикълът събира всичко на едно място: инициализация (int i = 0), условие (i < 5) и стъпка (i++). Използваме го, когато броят повторения е известен предварително. Променливата i (итератор/брояч) живее само в цикъла.

while проверява условието преди всяко изпълнение — ако то е false от самото начало, тялото няма да се изпълни нито веднъж. do-while проверява условието след тялото, затова гарантира поне едно изпълнение — идеален за менюта и валидация на вход.

Две полезни ключови думи вътре в цикъл: break прекратява цикъла веднага, а continue прескача останалата част от текущата итерация и минава към следващата.

Циклите могат да се влагат — цикъл вътре в цикъл. Вътрешният изминава всичките си итерации за всяка една стъпка на външния: външен с 5 стъпки × вътрешен с 5 стъпки = 25 изпълнения на тялото. Вложените цикли са основата на таблици, матрици и фигури от символи.

Класически шаблон е акумулаторът: променлива, декларирана преди цикъла (int sum = 0;), която се обновява на всяка итерация (sum += i;). Същият шаблон работи за броене, произведение, най-голяма стойност — сърцето на повечето задачи с цикли.

Златни правила

for — когато знаем броя

Използвайте for цикъл, когато предварително знаете точния брой итерации (напр. "точно 10 пъти", "за всеки индекс от 0 до n-1").

while — когато зависи от условие

while е подходящ, когато цикълът зависи от условие и може да не се изпълни нито веднъж (напр. "докато има още данни").

do-while — поне веднъж

do-while гарантира, че кодът в тялото ще се изпълни поне един път, преди да се провери условието — идеален за въвеждане с повторение при грешка.

Пазете се от безкраен цикъл

Внимавайте да не забравите да обновите променливата в условието на while — иначе условието никога няма да стане false и програмата ще "забие".

Бърз справочник

Синтаксис на цикли

Вид цикълУпотреба / ОписаниеПример
forКогато знаем броя повторения.for (int i = 0; i < 5; i++) { }
whileДокато дадено условие е true.while (count > 0) { count--; }
do-whileИзпълнява се поне 1 път.do { } while (condition);
foreachЗа всеки елемент от колекция (вж. Модул 4).foreach (var item in list) { }

Управление на цикъла

Ключова думаКакво прави?
breakПрекратява цикъла незабавно и продължава след него.
continueПрескача остатъка от текущата итерация и минава към следващата.
i++ / i--Увеличава / намалява брояча с 1 (равно на i = i + 1).
i += 2Увеличава брояча с 2 — напр. за обхождане само на четни числа.

Код за анализ и пренаписване

for с брояч и while за валидация на парола

Program.cs
using System;

namespace ModuleThree
{
    class Program
    {
        static void Main(string[] args)
        {
            // For цикъл - отпечатване на числата от 1 до 5
            for (int i = 1; i <= 5; i++)
            {
                Console.WriteLine($"For цикъл: стъпка {i}");
            }

            // While цикъл - въвеждане на парола
            string password = "";
            while (password != "secret123")
            {
                Console.Write("Въведи парола: ");
                password = Console.ReadLine();
            }
            Console.WriteLine("Успешен вход!");
        }
    }
}

Какво се случва тук?

  • for (int i = 1; i <= 5; i++) — трите части: инициализация (i = 1, изпълнява се веднъж), условие (i <= 5, проверява се преди всяка итерация) и стъпка (i++, изпълнява се след всяка итерация).
  • Тъй като започваме от 1 и условието е <= 5, цикълът прави точно 5 итерации. Ако беше i < 5 — само 4.
  • while-ът се върти, докато паролата е грешна. Преди цикъла password е празен низ "" — той е различен от "secret123", затова влизаме в цикъла поне веднъж.
  • Ключовият момент: вътре в тялото password се обновява от потребителя. Ако забравим този ред, условието никога няма да стане false → безкраен цикъл.
  • Същата задача с do-while би била дори по-естествена: първо питаме, после проверяваме.

Вложени цикли и акумулатор

Program.cs
using System;

namespace ModuleThreeExtra
{
    class Program
    {
        static void Main(string[] args)
        {
            // Вложени цикли - малка таблица за умножение
            for (int i = 1; i <= 5; i++)
            {
                for (int j = 1; j <= 5; j++)
                {
                    Console.Write($"{i * j,4}"); // ,4 = подравняване в 4 позиции
                }
                Console.WriteLine(); // нов ред след всеки ред от таблицата
            }

            // Акумулатор - сума на числата от 1 до n
            Console.Write("Въведи n: ");
            int n = int.Parse(Console.ReadLine());

            int sum = 0;
            for (int i = 1; i <= n; i++)
            {
                sum += i;
            }
            Console.WriteLine($"Сумата от 1 до {n} е {sum}");
        }
    }
}

Какво се случва тук?

  • За всяко i (1…5) вътрешният цикъл по j се изпълнява изцяло (1…5) — затова тялото Console.Write се изпълнява 25 пъти, а Console.WriteLine() (новият ред) — само 5 пъти, по веднъж на ред.
  • {i * j,4} е форматиране с подравняване: стойността заема минимум 4 позиции, допълнени с интервали отляво — така колоните на таблицата стоят равно.
  • Акумулаторът sum се декларира преди цикъла (иначе щеше да се нулира на всяка итерация!) и се обновява с sum += i.
  • Проследете на ръка за n = 4: sum става 1 → 3 → 6 → 10. Точно това "натрупване" е най-често срещаният шаблон в задачите с цикли.
  • Същият шаблон с друга операция: count++ брои, product *= i умножава (внимание: започнете от 1, не от 0!), if (x > max) max = x намира максимум.

Внимавай! Чести грешки

Грешките, които почти всеки прави в тази тема — виж разликата между грешния и правилния код.

Забравено обновяване в while → безкраен цикъл

Грешно

int count = 5;
while (count > 0)
{
    Console.WriteLine(count);
} // върти се вечно!

Правилно

int count = 5;
while (count > 0)
{
    Console.WriteLine(count);
    count--;
}

Условието count > 0 никога не става false, защото count не се променя — програмата "забива". Всеки while трябва да променя нещо от условието си (или да има break).

Точка и запетая след for

Грешно

for (int i = 1; i <= 5; i++);
{
    Console.WriteLine("Здравей!");
} // печата само веднъж!

Правилно

for (int i = 1; i <= 5; i++)
{
    Console.WriteLine("Здравей!");
}

; след for (...) е празна команда, която става тялото на цикъла — цикълът се върти 5 пъти "на празно", а блокът отдолу се изпълнява само веднъж, след него. Компилира се без грешка!

Грешка с единица в границата (off-by-one)

Грешно

for (int i = 1; i < 10; i++)
{
    Console.WriteLine(i);
} // печата 1..9, без 10

Правилно

for (int i = 1; i <= 10; i++)
{
    Console.WriteLine(i);
} // печата 1..10

< срещу <= е разлика от една итерация. Правило за самопроверка: заместете наум i с граничната стойност (тук 10) и вижте дали условието я пуска.

Промяна на брояча вътре в тялото

Грешно

for (int i = 0; i < 5; i++)
{
    Console.WriteLine(i);
    i--; // бори се със стъпката - безкраен цикъл
}

Правилно

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

Стъпката на for е на едно място — в декларацията. Промяна на брояча и в тялото прави поведението трудно за проследяване (а тук — безкрайно). Ако логиката изисква "ръчно" движение, ползвайте while, където това е очаквано.

Задачи за самостоятелна работа

Опитай първо сам — подсказката е там само ако наистина закъсаш.

Задача 1: Четни числа от 1 до 100

Отпечатайте всички четни числа от 1 до 100, използвайки for цикъл.

Задача 2: Сума до "Stop"

Създайте програма, която чете числа от конзолата, докато потребителят не въведе "Stop", и накрая отпечатва тяхната сума.

Задача 3: FizzBuzz (класика!)

Отпечатайте числата от 1 до 100, но: за кратните на 3 печатайте "Fizz", за кратните на 5 — "Buzz", а за кратните и на 3, и на 5 — "FizzBuzz". Това е една от най-известните задачи за интервю!

Мини-тест за проверка

Отговори си наум (или на глас!) и чак тогава разкрий отговора.

1. Каква е разликата между while и do-while?

2. Кои са трите части в декларацията на for цикъла (напр. for(1; 2; 3))?

3. Какво прави ключовата дума continue в цикъл?

Речник на термините

Виж пълния речник на курса
Итерация
Едно изпълнение на тялото на цикъла. "Цикълът направи 5 итерации" = тялото се изпълни 5 пъти.
Брояч (итератор)
Променливата, която следи докъде е стигнал цикълът — по конвенция i (после j, k за вложените).
Безкраен цикъл
Цикъл, чието условие никога не става false — програмата "забива". Най-често от забравено обновяване на променливата в условието.
Вложени цикли
Цикъл вътре в цикъл. Вътрешният изминава всичките си итерации за всяка стъпка на външния.
Тяло на цикъла
Кодът между { }, който се повтаря на всяка итерация.
Акумулатор
Променлива, декларирана преди цикъла, която "натрупва" резултат по време на итерациите: sum += i;.
break / continue
break прекратява целия цикъл; continue прескача само текущата итерация.

Провери знанията

Бърз тест с избор от отговори върху термините на модула — с точки и моментална обратна връзка.

Провери знанията си

7 въпроса върху термините от модула. Показваме определение — ти избираш правилния термин.

Препоръки за този модул

  • Проследете цикъла на хартия: напишете таблица със стойностите на i при всяка итерация — това разкрива off-by-one грешките.
  • Класическа грешка: i <= 5 срещу i < 5 — едното прави 6 итерации, другото 5. Винаги проверявайте границите.
  • Ако цикълът ви "забива" — поставете Console.WriteLine вътре, за да видите дали и как се променя условието.
  • Вложени цикли (цикъл в цикъл) са нормални — вътрешният се изпълнява изцяло за всяка стъпка на външния.

Начален курс по C# — учебен наръчник и бърз справочник за студенти.

Натисни Ctrl K или / отвсякъде, за да търсиш.