Тема 5. Розгалуження та цикли

Автор

Юрій Клебан

Опубліковано

2/2/25

Keywords

C#, розгалуження, умовні оператори, if, else, switch, тернарний оператор, цикли, for, while, do-while, foreach, оператор break, continue

Лекція охоплює основи розгалужень і циклів у C#. Студенти дізнаються про умовні оператори if-else та switch, а також про використання тернарного оператора. У другій частині лекції розглядаються цикли for, while, do-while і foreach, їх призначення та відмінності. Також пояснюється використання операторів break і continue для керування потоком виконання програм. Лекція супроводжується прикладами коду та практичними завданнями.


5.1.Оператори розгалуження

У C# для реалізації розгалужень коду використовуються спеціальні оператори: if-else, switch.

5.1.1. Оператор if-else

Якщо є потреба перевірити у коді програми виконання якоїсь умови та за її результатами перейти до одного із блоків програми зазвичай використовують оператор if-else. Загальний вигляд формату використання оператора if-else зображений у лістингу 4.1.

Лістинг 5.1.Формат використання оператора if-else

  if (умова)
  {
    //інструкція
  }
  else
  {
    //інструкція
  }

Вираз «умова» завжди повинен повертати результат у вигляді елемента логічного типу. Тобто, «умова» може бути або true, або false.

Якщо «умова» рівна true, то виконається інструкція (або код) записана у дужках після if. Якщо ж «умова» рівна false, то виконається інструкція записана у дужках після else.

Якщо після if або else тільки одна інструкція (можна ототожнити з один рядком коду), то «фігурні» дужки {} не є обов’язковими.

Розглянемо приклад: написати програму, що визначає парність/непарність числа. Тобто, користувач вводить число, а програма показує на консоль у текстовому вигляді: «парне» або «непарне» (лістинг 5.2).

Лістинг 5.2. Перевірка числа на парність

  int a = int.Parse(Console.ReadLine());
  if(a % 2 == 0)
    Console.WriteLine("парне");
  else
    Console.WriteLine("непарне");

Конструкції if-else можуть вкладеними одна в одну без обмежень по глибині (лістинг 5.3). Проте дуже глибокої вкладеності варто уникати, адже це ускладнює читання та розуміння коду програми.

if є обов’язковим і повинно існувати у всіх подібних конструкціях, у той же час else – необов’язковий.

Лістинг 5.3. Приклад використання вкладених операторів if-else

  if (умова1)
  {
    if (умова2)
    {
      //інструкція
    }
  }

Також конструкція if-else може мати структуру дерева із багатьма розгалуженнями. Така структура зазвичай записується якif-else-if (лістинг 5.4).

Лістинг 5.4. Формат запису if-else-if

  if (умова)
  {/*код*/}
  else if (умова)
      {/*код*/}
      else if (умова)
          {/*код*/}
          else {/*код*/}

Вирази обчислюються зверху-вниз. Якщо один із виразів («умова») отримає істинний результат, то програмний код, пов’язаний із цією гілкою розгалуження виконається, а всі інші гілки будуть пропущені. Якщо ж не виконається жодна з умов, то буде запущено код всередині останньої інструкції else (у цьому випадку else теж не обов’язковий).


5.1.2. Оператор switch

Наступною інструкцією для реалізації розгалуження, або точніше вибору значення є switch. Switch забезпечує багатонаправлене розгалуження і дозволяє вибрати один із варіантів із даної множини альтернатив. Ця конструкція працює наступним чином:

  1. Значення виразу послідовно порівнюється з константами із заданого списку.
  2. При виявленні збігу для однієї з умов порівняння виконується послідовність інструкцій, пов’язана з цією умовою.

Оператор switch приймає значення цілочисельного типу (наприклад, char, byte, int, long тощо) або тип string. Типи даних, що представляють числа з дробовою частиною не можуть бути використані даному випадку.

Switch складається з набору case конструкцій. Кожна конструкція case представлена у вигляді літерала такого ж типу даних як і значення, що приймає switch. Усі case конструкції у межах одного switch можуть мати тільки унікальні константи. Формат оголошення продемонстровано у лістингу 4.5.

Лістинг 5.5. Формат оголошення switch

  switch (значення)
  {
    case костанта1:
      //інструкція
      break;
    case костанта2:
      //інструкція;
      break;
    ...
    default:
      //інструкція
      break;
}

Case-конструкції перевіряються у порядку розміщення. Вкінці кожного case повинно бути ключове слово break, що означає вихід із switch.

Також у switch використовують конструкцію default, яка не є обов’язковою і виконується лише у випадку, якщо жодна із case-конструкцій так і не відпрацювала.

