Лекція 5. Оператори розгалуження та цикли


Table of Contents

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

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

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

Якщо є потреба перевірити у коді програми виконання якоїсь умови та за її результатами перейти до одного із блоків програми зазвичай використовують оператор if-else. Загальний вигляд формату використання оператора if-else зображений у лістингу 5.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 можуть мати тільки унікальні константи. Формат оголошення продемонстровано у лістингу 5.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 може мати вигляд як на лістингу 5.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 має вигляд як на лістингу 5.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;
  }

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

  • Початок: i = 0; j = 1; sum = 0.
  • 1-ша ітерація: i = 1; j = 3; sum = 5.
  • 2-га ітерація: i = 2; j = 5; sum = 12.
  • 3-тя ітерація: i = 3; j = 7; sum = 22

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

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

На прикладі лістингу 5.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 розглянемо лістинги 5.14 та 5.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 разом із вивченням масивів.


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

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

Розв’язок:

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

Приклад 5.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. Написати програму, що моделює роботу навігації. Програма повинна пропонувати користувачу вибір дії шляхом введення символа з клавіатури. Доступними діями є:

  • Hello - виводить на консоль текст «Hello, user!»
  • Time - виводить години, хвилини та секунди на поточному ПК
  • 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.

Обчислити значення виразу $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.5.

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

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

Задача 5.6.

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


Задача 5.7.

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


Задача 5.8.

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


Задача 5.9.

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


Задача 5.10.

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


Задача 5.11.

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

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

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

Ваш вибір :> *

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

Резльутат: 20

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

Задача 5.12.

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


Задача 5.13.

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


Задача 5.14.

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

Фігура 1.

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

Фігура 2.

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

Фігура 3.

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

Задача 5.15.

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


Задача 5.16.

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

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

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


Задача 5.17.

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


Контрольні запитання


Список використаних джерел

  1. Albahari, J., & Albahari, B. (2012). C# 5.0 in a Nutshell, Fifth Edition. 1005 Gravenstein Highway North, Sebastopol, USA: O’Reilly Media, Inc.
  2. Cardelli, L., & Wegner, P. (December 1985 p.). On Understanding Types, Data Abstraction, and Polymorphism. ACM Computing 1. Surveys, 17(4), сс. 149-154. Отримано з http://lucacardelli.name/Papers/OnUnderstanding.A4.pdf
  3. Kort, W. d. (2013). Exam Ref 70-483: Programming in C#. Sebastopol, California 95472: O’Reilly Media, Inc.
  4. MSDN. (без дати). Отримано з Microsoft Developer Network: http://msdn.microsoft.com/
  5. Биллиг, А. (2005). Основы программирования на C#. Москва, Россия: НОУ ИНТУИТ.
  6. Нейгел, К. И. (2011). С# 4.0 и платформа .NET 4 для профессионалов. Москва, Россия: ООО “И.Д. Вильямс”.
  7. Павловская, Т. (2009). С#. Программирование на языке высокого уровня. Учебник для вузов. СПб, Россия: Питер.

Додаткові матеріали для завантаження

  1. Лекція у форматі DOCX Завантажити (у розробці)
  2. Лекція у форматі PDF Завантажити (у розробці)
  3. Діаграми до лекції у форматі draw.io на github Перейти

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