# Управляющие конструкции: условные операторы и циклы

## Введение

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

Глава "Управляющие конструкции: условные операторы и циклы" направлена на раскрытие ключевых аспектов этих конструкций, начиная с простых условий и заканчивая более сложными циклами. Мы рассмотрим, как использовать условные операторы для принятия решений в зависимости от различных условий, а также как циклы обеспечивают эффективную обработку повторяющихся задач.

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

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

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

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

#### **`if` - простое условие**

Оператор `if` позволяет выполнить блок кода, если указанное условие истинно. Если условие ложно, код внутри блока `if` пропускается.

```csharp
csharpCopy codeint number = 7;
if (number > 5)
{
    Console.WriteLine("Число больше 5");
}
```

#### **`else` - ветвление при ложном условии**

Оператор `else` используется в паре с `if` и выполняет блок кода, если условие `if` ложно.

```csharp
csharpCopy codeint age = 16;
if (age >= 18)
{
    Console.WriteLine("Доступ разрешен");
}
else
{
    Console.WriteLine("Доступ запрещен. Вам несовершеннолетнему.");
}
```

#### **`else if` - дополнительные условия**

Оператор `else if` добавляет дополнительные условия к проверке `if`. Блок кода внутри `else if` выполняется, если предыдущее условие ложно, а текущее – истинно.

```csharp
csharpCopy codeint mark = 85;
if (mark >= 90)
{
    Console.WriteLine("Отличная оценка");
}
else if (mark >= 70)
{
    Console.WriteLine("Хорошая оценка");
}
else
{
    Console.WriteLine("Плохая оценка");
}
```

#### **Тернарный оператор**

Тернарный оператор (`? :`) предоставляет компактный синтаксис для создания условий в одной строке кода.

```csharp
csharpCopy codeint x = 10;
int y = 5;
string result = (x > y) ? "x больше y" : "y больше или равно x";
Console.WriteLine(result);
```

#### **`switch` - множественный выбор**

Оператор `switch` предоставляет возможность создавать множественные ветвления в зависимости от значения выражения.

```csharp
csharpCopy codeint day = 3;
switch (day)
{
    case 1:
        Console.WriteLine("Понедельник");
        break;
    case 2:
        Console.WriteLine("Вторник");
        break;
    case 3:
        Console.WriteLine("Среда");
        break;
    default:
        Console.WriteLine("День недели не определен");
        break;
}
```

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

## Циклы

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

#### **`while` - цикл с предусловием**

Цикл `while` проверяет условие перед каждой итерацией. Если условие истинно, выполняется блок кода внутри цикла.

Пример:

```csharp
csharpCopy codeint count = 0;
while (count < 5)
{
    Console.WriteLine($"Текущее значение счетчика: {count}");
    count++;
}
```

В данном примере цикл будет выполняться, пока `count` меньше 5. После каждой итерации значение `count` увеличивается на единицу.

#### **`do-while` - цикл с постусловием**

Цикл `do-while` гарантирует выполнение блока кода хотя бы один раз, так как условие проверяется после каждой итерации.

Пример:

```csharp
csharpCopy codeint number;
do
{
    Console.WriteLine("Введите положительное число:");
} while (!int.TryParse(Console.ReadLine(), out number) || number <= 0);
```

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

#### **`for` - цикл с определенным количеством итераций**

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

Пример:

```csharp
csharpCopy codefor (int i = 0; i < 5; i++)
{
    Console.WriteLine($"Текущее значение переменной i: {i}");
}
```

В данном примере цикл выполняется от 0 до 4 (включительно) с шагом 1.

#### **`foreach` - цикл для перебора элементов в коллекциях**

Цикл `foreach` предназначен для перебора элементов в коллекциях, таких как массивы, списки и другие объекты, реализующие интерфейс IEnumerable.

Пример:

```csharp
csharpCopy codestring[] colors = { "Красный", "Зеленый", "Синий" };
foreach (string color in colors)
{
    Console.WriteLine($"Текущий цвет: {color}");
}
```