Для розуміння принципів роботи switch розглянемо приклад. Написати програму, яка у залежності від введеної цифри виводить на консоль пору року: 1 — «Зима», 2 — «Весна», 3 — «Літо», 4 — «Осінь», інше число — «Введіть число із діапазону [1;4]» (Лістинг 5.6).

Лістинг 5.6. Розв’язання задачі «Пори року» з використанням switch

  Console.Write("Введіть номер пори року [1;4]:\t");
  int res = int.Parse(Console.ReadLine());
  
  switch (res)
  {
    case 1:
      Console.WriteLine("Зима");
      break;
    case 2:
      Console.WriteLine("Весна");
      break;
   case 3:
     Console.WriteLine("Літо");
     break;
   case 4:
     Console.WriteLine("Зима");
     break;
   default:
     Console.WriteLine("Введіть число від 1 до 4");
     break;
  }

Результат виконання:

  Введіть номер пори року [1;4]: 2
  Весна

У випадку, якщо потрібно, щоб одна і та ж інструкція виконувалася для кількох різних значень констант код switch може мати вигляд як на лістингу 4.7.

Лістинг 5.7. Приклад використання switch

  Console.Write("Введіть оцінку [1-12]:\t");
  int res = int.Parse(Console.ReadLine());
  
  switch (res)
  {
     case 1:
     case 2:
     case 3:
       Console.WriteLine("Низький рівень");
       break;
     ...
     case 10:
     case 11:
     case 12:
       Console.WriteLine("Високий рівень");
       break;
  }

У прикладі показано виведення шкільких оцінок відповідно до 12-ти бальної системи по рівнях.


5.1.3. Тернарний оператор

Інколи для простої заміни оператора if-else використовують тернарний оператор. Тернарний оператор отримав свою назву від кількості задіяних виразів (3) і позначається символами ?:. Загальний формат запису тернарного оператора має вигляд:

Вираз_1 ? Вираз_2 : Вираз_3

де Вираз_1 — логічний вираз, за рузультатом обчислення якого визначається наступна дія, Вираз_2 — значення, що повертається, якщо результатом Виразу_1 є true, Вираз_3 — значення, що повертається, якщо результатом Виразу_1 є false.

Для демонстрації роботи тернарного оператора спробуємо розвязати задачу визначення модуля цілого числа. Можна було б для також задачі скористатися оператором if-else, проте тернарний оператор спрощує синтаксис запису такого коду (лістинг 5.8).

Лістинг 5.8. Приклад використання тернарного оператора: визначення модуля числа

  Console.Write("Введіть ціле число:\t");
  int a = Convert.ToInt32(Console.ReadLine());
  int absval = (a > 0) ? a : -a;
  Console.WriteLine("ABS: {0}", absval);

Увага! Для знаходження модуля числа у C# існує спеціальний метод Math.Abs(значення).


5.2. Використання циклів під час написання програм

Для виконання повторюваних операцій у програмуванні використовуються цикли. Цикл – це спеціальна конструкція мови програмування для багаторазового виконання набору інструкцій. У C# існують 4 типи циклів: for, while, do-while, foreach.

5.2.1. Цикл for

Загальний синтаксис оголошення циклу for має вигляд як на лістингу 4.9. Блок «ініціалізація» використовується для оголошення керуючих змінних циклу. У другому блоці оголошення циклу перевіряється умова можливості продовження виконання циклу. Якщо «умова» повератає false, то виконання циклу завершується. Блок «інструкції» довляє виконувати дії над змінними програми. Найчастіше у цьому блоці відбуваються дії над керуючими змінними.

Лістинг 5.9. Синтаксис оголошення циклу for

  for(ініціалізація; умова; інструкції)
  {
    //код;
  }

Усі три блоки «ініціалізація», «умова» та «інструкції» не є обов’язковим у оголошенні циклу for, проте розділювачі потрібно записати обов’язково (Лістинг 5.10).

Лістинг 5.10. Вічний цикл for

  for(;;)
  {
    //код;
  }

Розглянемо приклад задачі: знайти суму усіх чисел від 1 до 10-ти включно (Лістинг 5.11).

Лістинг 5.11. Приклад використання циклу for

  int sum = 0;
  for (int i = 1; i <= 10; ++i)
    sum += i;

Якщо після for тільки одна інструкція, то «фігурні» дужки {} не є обов’язковими.

Для деталізації розглянемо ще один приклад програми і розберемо його (Лістинг 5.12).

Лістинг 5.12. Приклад використання циклу for

  int sum = 0;
  for (int i = 0, j = 1; sum < 20; i++, j += 2)
  {
      sum += i + j;
  }

