---
course: ОАиП
lecture: 3
title: "Лекция №3. Управление потоком. Условные операторы и Циклы."
---

# Лекция №3. Управление потоком. Условные операторы и Циклы.

## §3.1 Условные операторы

**Условные операторы** являются фундаментальным элементом управления потоком выполнения программы. Они позволяют принимать решения на основе истинности или ложности заданных условий, обеспечивая **ветвление алгоритма** — выбор одного из нескольких возможных путей выполнения в зависимости от текущего состояния данных.

**Условные операторы** применяются для реализации логики, при которой определённые блоки кода должны выполняться только при соблюдении конкретных критериев. Это делает программы динамичными и адаптивными к различным входным данным и условиям среды.

В языках C# и C++ предусмотрены различные формы условных конструкций, каждая из которых предназначена для определённых сценариев. К ним относятся: **оператор условного ветвления** *if / else*, **оператор множественного выбора** *switch / case*, тернарный условный оператор и оператор безусловного перехода **goto**. Эти средства позволяют гибко управлять ходом выполнения программы, обеспечивая как простые, так и сложные логические структуры.

### §3.1.1 Операторы условного ветвления if / else

Одним из наиболее распространённых и универсальных средств управления потоком выполнения программы является оператор условного ветвления **if / else**. Он позволяет программе принимать решения на основе проверки логического условия: **если условие истинно**, выполняется один блок кода, **если ложно** — другой (или не выполняется вовсе).