Цикл `foreach` автоматически проходит по всем элементам коллекции `colors`.

#### **Прерывание циклов (`break` и `continue`)**

Оператор `break` используется для прерывания выполнения цикла, а `continue` позволяет пропустить текущую итерацию и перейти к следующей.

Пример:

```csharp
csharpCopy codefor (int i = 0; i < 10; i++)
{
    if (i == 5)
        break; // Прервать цикл при достижении i == 5
    if (i % 2 == 0)
        continue; // Пропустить четные значения i
    Console.WriteLine($"Текущее значение i: {i}");
}
```

В данном примере цикл `for` прервется при `i == 5` и пропустит четные значения, продолжая выполнение.

Циклы в C# предоставляют гибкость и мощные инструменты для обработки данных и выполнения многократных операций. Понимание различных видов циклов и их правильное применение улучшат структуру и эффективность вашего кода.

## Нестандартные управляющие конструкции

Помимо стандартных условных операторов и циклов, в языке программирования C# существуют несколько нестандартных управляющих конструкций, которые могут быть полезны в определенных сценариях. Ниже представлены две из них: `goto` и `yield`.

#### **`goto` - метка и переход**

Оператор `goto` предоставляет возможность создавать метки в коде и осуществлять переход к этим меткам. Использование `goto` требует осторожности, так как оно может сделать код менее читаемым и сложным для понимания.

Пример:

```csharp
csharpCopy codeint i = 0;
startLoop:
    Console.WriteLine(i);
    i++;
    if (i < 5)
        goto startLoop;
```

В данном примере цикл может быть заменен на более структурированный код, но `goto` служит для демонстрации возможности перехода к метке.

#### **`yield` - управление потоком в итераторах**

Оператор `yield` используется в контексте итераторов для управления потоком выполнения. Он позволяет создавать итерируемые последовательности без необходимости вычислять все значения сразу.

Пример:

```csharp
csharpCopy codepublic IEnumerable<int> GenerateNumbers()
{
    for (int i = 0; i < 5; i++)
    {
        yield return i;
    }
}
```

В данном примере метод `GenerateNumbers` возвращает последовательность чисел от 0 до 4. Оператор `yield` приостанавливает выполнение метода и возвращает текущее значение, сохраняя состояние для следующего вызова.

Использование `goto` и `yield` требует внимательного обращения, чтобы избежать создания сложных и трудноподдерживаемых конструкций. Однако они могут быть полезны в определенных сценариях, где стандартные управляющие конструкции не справляются.

## Лучшие практики при использовании управляющих конструкций

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

#### **Читаемость кода**

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

```csharp
csharpCopy code// Плохо
int a = 10;
int b = 5;
for (int i = 0; i < a; i++)

// Хорошо
int numberOfIterations = 10;
int step = 5;
for (int iterationCount = 0; iterationCount < numberOfIterations; iterationCount++)
```

* **Форматируйте код правильно:** Используйте правильные отступы, пробелы и пустые строки для лучшей структурированности кода.

```csharp
csharpCopy code// Плохо
for(int i=0;i<10;i++){
Console.WriteLine(i);}

// Хорошо
for (int i = 0; i < 10; i++)
{
    Console.WriteLine(i);
}
```

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

```csharp
csharpCopy code// Плохо
if (age >= 18 && (isStudent || hasJob) && !isUnderProbation)

// Хорошо
bool isAdult = age >= 18;
bool isEmployedOrStudent = isStudent || hasJob;
bool isNotUnderProbation = !isUnderProbation;
if (isAdult && isEmployedOrStudent && isNotUnderProbation)
```

#### **Эффективность выполнения**

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

```csharp
csharpCopy code// Плохо
for (int i = 0; i < GetExpensiveOperationResult(); i++)

// Хорошо
int result = GetExpensiveOperationResult();
for (int i = 0; i < result; i++)
```

* **Оптимизируйте условия:** Если условие всегда истинно или ложно в определенных сценариях, рассмотрите возможность оптимизации или реорганизации кода.