Проаналізуємо, як повинна відпрацювати дана програма та які значення будуть мати змінні на кожній ітерації циклу.

Також у циклах можуть використовуватися ключові слова break та continue.

Ключове слово break зупиняє виконання циклу і переходить до виконання наступного після циклу коду. Ключове слово continue переводить цикл на нову ітерацію.

На прикладі лістингу 4.13. розглянемо використання цих операторів. Програма працює наступним чином: цикл послідовно проходить по усіх числах та виводить їх на екран; якщо число кратне 3-м, то цикл переходить на нову ітерацію; якщо число кратне 7-ми, то цикл закінчується.

Лістинг 5.13. Приклад використання операторів break та continue у циклах

  for (int i = 0; i < 10; ++i)
  {
     if (i%3 == 0)
        continue;
     
     Console.Write(i + " ");
     
     if(i%7==0)
        break;
  }

Результат виконання:

  1 2 4 5 7

5.2.2.Цикли while та do-while

Цикл while у мінімально модифікованому вигляді є частиною практично усіх мов програмування. Тіло циклу виконується до тих пір, поки залишається істинною умова while. Синтаксис оголошення має вигляд:

  while (умова) { 
      //інструкції 
  }

Цикл while може працювати з передумовою та післяумовою. Цикл з передумовою спочатку перевіряє умову, а після цього виконує або не виконує ітерацію циклу. Цикл з післяумовою спочатку виконується (одна ітерація), а потім тільки перевіряється умова. Таким чином можна зробити висновок, що цикл з післяумовою виконається мінімум 1 раз. Синтаксис огололшення циклу while з післяумовою:

  do 
  { 
      //інструкції 
  } while (умова);

Для порівняння циклів while розглянемо лістинги 4.14 та 4.15. У першому випадку не буде виведено на консоль нічого, у другому буде виведено «5».

Лістинг 5.14. Приклад використання циклу while з передумовою

  int x = 5;
  while (x < 5)
  {
       Console.Write(x + " ");
  }

Лістинг 5.15. Приклад використання циклу while з післяумовою

  int x = 5;
  do
  {
      Console.Write(x + " ");
  } while (x < 5);

Робота з циклом foreach буде розглянута у розділі 6 разом із вивченням масивів.


Приклади розв’язання задач

Приклад 4.1. Написати програму, яка генерує і виводить на консоль 10 випадкових чисел із діапазону від 10 до 50.

Розв’язок:

  Random r = new Random();
  for (int i = 0; i < 10; ++i)
  {
      Console.Write(r.Next(10,50) + "\t");
  }

Приклад 4.2. Написати програму, яка серед 5-ти введених чисел знаходить найменше. Програма працює наступним чином: користувач вводить за запитом системи числа, а потім на консоль виводиться найменше з них.

Розв’язок:

  int min = int.MaxValue;
  for (int i = 0; i < 5; ++i)
  {
     Console.Write("Введіть {0} число:\t", i + 1);
     int num = int.Parse(Console.ReadLine());
     min = num < min ? num : min;
  }
  Console.WriteLine("Найменше число:\t{0}",min);

Приклад 5.3. Написати програму, що моделює роботу навігації. Програма повинна пропонувати користувачу вибір дії шляхом введення символа з клавіатури. Доступними діями є: - [x] Hello - виводить на консоль текст «Hello, user!» - [x] Time - виводить години, хвилини та секунди на поточному ПК - [x] Exit - завершує роботу програми.

Розв’язок:

  while (true)
  {
     Console.WriteLine("\nMake a choice:");
     Console.Write(" [H]ello\n [T]ime\n E[x]it\n\t\t:>");
     string res = Console.ReadLine();
     
     switch (res)
     {
       case "H":
       case "h":
          Console.WriteLine("Hello, user!");
          break;
       case "T":
       case "t":
         Console.WriteLine(
         DateTime.Now.ToString("HH:mm:ss",
         new CultureInfo("uk")));
         break;
       case "X":
       case "x":
         return;
         break;
       default:
         Console.WriteLine("Wrong choice");
         break;
     }
  }

Задачі

Задача 5.1.

Написати програму, що знаходить добуток чисел у вказаному користувачем діапазоні.


Задача 5.2.

Дано цілі додатні числа \(i\) та \(k\) . Реалізувати функцію, що обчислює значення виразу:

\[ z = i - k, при i кратному k \] \[z = k - i, при k кратному i\] \[z = k + i, при{ }всіх{ }інших{ }умовах\]


Задача 5.3.

