Теория
Цикълът кара блок от код да се изпълнява многократно. Без цикли, за да отпечатаме числата от 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 за валидация на парола
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би била дори по-естествена: първо питаме, после проверяваме.
Вложени цикли и акумулатор
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 в цикъл?
Речник на термините
Виж пълния речник на курсаi (после j, k за вложените).false — програмата "забива". Най-често от забравено обновяване на променливата в условието.{ }, който се повтаря на всяка итерация.sum += i;.break прекратява целия цикъл; continue прескача само текущата итерация.Провери знанията
Бърз тест с избор от отговори върху термините на модула — с точки и моментална обратна връзка.
Провери знанията си
7 въпроса върху термините от модула. Показваме определение — ти избираш правилния термин.
Препоръки за този модул
- Проследете цикъла на хартия: напишете таблица със стойностите на
iпри всяка итерация — това разкрива off-by-one грешките. - Класическа грешка:
i <= 5срещуi < 5— едното прави 6 итерации, другото 5. Винаги проверявайте границите. - Ако цикълът ви "забива" — поставете
Console.WriteLineвътре, за да видите дали и как се променя условието. - Вложени цикли (цикъл в цикъл) са нормални — вътрешният се изпълнява изцяло за всяка стъпка на външния.