```csharp
csharpCopy code// Плохо
if (true)
{
    // ...
}

// Хорошо
// Обозначить намерение сделать что-то всегда
const bool alwaysDoSomething = true;
if (alwaysDoSomething)
{
    // ...
}
```

#### **Избегание злоупотребления `goto`**

* **Используйте `goto` осторожно:** Избегайте чрезмерного использования `goto`, так как это может усложнить понимание кода и создать трудноподдерживаемую логику.

```csharp
csharpCopy code// Плохо
startLoop:
    // ...
    goto startLoop;

// Хорошо
while (condition)
{
    // ...
}
```

#### **Разумное применение тернарного оператора**

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

```csharp
csharpCopy code// Плохо
int result = (condition1 && condition2) ? value1 + value2 : value3 - value4;

// Хорошо
int result = (condition1 && condition2)
    ? CalculateSum(value1, value2)
    : CalculateDifference(value3, value4);
```

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

```csharp
csharpCopy code// Плохо
int result = condition1
    ? (condition2 ? value1 : value2)
    : (condition3 ? value3 : value4);

// Хорошо
int result = CalculateResult(condition1, condition2, condition3, value1, value2, value3, value4);
```

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

## Заключение

Управляющие конструкции в языке программирования C# являются фундаментальным элементом разработки, обеспечивая программистам мощные средства управления ходом выполнения кода. В данной главе мы рассмотрели разнообразные аспекты управляющих конструкций, начиная от условных операторов и циклов, заканчивая нестандартными конструкциями, такими как `goto` и `yield`.

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

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

Бережное отношение к нестандартным управляющим конструкциям, таким как `goto`, и разумное применение тернарного оператора способствуют созданию кода, который не только легко понимать, но и легко поддерживать. В конечном итоге, грамотное использование управляющих конструкций в разработке программ на C# является ключевым компонентом создания надежных и эффективных приложений.

***

## Упражнения

#### **Упражнение 1: Калькулятор условий**

**Задача:** Напишите программу на C#, которая запрашивает у пользователя два числа и оператор (‘+’, ‘-’, ‘\*’ или ‘/’). В зависимости от введенного оператора программа выполняет соответствующую операцию и выводит результат.

<details>

<summary>Решение</summary>

```csharp
// Упражнение 1: Калькулятор условий
using System;

class Program
{
    static void Main()
    {
        // Ввод данных
        Console.Write("Введите первое число: ");
        double number1 = double.Parse(Console.ReadLine());

        Console.Write("Введите второе число: ");
        double number2 = double.Parse(Console.ReadLine());

        Console.Write("Введите оператор (+, -, *, /): ");
        char operatorSymbol = char.Parse(Console.ReadLine());

        // Выполнение операции в зависимости от введенного оператора
        switch (operatorSymbol)
        {
            case '+':
                Console.WriteLine($"Результат сложения: {number1 + number2}");
                break;
            case '-':
                Console.WriteLine($"Результат вычитания: {number1 - number2}");
                break;
            case '*':
                Console.WriteLine($"Результат умножения: {number1 * number2}");
                break;
            case '/':
                if (number2 != 0)
                {
                    Console.WriteLine($"Результат деления: {number1 / number2}");
                }
                else
                {
                    Console.WriteLine("Деление на ноль невозможно.");
                }
                break;
            default:
                Console.WriteLine("Неверный оператор.");
                break;
        }
    }
}
```

</details>

#### **Упражнение 2: Проверка четности**

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

<details>

<summary>Решение</summary>

```csharp
// Упражнение 2: Проверка четности
using System;

class Program
{
    static void Main()
    {
        // Ввод данных
        Console.Write("Введите целое число: ");
        int number = int.Parse(Console.ReadLine());

        // Проверка четности и вывод результата
        if (number % 2 == 0)
        {
            Console.WriteLine("Число четное.");
        }
        else
        {
            Console.WriteLine("Число нечетное.");
        }
    }
}
```