Синтаксически оператор **if** представляет собой конструкцию, в которой после ключевого слова if в круглых скобках указывается выражение, интерпретируемое как логическое значение (*истина или ложь*). Если это выражение истинно (*в C++ — ненулевое значение, в C# — значение типа bool, равное true*), то выполняется соответствующий блок кода, заключённый в фигурные скобки (*или один оператор, если скобки опущены*). При невыполнении условия можно указать альтернативный блок кода с помощью ключевого слова **else**.

Синтаксис конструкции в языке C# и С++ одинаков:

text

```text
if (условное выражение)
{
    //Сделать нечто, когда условное выражение true;
}
else
{
    //Сделать другое, когда условное выражение false;
}
```

Часть **else** конструкции **if … else** является необязательной и может не использоваться в тех ситуациях, когда в противном случае не нужно делать ничего.

Конструкция допускает каскадное ветвление: с помощью цепочки **if – else if – else** можно проверять несколько взаимоисключающих условий последовательно. Это особенно полезно при реализации множественного выбора, когда необходимо выбрать один из нескольких возможных путей выполнения.

Проанализируем конструкцию в листинге ниже, обрабатывающую условное выражение и позволяющую пользователю решить, следует ли умножить или просуммировать два числа.

csharp

```csharp
using System;
class Program
{
    static void Main()
    {
        Console.WriteLine("Введите два числа:");

        int num1 = int.Parse(Console.ReadLine());
        int num2 = int.Parse(Console.ReadLine());

        Console.Write("Введите m для умножения: ");

        char userSelection = Console.ReadKey();
        int result = 0;
        
        if (userSelection == 'm')
        { 
             result = num1 * num2; 
        }
        else
        { 
            result = num1 + num2;  
        }

        Console.WriteLine($"Результат: {result}");
    }
}
```

Результат выполнения программы:

text

```text
Введите два числа:
25
56
Введите m для умножения: m
Результат: 1400
```

следующий запуск:

text

```text
Введите два числа:
25
56
Введите m для умножения: a
Результат: 81
```

Обратите внимание на использование оператора **if** в строке 13 и оператора **else** в строке 15. В строке 13 мы инструктируем компилятор выполнить умножение, если следующее за оператором **if** выражение (UserSelection == 'm') истинно (возвращает значение true), или выполнять сложение, если выражение ложно 3 (возвращает значение false).

Выражение (UserSelection == 'm') возвращает значение **true**, когда пользователь вводит символ (с учетом регистра), и значение **false** в любом другом случае.

Таким образом, эта простая программа моделирует блок – схему и демонстрирует, как ваше приложение может вести себя по-другому при иной ситуации:

![Рисунок 1 – Блок – схема if / else](/images/lectures/oaip/03/image-01.webp)

Нередки ситуации, когда необходимо проверить несколько разных условий, некоторые из которых зависят от результата оценки предыдущего условия. Разрешено вкладывать операторы **if** для выполнения таких требований. Вложенные операторы **if** имеют следующий синтаксис:

text

```text
if (условие 1)
{
   СделатьНечто 1;

   if (условие2)
   {
      СделатьНечто2;
   }
   else
   {
      СделатьНечтоДругое2;
   }
}
else
{
   СделатьНечтоДругое1;
}
```

Например:

csharp

```csharp
using System;

class Program
{
    static void Main()
    {
        Console.Write("Введите возраст: ");
        int age = int.Parse(Console.ReadLine());

        Console.Write("Есть ли у вас водительские права: ");
        char hasLicenseInput = Console.ReadKey().KeyChar;
 
        if (age >= 18)
        {
            Console.WriteLine("Вы совершеннолетний.");
            if (hasLicenseInput == 'y' || 
                hasLicenseInput == 'Y')
            {
                Console.WriteLine("Водите на здоровье.");
            }
            else 
            {
                Console.WriteLine("У вас нет прав :/");
            }
        }
        else
        { 
            Console.WriteLine("Вы несовершеннолетний!");
        }
 
        Console.WriteLine("Программа завершена.");
    }
}
```

При разных сценариях данная программа выведет разные результаты, например:

text

```text
Введите возраст: 20
Есть ли у вас водительские права: y
Вы совершеннолетний.
Водите на здоровье.
Программа завершена.
```

или

text

```text
Введите возраст: 25
Есть ли у вас водительские права: n
Вы совершеннолетний.
У вас нет прав :/
Программа завершена.	
```

### §3.1.2 Оператор множественного выбора switch / case

**Оператор switch**

— это средство множественного ветвления, предназначенное для выбора одного из нескольких альтернативных путей выполнения программы на основе значения выражения.

В отличие от цепочки **if – else if**, которая последовательно проверяет условия, **switch** обеспечивает прямой переход к ветви, соответствующей конкретному значению, что делает его более эффективным и читаемым в случаях, когда требуется сравнение одного выражения с несколькими константами.

Оператор **switch** оценивает выражение (называемое управляющим выражением) и сравнивает его значение с метками case, каждая из которых представляет собой константное выражение. При совпадении управление передаётся на соответствующую ветвь. Если ни одно из значений case не совпадает, выполняется ветвь **default** (если она присутствует).

**switch** особенно удобен при обработке:

- Выбора из меню.
- Обработки кодов ошибок.

Синтаксис на С++ и С# практически идентичен:

```csharp
switch (выражение) {
    case значение1:
        // код
        break;
    case значение2:
        // код
        break;
    default:
      // код по умолчанию
        break;
}
```

При использовании **switch … case** следует учитывать особенности и ограничения:

**1. Метки case должны быть уникальными и константными выражениями.**

- Нельзя использовать переменные или диапазоны напрямую (например, *case x: — ошибка*).

**2. Обязательность break (в C++ и C#).**

- Отсутствие **break** приводит к проваливанию (*fall-through*) — выполнению кода следующей ветви case, что может быть опасной ошибкой.
- В C# явный **fall-through** запрещён, если только ветвь не пустая (но это требует явного указания и считается плохой практикой).

**3. Наличие default — необязательно, но рекомендуется.**

Пример использования конструкции **switch … case**:

csharp

```csharp
Console.Write("Введите оценку (A, B, C, D, F): ");
char grade = Console.ReadKey().KeyChar;
Console.WriteLine();
 
switch (grade)
{
    case 'A':
        Console.WriteLine("Отлично!");
        break;
    case 'B':
        Console.WriteLine("Хорошо.");
        break;
    case 'C':
        Console.WriteLine("Удовлетворительно.");
        break;
    case 'D':
        Console.WriteLine("Неудовлетворительно.");
        break;
    case 'F':
        Console.WriteLine("Сдано.");
        break;
    default:
        Console.WriteLine("Некорректная оценка.");
        break;
}
```

Важно учитывать, что без **break** — после case 'A' выполнились бы все последующие ветви до **default**. **default** рекомендуется, потому что защищает от некорректного ввода.

### §3.1.3 Условный тернарный оператор

**Условный тернарный оператор (?:)**

— это компактная форма ветвления, позволяющая выбрать одно из двух значений в зависимости от истинности логического условия.

Являясь **единственным тернарным оператором** в языках C++ и C#, он предоставляет удобный способ записи простых условных выражений без необходимости использования полноценной конструкции **if / else**.

Синтаксически **оператор** состоит из трёх операндов, откуда и происходит название «тернарный»:

text

```text
condition ? expression_if_true : expression_if_false
```

- **condition** — логическое выражение, результат которого оценивается как true или false.
- **expression\_if\_true** — выражение, значение которого возвращается, если условие истинно.
- **expression\_if\_false** — выражение, возвращаемое при ложности условия.

Результатом всего выражения является значение одного из двух выражений, в зависимости от условия. Это именно выражение, а не оператор, что означает: оно возвращает значение и может использоваться в присваиваниях, возврате из функций, вызовах методов и других контекстах, где ожидается значение.

В стилистике if / else данный оператор можно записать в следующем виде:

text

```text
if(логическое условное выражение)
{
    выражение1 при true;
}
else
{
    выражение2 при false;
}
```

Пример на языке C#:

csharp

```csharp
int age = 20;
string status = age >= 18 ? "Совершеннолетний" 
                          : "Несовершеннолетний";
Console.WriteLine(status); // Вывод: Совершеннолетний
```

Пример на языке C++:

cpp

```cpp
#include <iostream>
using namespace std;
 
int main() {
    int a = 5, b = 10;
    int max = (a > b) ? a : b;
    cout << "Максимум: " << max << endl; // Вывод: 10
    return 0;
}
```

Важно понимать, что оба выражения (**expression\_if\_true и expression\_if\_false**) должны быть неявно приводимы к одному общему типу, иначе возникнет ошибка компиляции. Пример из C#:

csharp

```csharp
// Допустимо: string и string
string result = condition ? "Yes" : "No";
 
// Допустимо: int и double → результат double
double value = flag ? 5 : 3.14;
 
// Опасно: object и int — будет object, но с boxing
object obj = flag ? "text" : 123;
```

В C# компилятор выводит общий тип на основе выражений. В C++ тип результата определяется по правилам стандартных преобразований (например, *int* и *double → double*).

в C++ при смешении знаковых и беззнаковых типов знаковый операнд может быть преобразован к беззнаковому, что может привести к неожиданному поведению.

Например, -50 как **unsigned int** станет очень большим положительным числом.

cpp

```cpp
unsigned int u = 100;
signed int s = -50;
 
auto result = (u > s) ? u : s;
// Тип: unsigned int (внимание — здесь есть нюанс!)
```

### §3.1.4 Оператор goto

**Оператор goto**

— это оператор безусловного перехода, позволяющий передать управление непосредственно на метку (обозначенное имя) внутри той же функции. Несмотря на свою простоту и мощь, goto считается одним из наиболее спорных и критикуемых инструментов в структурном программировании.

Синтаксис в C++ и C#:

```csharp
goto label;
...
label: statement;
```

Оператор **goto** позволяет нарушить естественный порядок выполнения программы, перейдя к указанному участку кода. В теории он универсален — с его помощью можно реализовать любую управляющую структуру (циклы, ветвления), однако на практике его использование сильно ограничено из-за риска снижения читаемости и поддерживаемости кода.

Пример использования **goto** в С#:

csharp

```csharp
using System;
class Program
{
    static void Main()
    {
        Start:
        Console.Write("Введите 'да' или 'нет': ");
        string answer = Console.ReadLine();

        if (answer == "да")
        {
            Console.WriteLine("Вы сказали — да!");
        }
        else if (answer == "нет")
        { 
            Console.WriteLine("Вы сказали — нет!");
        }
        else
        {
            Console.WriteLine("Непонятно. Попробуйте снова.");
            goto Start; // Возвращаемся к метке Start
        }
    }
}
```

Пример использования goto на С++:

cpp

```cpp
FILE* file1 = fopen("file1.txt", "r");
if (!file1) goto error;
 
FILE* file2 = fopen("file2.txt", "w");
if (!file2) goto error;
 
// Работа с файлами...
fclose(file1);
fclose(file2);
return 0;
 
error:
    if (file1) fclose(file1);
    if (file2) fclose(file2);
    return -1;
```

**Спагетти – код**

— это код, порядок выполнения которого напоминает тарелку со спагетти (всё запутано и закручено), что крайне затрудняет следование порядку и понимание логики выполнения такого кода.

## §3.2 Циклические алгоритмы

**Циклические алгоритмы**

— это управляющие структуры, предназначенные для многократного выполнения одного и того же блока кода до тех пор, пока выполняется заданное условие или не будет пройден заданный диапазон значений. Последовательность действий, предназначенная для многократного исполнения, называется **телом цикла**.

Они необходимы в тех случаях, когда одну и ту же операцию нужно повторить много раз, но писать её вручную для каждого повторения неэффективно и непрактично. **Циклы** позволяют автоматизировать повторяющиеся действия, что делает программы компактными, гибкими и универсальными.

Например, **циклы** используются для:

- Обработки массивов и списков.
- Ввода и проверки данных с повторением при ошибке.
- Вычисления сумм, произведений, факториалов.
- Моделирования процессов, происходящих во времени.

### §3.2.1 Цикл с предусловием while

**Цикл while**

— это один из базовых операторов циклического выполнения, который предназначен для многократного выполнения блока кода при истинности заданного условия. Так как условие проверяется до входа в тело цикла, такой цикл называется **циклом с предусловием**.

Синтаксис на С++ и С# одинаков:

text

```text
while (условие)
{
    // тело цикла
}
```

Цикл работает следующим образом:

- Проверяется условие.
- Если оно истинно (true) — выполняется тело цикла.
- После выполнения тела управление возвращается к началу — условие проверяется снова.
- Если условие ложно (false) — цикл завершается, и программа продолжается дальше.

Для примера можно рассмотреть пример простого счетчика:

csharp

```csharp
int i = 1;

while (i <= 3)
{
    Console.WriteLine($"Итерация: {i}");
    i++;
}
```

Данная программа выведет следующее:

text

```text
Итерация: 1 Итерация: 2 Итерация: 3
```

Здесь переменная **i** увеличивается на **1** в каждой итерации. Как только **i** становится равным **4**, условие **i <= 3** становится ложным, и цикл завершается.

Если условие в **while** никогда не становится ложным, цикл будет выполняться бесконечно.

Первый случай бесконечного цикла

csharp

```csharp
while (true)
{
   Console.WriteLine("ВЕЧНОСТЬ");
}
```

Второй случай бесконечного цикла

csharp

```csharp
while (1)
{  
   Console.WriteLine("ВЕЧНОСТЬ");
}
```

Такой цикл намеренно используется, когда программа должна работать непрерывно (например, *сервер, игра, меню*), а выход из цикла организуется внутри с помощью **break**, **return** или условия.

csharp

```csharp
while (true)
{
    Console.Write("Введите 'выход' для завершения: ");
    string input = Console.ReadLine();

    if (input == "выход")
    {
        Console.WriteLine("Программа завершена.");
        break; // выходим из цикла
    }

    Console.WriteLine("Вы не вышли. Попробуйте снова.");
}
```

**Счетчик цикла**

— это целочисленная переменная, которая объявляется с единственной целью: считать, сколько раз выполнился цикл.

**Счетчикам цикла** часто дают простые имена, такие как **i**, **j** или **k**. А еще лучше использовать «реальные» имена для переменных, например, **count** или любое другое имя, которое предоставляет контекст использования этой переменной (например, *number*).

Каждое выполнение цикла называется итерацией (или *«повтором»*).

Поскольку тело цикла обычно является блоком, и поскольку этот блок выполняется по новой с каждым повтором, то любые переменные, объявленные внутри тела цикла, создаются, а затем и уничтожаются по новой.

cpp

```cpp
while (count <= 6)
{
   int z;

   cout << "Enter integer #" << count << ':';
   cin >> z;

   count++;
} // z уничтожается здесь по новой с каждой итерацией
```

Иногда нам может понадобиться выполнить что-то при достижении определенного количества итераций, например, вставить символ новой строки. Это легко осуществить, используя оператор остатка от деления со счетчиком цикла, как представлено ниже:

cpp

```cpp
int count = 1;
while (count <= 30)
{
   // Выводим числа до 10 (перед каждым числом добавляем0)
    if (count < 10)
    {
       cout << "0" << count << " ";
    }
    else 
    {
       cout << count << " ";
    }

    // Если счетчик цикла делится на 10 без остатка, то тогда
    // вставляем символ новой строки
    if (count % 10 == 0)
    {
        cout << "\n";
    }

    // Увеличиваем значение счетчика цикла на единицу
    ++count;
}
```

Результат выполнения программы:

wireframe

```
01 02 03 04 05 06 07 08 09 10

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30
```

Также одни циклы **while** могут быть вложены внутри других циклов **while**. В листинге ниже внутренний и внешний циклы имеют свои собственные счетчики. Однако, обратите внимание, условие внутреннего цикла использует счетчик внешнего цикла.

csharp

```csharp
using System;
 
class Program
{
    static void Main()
    {
        int outer = 1;

        while (outer <= 5)
        {
            int inner = 1;

            while (inner <= outer)
            {
                Console.Write(inner++ + " ");
            }

            // Вставляем символ новой строки в конце каждого ряда
            Console.WriteLine();
            ++outer;
        }
    }
}
```

Результат выполнения программы:

wireframe

```
1

1 2

1 2 3

1 2 3 4

1 2 3 4 5
```

### §3.2.2 Цикл с постусловием do – while

**Цикл с постусловием do – while**

— это управляющая конструкция, предназначенная для организации повторяющегося выполнения блока кода с гарантией его хотя бы одного выполнения.

В отличие от цикла с предусловием **while**, в котором условие проверяется до входа в тело, в **do – while** условие проверяется после выполнения тела цикла.

text

```text
do
{
    // тело цикла
} while (условие);
```

Обратите внимание:

- Тело цикла заключено между do и while.
- Условие записывается после тела и завершается точкой с запятой — это единственный случай в C-подобных языках, когда while заканчивается на точку с запятой.

Принцип работы:

1. Выполняется тело цикла (хотя бы один раз).
2. Проверяется условие продолжения.
3. Если условие истинно (true) — цикл повторяется.
4. Если условие ложно (false) — цикл завершается, и выполнение переходит к следующему оператору.

Таким образом, цикл **do – while** реализует логику: *«Сделай это хотя бы раз, а потом решай — повторять ли».*

csharp

```csharp
char choice;
do
{
    Console.WriteLine("\nМеню:");
    Console.WriteLine("1. Начать игру");
    Console.WriteLine("2. Настройки");
    Console.WriteLine("3. Выход");
    Console.Write("Выберите пункт: ");
    
    choice = Console.ReadKey().KeyChar;
    Console.WriteLine();
 
    switch (choice)
    {
        case '1': Console.WriteLine("Игра начата!"); 
           break;
        case '2': Console.WriteLine("Настройки открыты."); 
           break;
        case '3': Console.WriteLine("Выход..."); 
           break;
        default: Console.WriteLine("Неверный выбор."); 
           break;
    }
 
} while (choice != '3');  
```

Программа всегда показывает меню хотя бы один раз, даже если пользователь сразу выберет «Выход».

Переменная **choice** должна быть объявлена вне блоков **do / while**. Если бы переменная **choice** была объявлена внутри блока **do**, то она была бы уничтожена при завершении этого блока еще до проверки условия **while**. Но нам нужна переменная, которая будет использоваться в условии **while**, следовательно, переменная **choice** должна быть объявлена вне блока **do**.

### §3.2.3 Цикл со счетчиком for

**Цикл for**

— это одна из наиболее часто используемых управляющих конструкций в языках C# и C++. Он предназначен для организации повторяющегося выполнения блока кода с заранее известным или контролируемым количеством итераций, что делает его идеальным выбором в случаях, когда требуется выполнить действие определенное число раз или пройти по последовательности значений.

В С# и C++ единый синтаксис цикла for:

text

```text
for (инициализация; условие; обновление)
{
    // тело цикла
}
```

Цикл **for** состоит из трёх компонентов, заключённых в круглые скобки и разделённых точкой с запятой:

- **Инициализация** — выполняется один раз при входе в цикл. Обычно здесь объявляется и инициализируется счётчик.
- **Условие** — логическое выражение, проверяемое перед каждой итерацией. Если оно истинно (true) — цикл продолжается; если ложно — завершается.
- **Обновление** — выражение, выполняемое после каждой итерации (чаще всего — изменение счётчика: инкремент, декремент и т.п.).

Принцип работ:

1. Выполняется инициализация.
2. Проверяется условие.
3. Если условие истинно — выполняется тело цикла.
4. После тела — выполняется обновление.
5. Управление возвращается к проверке условия.
6. Цикл повторяется, пока условие остаётся истинным.

Если условие изначально ложно, тело цикла не выполнится ни разу.

Пример вывода чисел от 1 до 5:

csharp

```csharp
for (int i = 1; i <= 5; i++)
{
    Console.WriteLine($"Итерация: {i}");
}
```

что выведет:

text

```text
Итерация: 1
Итерация: 2
Итерация: 3
Итерация: 4
Итерация: 5
```

Конструкция **for** чрезвычайно гибкая:

- **Любое выражение инициализации**: можно объявить несколько переменных (в C++), или не объявлять вообще.
- **Любое логическое условие**: простое сравнение, сложное выражение с логическими операторами.
- **Любое обновление**: i++, i--, i += 2, i \*= 2 и т.д.

На счет первого пункта. В C# нельзя напрямую объявить две переменные в заголовке одного **for – цикла**, в отличие от языков вроде C или C++, где это допускается при условии, что они одного типа.

Неправильно (так нельзя в C#):

csharp

```csharp
for (int i = 0, j = 10; i < j; i++, j--) // Ошибка компиляции
{
    // ...
} // ВНИМАНИЕ! В С++ ТАКОЕ РАЗРЕШАЕТСЯ
```

Но такое можно обойти, если объявить переменные до цикла.

csharp

```csharp
int i, j;

for (i = 0, j = 10; i < j; i++, j--)
{
    Console.WriteLine($"i = {i}, j = {j}");
}
```

Пример: счётчик в обратном порядке

csharp

```csharp
for (int i = 5; i >= 1; i--)
{
    Console.WriteLine(i);
} 
```

Пример: шаг 2

csharp

```csharp
for (int i = 0; i < 10; i += 2)
{
    Console.WriteLine(i); // 0, 2, 4, 6, 8
}
```

По аналогии с циклом **while**, если условие всегда истинно, цикл будет выполняться бесконечно.

csharp

```csharp
for (int i = 0; true; i++)
{
    Console.WriteLine($"Бесконечность: {i}");
}
```

Но чаще всего используется каноническая форма бесконечного **for**:

csharp

```csharp
for (;;)
{
    Console.WriteLine("Я работаю вечно!");
}
```

### §3.2.4 Цикл на основе диапазона foreach

**Цикл foreach**

— это специализированная управляющая конструкция, предназначенная для упрощённого перебора элементов коллекции или контейнера. В отличие от циклов с явным управлением (*for, while*), **foreach** абстрагирует программиста от деталей индексации и итерирования, предоставляя прямой доступ к каждому элементу коллекции по одному за раз.

Цель **foreach** — обеспечить безопасный, читаемый и удобный способ обхода всех элементов последовательности, таких как массивы, списки, строки, множества и другие перечисляемые структуры. Он реализует принцип: «Для каждого элемента в коллекции выполнить действие».

Этот подход особенно полезен, когда: требуется обработать все элементы, нет необходимости в явной работе с индексами и важно избежать ошибок, связанных с выходом за границы.

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

text

```text
foreach (тип_элемента переменная in коллекция)
{
    // тело цикла
}
```

Пример:

csharp

```csharp
string text = "C#";

foreach (char c in text)
{
    Console.WriteLine(c); // Вывод: C, # (по символам)
} 
```

В C++ нет **foreach** как ключевого слова, но начиная с C++11, введён **range-based for** — функциональный аналог:

cpp

```cpp
for (auto& элемент : контейнер)
{
    // тело цикла
} 
```

Пример:

cpp

```cpp
#include <iostream>
#include <string>

using namespace std;
 
int main()
{
    string text = "C++";
    for (char c : text)
    {
        cout << c << endl; // Вывод: C, +, + (по символам)
    }
    return 0;
}
```

### §3.2.5 Операторы break и continue

Операторы **break** и **continue** являются вспомогательными средствами управления ходом выполнения циклов. Они позволяют нарушить стандартный порядок итераций в зависимости от условий, возникающих в ходе выполнения программы. Оба оператора используются внутри тела цикла и оказывают непосредственное влияние на его поведение, обеспечивая гибкость и точность управления потоком.

Оператор **break** немедленно прерывает выполнение текущего цикла и передаёт управление следующему оператору после цикла.

Применение:

- Досрочный выход из цикла при выполнении условия.
- Выход из switch (в C# и C++).
- Прерывание поиска, обработки ошибок, выход из бесконечного цикла.

Пример на С#:

csharp

```csharp
int i = 1;
while (i <= 10)
{
    if (i == 5)
    {
        break; // выход из цикла
    }

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

Console.WriteLine("Цикл завершён.");
```

Вывод:

text

```text
i = 1
i = 2
i = 3
i = 4
Цикл завершён.
```

Пример на С++:

cpp

```cpp
#include <iostream>
using namespace std;
 
int main()
{
    for (int i = 0; i < 6; i++)
    {
        if (i == 3)
        {
            break;
        }

        cout << "i = " << i << endl;
    }

    cout << "Цикл завершён." << endl;
    return 0;
}
```

Вывод:

text

```text
i = 0
i = 1
i = 2
Цикл завершён.
```

**break** работает только с **ближайшим** (*внутренним*) циклом. Чтобы выйти из вложенных циклов, требуется **goto** (в C#) или **флаг** (в C++).

Оператор **continue** прерывает текущую итерацию и переходит к следующей, пропуская оставшуюся часть тела цикла.

Применение:

- Пропуск определённых значений.
- Фильтрация данных.
- Упрощение условной логики без вложенных if.

Пример на C#:

csharp

```csharp
for (int i = 1; i <= 5; i++)
{
    if (i == 3)
    {
        continue; // пропустить итерацию
    }

    Console.WriteLine($"i = {i}");
}

Console.WriteLine("Цикл завершён."); 
```

Вывод:

text

```text
i = 1
i = 2
i = 4
i = 5
Цикл завершён.
```

Пример на С++:

cpp

```cpp
while (i < 5)
{
    i++;
    if (i % 2 == 0) 
    { 
        continue; // пропустить чётные
    }

    cout << "Нечётное: " << i << endl;
}
```

Вывод:

text

```text
Нечётное: 1
Нечётное: 3
Нечётное: 5
Цикл завершён.
```

Так же **break** и **continue** разрешается использовать вместе:

csharp

```csharp
for (int i = 1; i <= 6; i++)
{
    if (i == 3)
    {
        continue; // пропустить 3
    }

    if (i == 6)
    {
        break; // выйти перед 6
    }

    Console.WriteLine($"i = {i}");
}
```

Вывод:

text

```text
i = 1
i = 2
i = 4
i = 5
```

В данном коде пропущено **3** из-за использования конструкции **continue**, **6** не достигнуто из-за **break**.