Обчислити значення виразу \(y=\frac{(x + 5)^3}{\sqrt{x + 1}}\) для усіх \(x\) з діапазону \([10; 100]\) кратних \(7\)-ми. На консоль вивести результат у вигляді, наприклад:

  x   y
  7   125.21
  14  100.41
  ...

Примітка. Вивести на консоль не більше двох знаків після розділювача дробової та цілої частини (крапки) для значень \(y\).


Задача 5.4

Написати програму, яка генерує і виводить на консоль \(8\) випадкових чисел із діапазону від \(1 до 10\). Якщо згенероване число є непарним, то його значення замінюється на \(0\) і виводиться у фигляді \(0(непарне число)\).

Наприклад, виведення може мати вигляд:

2 4 0(7) 0(1) 8 4 2 6 0(9) 0(1) 6

Задача 5.5.

Обчислити значення виразу \(y=\frac{cos(x^2 + 5)^3}{\sqrt{x - ln(x)}}\) для усіх \(x\) з діапазону \([100; 200]\) кратних \(10\)-ти. На консоль вивести результат у вигляді, наприклад:

  x     y
  100    0.8710
  110   -0.0247
  ...

Примітка. Вивести на консоль не більше чотирьох знаків після розділювача дробової та цілої частини (крапки) для значень \(y\). Також зверніть увагу на виведення чисел з від’ємним та додатними значеннями.


Задача 5.6.

Написати програму, що виводить на консоль таблицю множення на вказане користувачем число. Наприклад, якщо користувач ввів число \(5\), то результат виконання програми матиме вигляд:

  5 x 1 = 5
  5 x 2 = 10
  ...
  // і так далі...
  ...
  5 x 10 = 50

Задача 5.7.

Відомо, що \(1 дюйм\) рівний \(2.54 см\). Розробити додаток, що переводить дюйми в сантиметри і навпаки. Діалог з користувачем реалізувати через систему меню.


Задача 5.8.

Написати програму, що знаходить суму усіх чисел кратних \(7\) у діапазоні від \(0\) до \(100\).


Задача 5.9.

Написати програму, що обчислює суму цифр введено числа.


Задача 5.10.

Написати програму, що виводить на екран цифри введеного числа у зворотному порядку. Наприклад, \(248641 > 146842\).


Задача 5.11.

Написати програму, дозволяє вивести на консоль в порядку спадання непарні числа із діапазону \([5;90]\), кратні \(3\) та не кратні \(5\). одночасно.


Задача 5.12.

Розробити програму, що працює як найпростіший калькулятор, який виконує арифметичні дії +, -, *, / (скористатися оператором switch).

Пояснення. Програма повинна працювати у режимі постійного діалогу з користувачем.

--- МЕНЮ ---
[+] - Додати
[-] - Відняти
[*] - Множити
[/] - Ділити
[0] - Вийти з програми

Ваш вибір :> *

Введіть число 1: 4
Введіть число 2: 5

Резльутат: 20

// повторне виведення меню

Задача 5.13.

Знайти найбільший спільний дільник двох натуральних чисел, використавши алгоритм Евкліда. Алгоритм Евкліда полягає в наступному: від більшого числа віднімається менше до тих пір, поки вони не стануть рівними; отримане в результаті число і буде найбільшим спільним дільником.


Задача 5.14.

Написати програму, яка виводить на екран лінію з символів. Число символів та сам символ, і яка буде лінія вертикальна, або горизонтальна - вказує користувач.


Задача 5.15.

Написати програму, яка виводить на консоль фігури, зображені нижче. Примітка. Розміри фігур вказує користувач.

Фігура 1.

****************
****************
****************
****************
****************

Фігура 2.

****************
*              *
*              *
*              *
****************

Фігура 3.

*****
****
***
**
*

Задача 5.16.

Написати програму, що генерує та виводить на консоль 5 випадкових чисел, кратних 7-ми та некратних 5-ти одночасно з діапазону \([50; 150]\).


Задача 5.17.

Написати програму, що передбачає вгадування користувачем числа, загаданого комп’ютером. Після кожної спроби вгадати число комп’ютер повідомляє чи загадане значення більше (>) чи менше (<) від запропонованого користувачем. Після вгадування на екран виводиться кількість спроб.

Припустимо, що компютер має право загадувати число у діапазоні \([1; 10000)\).

Примітка. Потрібне вміння генерувати випадкові числа за допомогою класу Random.


Задача 5.18.

Згенерувати 10 випадкових чисел у діапазоні \([10, 100)\). Вивести числа на консоль.


Warning

Дорогі друзі, якщо Ви помітили, що для написання матеріалів використані джерела, які я не вказав - прошу надіслати мені інформацію на пошту. Дякую.