</details>

#### **Упражнение 3: Таблица умножения**

**Задача:** Напишите программу, которая выводит на экран таблицу умножения для заданного числа. Пользователь вводит число, и программа выводит умножение этого числа на числа от 1 до 10.

<details>

<summary>Решение</summary>

```csharp
// Упражнение 3: Таблица умножения
using System;

class Program
{
    static void Main()
    {
        // Ввод данных
        Console.Write("Введите число для таблицы умножения: ");
        int multiplier = int.Parse(Console.ReadLine());

        // Вывод таблицы умножения для заданного числа
        for (int i = 1; i <= 10; i++)
        {
            Console.WriteLine($"{multiplier} * {i} = {multiplier * i}");
        }
    }
}
```

</details>

#### **Упражнение 4: Поиск максимального значения**

**Задача:** Напишите программу, которая запрашивает у пользователя три числа и определяет максимальное из них. Выведите результат на экран.

<details>

<summary>Решение</summary>

```csharp
// Упражнение 4: Поиск максимального значения
using System;

class Program
{
    static void Main()
    {
        // Ввод данных
        Console.Write("Введите первое число: ");
        int number1 = int.Parse(Console.ReadLine());

        Console.Write("Введите второе число: ");
        int number2 = int.Parse(Console.ReadLine());

        Console.Write("Введите третье число: ");
        int number3 = int.Parse(Console.ReadLine());

        // Поиск максимального значения и вывод результата
        int maxNumber = Math.Max(number1, Math.Max(number2, number3));
        Console.WriteLine($"Максимальное число: {maxNumber}");
    }
}
```

</details>

#### **Упражнение 5: Генератор случайных чисел**

**Задача:** Напишите программу, которая генерирует случайное число от 1 до 100 и предлагает пользователю угадать это число. Программа должна предоставлять подсказки (больше/меньше), пока пользователь не угадает число.

<details>

<summary>Решение</summary>

```csharp
// Упражнение 5: Генератор случайных чисел
using System;

class Program
{
    static void Main()
    {
        // Генерация случайного числа от 1 до 100
        Random random = new Random();
        int secretNumber = random.Next(1, 101);

        int userGuess;

        do
        {
            // Ввод предположения пользователя
            Console.Write("Угадайте число от 1 до 100: ");
            userGuess = int.Parse(Console.ReadLine());

            // Проверка и вывод подсказки
            if (userGuess < secretNumber)
            {
                Console.WriteLine("Загаданное число больше.");
            }
            else if (userGuess > secretNumber)
            {
                Console.WriteLine("Загаданное число меньше.");
            }
            else
            {
                Console.WriteLine("Поздравляю! Вы угадали число.");
            }
        } while (userGuess != secretNumber);
    }
}
```

</details>

***

## Вопросы

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

Какие ключевые слова используются для создания условных операторов в C#?

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

В чем отличие между операторами `if-else` и `switch` в C#?

#### **Цикл for**

Как выглядит структура оператора цикла `for` в C#?

#### **Цикл while**

Какова основная идея оператора цикла `while` в C#?

#### **Цикл do-while**

В чем отличие между циклами `while` и `do-while` в C#?

#### **Оператор break**

Для чего используется оператор `break` в циклах в C#?

#### **Оператор continue**

Как работает оператор `continue` в циклах в C#?

#### **Вложенные циклы**

Что такое вложенные циклы, и в каких ситуациях их целесообразно использовать?

#### **Операторы инкремента и декремента**

Какие операторы в C# используются для увеличения и уменьшения значения переменной на единицу?

#### **Безусловный оператор goto**

Почему использование оператора `goto` считается не рекомендуемым в языке C#?

***

## Тесты

{% embed url="<https://docs.google.com/forms/d/e/1FAIpQLSeoBrBj8fZCTcu9fgcuO7JOeogmrYKuUPI_VX20XISZNlwb1A/viewform?usp=sf_link>" fullWidth="true" %}
