До цього моменту ви вже вмієте зберігати дані у змінних і вводити їх з клавіатури. Але програма — це не просто сховище даних. Програма думає: вона порівнює числа, приймає рішення, виконує дії залежно від умов. Інструментом для всього цього є оператори.
Оператор (operator) — це символ або ключове слово, яке дає компілятору команду виконати певну дію над одним або кількома операндами (operands). Операнди — це дані, з якими виконується операція: значення, змінні або вирази.
int result = 10 + 3;
// ↑ ↑
// операнди: 10 і 3
// ↑
// оператор: +
Усі оператори C++ поділяються на кілька груп за призначенням:
➕ Арифметичні
+, -, *, /, %✏️ Присвоєння
=, +=, -=, *=, /=, %=⚖️ Порівняння
==, !=, <, >, <=, >=🔗 Логічні
&&, ||, !↕️ Інкремент / Декремент
++, --🔢 Побітові
&, |, ^, ~, <<, >>У цій статті ми детально розберемо перші п'ять груп — саме їх ви будете використовувати щодня.
Ви вже зустрічалися з ними у попередньому розділі. Розглянемо їх систематично та зверніть увагу на деталі, які часто є джерелом помилок.
| Оператор | Назва | Приклад | Результат |
|---|---|---|---|
+ | Додавання | 7 + 3 | 10 |
- | Віднімання | 7 - 3 | 4 |
* | Множення | 7 * 3 | 21 |
/ | Ділення | 7 / 3 | 2 (ціле!) |
% | Остача від ділення | 7 % 3 | 1 |
Найбільш несподіваний оператор для новачків — це /. У C++ поведінка оператора ділення залежить від типів операндів.
Якщо обидва операнди є цілими числами (int, short, long тощо), C++ виконує ціле ділення (integer division): дробова частина результату просто відкидається, а не округлюється.
int a = 7;
int b = 3;
int result = a / b; // result = 2, а не 2.333...
Зверніть увагу на принципову відмінність: 7 / 3 = 2, а не 2.33. Дробова частина .33 не округлюється до нуля — вона знищується. Якщо вам потрібен дійсний результат, хоча б один із операндів повинен бути типу float або double:
int a = 7;
int b = 3;
double result1 = a / b; // result1 = 2.0 ← НЕПРАВИЛЬНО!
double result2 = (double)a / b; // result2 = 2.333... ← Правильно
double result3 = a / 3.0; // result3 = 2.333... ← Теж правильно
У першому рядку ціле ділення відбувається до присвоєння в double: спочатку 7 / 3 = 2, а потім 2 конвертується у 2.0. Результат некоректний. У другому та третьому рядках хоча б один з операндів є дійсним числом — тому і ділення стає дійсним.
0, 1 або інше округлене значення замість дробового — перевірте типи операндів у виразі ділення.%Оператор % (модуль або остача від ділення) повертає залишок від цілого ділення. Він застосовується лише до цілих типів.
cout << 10 % 3; // 1 (10 = 3*3 + 1)
cout << 14 % 7; // 0 (14 = 7*2 + 0)
cout << 5 % 8; // 5 (5 = 8*0 + 5)
Навіщо він потрібен? Декілька практичних застосувань:
n % 2 == 0, число парне.0 до 6. Якщо день d + 3 може вийти за межі, використайте (d + 3) % 7.n — це n % 10, передостання — (n / 10) % 10.C++ дотримується математичного пріоритету (precedence): множення, ділення та остача виконуються до додавання та віднімання. Для зміни порядку використовуйте дужки.
int a = 2 + 3 * 4; // a = 14 (спочатку 3*4=12, потім 2+12)
int b = (2 + 3) * 4; // b = 20 (дужки змінюють порядок)
int c = 10 - 6 / 2; // c = 7 (спочатку 6/2=3, потім 10-3)
Звичайний оператор присвоєння = ви вже знаєте. Але C++ має скорочені форми, які суміщають арифметичну операцію з присвоєнням. Вони називаються складеними операторами присвоєння (compound assignment operators).
| Оператор | Еквівалент | Приклад | Результат |
|---|---|---|---|
x += n | x = x + n | x += 5 | Збільшити x на 5 |
x -= n | x = x - n | x -= 3 | Зменшити x на 3 |
x *= n | x = x * n | x *= 2 | Подвоїти x |
x /= n | x = x / n | x /= 4 | Поділити x на 4 |
x %= n | x = x % n | x %= 7 | Залишити лише остачу від ділення x на 7 |
int score = 100;
score += 50; // score = 150 (нараховуємо бонуси)
score -= 30; // score = 120 (штраф)
score *= 2; // score = 240 (подвоєння)
score /= 3; // score = 80 (ціле ділення!)
| Name | Type | Value |
|---|---|---|
| ◢start score | int | 100 |
| ◢after += 50 | int | 150 |
| ◢after -= 30 | int | 120 |
| ◢after *= 2 | int | 240 |
| ◢after /= 3 | int | 80 |
Ці оператори не просто «зручне скорочення» — вони роблять код читабельнішим, явно показуючи, що ми модифікуємо існуючу змінну, а не присвоюємо їй нове незалежне значення.
Окремий та дуже поширений випадок — збільшення або зменшення значення рівно на одиницю. Для цього C++ має спеціальні оператори.
Інкремент (increment) ++ — збільшує значення змінної на 1.
Декремент (decrement) -- — зменшує значення змінної на 1.
int counter = 0;
counter++; // counter = 1
counter++; // counter = 2
counter--; // counter = 1
Кожен з цих операторів існує у двох формах: префіксній (перед змінною) та постфіксній (після змінної). Різниця проявляється лише тоді, коли вираз використовується у ширшому контексті — наприклад, при виводі або присвоєнні.
Спочатку збільшує значення, потім повертає вже збільшене значення.
int x = 5;
int y = ++x; // Спочатку x стає 6, потім y = 6
// x = 6, y = 6
Аналогія: «Спочатку дій, потім звітуй».
Спочатку повертає поточне значення, а потім збільшує його.
int x = 5;
int y = x++; // y = 5 (береться поточне значення), потім x стає 6
// x = 6, y = 5
Аналогія: «Спочатку звітуй, потім дій».
counter++;), між префіксною та постфіксною формами немає жодної різниці — обидва варіанти просто збільшують значення на 1. Різниця виникає лише всередині складніших виразів.У C++ типи суворо визначені. Проте іноді нам потрібно «переключитися» між типами: взяти ціле число і зробити з нього дійсне, або навпаки. Для цього існують механізми перетворення типів (type conversion).
Коли значення одного типу автоматично перетворюється в інший без жодних додаткових команд — це неявне перетворення. Компілятор виконує його самостійно, коли типи операндів не збігаються.
Загальне правило: при змішуванні різних числових типів C++ розширює менший тип до більшого (щоб уникнути втрати інформації).
int age = 25;
double ratio = age; // int → double: неявне розширення (безпечно)
// ratio = 25.0
double pi = 3.14159;
int piInt = pi; // double → int: неявне звуження (небезпечно!)
// piInt = 3 (дробова частина ЗАГУБЛЕНА)
Ієрархія неявного розширення виглядає таким чином:
Кожен тип автоматично й безпечно розширюється до наступного. Рух у зворотному напрямку (звуження) — небезпечний, адже веде до втрати даних.
double до int не дає похибки компіляції, але мовчки знищує дробову частину. Компілятор може видати warning (попередження), але не зупинить компіляцію. Це один з найнебезпечніших аспектів неявних перетворень.Коли перетворення потрібно виконати свідомо та навмисно, використовується явне приведення типу (type cast). Синтаксис у стилі C, який прийнятий у цьому курсі:
(тип) вираз
int a = 7;
int b = 3;
double result = (double)a / b; // 7.0 / 3 = 2.333...
Тут (double)a — це явне перетворення значення змінної a до типу double. Сама змінна a при цьому не змінюється — вона залишається int. Перетворюється лише значення, яке використовується у цьому виразі.
Розглянемо ще один типовий приклад — виведення відсотка:
int correct = 7;
int total = 10;
// Неправильно: 7 / 10 = 0 (ціле ділення), 0 * 100 = 0
double percent1 = correct / total * 100;
// Правильно: (7.0) / 10 = 0.7, 0.7 * 100 = 70.0
double percent2 = (double)correct / total * 100;
cout << "Percent: " << percent2 << "%\n"; // Percent: 70%
(тип), коли:int і char (код символу)char та intТип char зберігає один символ, але внутрішньо він є числом — кодом символу за таблицею ASCII. Це дає змогу конвертувати між символами та їх числовими кодами.
char letter = 'A';
int code = (int)letter; // code = 65 (код символу 'A' в ASCII)
int number = 66;
char symbol = (char)number; // symbol = 'B' (символ з кодом 66)
cout << "Код 'A': " << code << "\n"; // Код 'A': 65
cout << "Символ 66: " << symbol << "\n"; // Символ 66: B
Ця властивість використовується, наприклад, для визначення, чи є символ літерою, цифрою, або для переведення між регістрами:
char lower = 'a';
char upper = (char)(lower - 32); // 'a'(97) - 32 = 'A'(65)
cout << upper; // A
Щоб програма могла приймати рішення, їй потрібно вміти порівнювати значення. Для цього використовуються оператори порівняння (relational / comparison operators). На відміну від арифметичних операторів, вони повертають не число, а логічне значення типу bool: true (істина) або false (хибність).
| Оператор | Значення | Приклад | Результат |
|---|---|---|---|
== | Дорівнює | 5 == 5 | true |
!= | Не дорівнює | 5 != 3 | true |
< | Менше | 3 < 5 | true |
> | Більше | 3 > 5 | false |
<= | Менше або дорівнює | 5 <= 5 | true |
>= | Більше або дорівнює | 6 >= 5 | true |
== (два знаки рівності). Оператор присвоєння — = (один знак). Написавши if (x = 5) замість if (x == 5), ви не порівняєте x з 5 — ви присвоїтеx значення 5, і умова завжди буде true (непорожнє значення = true). Компілятор часто not попереджає про це.Результат порівняння — значення bool. Його можна зберегти у змінній:
int age = 20;
bool isAdult = (age >= 18); // true
bool isChild = (age < 12); // false
cout << isAdult; // Виведе: 1 (true відображається як 1)
cout << isChild; // Виведе: 0 (false відображається як 0)
Або використати напряму в умовній конструкції (детальніше про if — у наступному розділі):
if (age >= 18) {
cout << "Доступ дозволено\n";
}
Поодинці оператори порівняння дозволяють перевірити лише одну умову: «вік більший за 18» або «пароль вірний». Але реальні програми часто потребують складніших перевірок: «вік більший за 18 І є квиток» або «температура вище 37 АБО є симптоми». Для об'єднання кількох умов в одну використовуються логічні оператори (logical operators).
&& (логічне AND)Повертає true лише якщо обидві умови є істинними одночасно. Достатньо хоч одній умові бути false — і весь вираз стає false.
Таблиця істинності &&:
| Умова A | Умова B | A && B |
|---|---|---|
false | false | false |
false | true | false |
true | false | false |
true | true | true |
int age = 20;
bool hasTicket = true;
bool canEnter = (age >= 18) && hasTicket;
// true && true → true: вхід дозволено
Аналогія з життя: ви заходите у клуб лише якщо І ви повнолітній, І у вас є квиток.
|| (логічне OR)Повертає true якщо хоча б одна з умов є істинною. Повертає false лише якщо обидві умови хибні.
Таблиця істинності ||:
| Умова A | Умова B | A || B |
|---|---|---|
false | false | false |
false | true | true |
true | false | true |
true | true | true |
bool hasPass = false;
bool isEmployee = true;
bool canGoIn = hasPass || isEmployee;
// false || true → true: вхід дозволено
Аналогія: Ви можете увійти у службовий вхід, якщо АБО маєте перепустку, АБО є співробітником (є хоча б одна підстава).
! (логічне NOT)Інвертує логічне значення: перетворює true на false, і навпаки. Це унарний оператор — він діє на один операнд.
| Умова A | !A |
|---|---|
false | true |
true | false |
bool isRaining = false;
bool goForAWalk = !isRaining; // true: не дощить → можна гуляти
bool isDividableBy2 = (number % 2 == 0);
bool isOdd = !isDividableBy2; // інвертуємо: ділиться → підраховуємо непарне
Логічні оператори можна комбінувати для побудови складних умов. Пріоритет операцій: ! виконується першим, потім &&, потім ||. Дужки дозволяють перевизначити порядок.
int temperature = 38;
bool hasCough = true;
bool hasVaccine = false;
// Пацієнт у групі ризику: висока температура АБО (кашель І без щеплення)
bool isAtRisk = (temperature > 37) || (hasCough && !hasVaccine);
// true || (true && true) → true || true → true
Розберемо, як обчислюється цей вираз покроково:
!hasVaccine → !false → truehasCough && true → true && true → true(temperature > 37) → (38 > 37) → truetrue || true → true&&: якщо перша умова — false, результат завжди false, друга умова не перевіряється. Для ||: якщо перша умова — true, результат завжди true. Це важливо, коли друга умова містить виклик функції або звернення до пам'яті.У складних виразах порядок виконання операторів визначається їх пріоритетом (precedence). Ось спрощена таблиця від найвищого до найнижчого:
| Пріоритет | Оператори | Напрям виконання |
|---|---|---|
| 1 (найвищий) | () дужки | зліва направо |
| 2 | !, ++, -- (префіксні), (тип) | справа наліво |
| 3 | *, /, % | зліва направо |
| 4 | +, - | зліва направо |
| 5 | <, >, <=, >= | зліва направо |
| 6 | ==, != | зліва направо |
| 7 | && | зліва направо |
| 8 | || | зліва направо |
| 9 (найнижчий) | =, +=, -=, *=, /=, %= | справа наліво |
(a > 0) && (b != 0) || !flag значно читабельніший, ніж a > 0 && b != 0 || !flag, навіть якщо результат однаковий.Складемо програму, яка зчитує три сторони та перевіряє, чи можуть вони утворити трикутник. За теоремою: трикутник існує, якщо кожна зі сторін менша за суму двох інших.
#include <iostream>
using namespace std;
int main()
{
double a, b, c;
cout << "Enter three sides: ";
cin >> a >> b >> c;
bool isValid = (a + b > c) && (a + c > b) && (b + c > a);
cout << "Is triangle: " << isValid << "\n";
// Виведе 1 (true) або 0 (false)
return 0;
}
Розберемо ключові елементи:
cin автоматично розбиває введення за пробілами.&&. Усі три повинні бути true одночасно, щоб трикутник існував.bool при виводі через cout відображається як 0 або 1.Приклади роботи:
Розробимо програму, що переводить температуру із Цельсія у Фаренгейт і відразу показує відсоток від «точки кипіння» (100°C = 212°F).
#include <iostream>
using namespace std;
int main()
{
double celsius;
cout << "Enter temperature in Celsius: ";
cin >> celsius;
// Формула перетворення
double fahrenheit = celsius * 9.0 / 5.0 + 32.0;
// Відсоток від точки кипіння (100 C)
double percentOfBoiling = celsius / 100.0 * 100.0;
// Чи перевищує температура поріг нормального тіла (36.6)?
bool isHighTemp = celsius > 36.6;
cout << celsius << " C = " << fahrenheit << " F\n";
cout << "Percent of boiling: " << percentOfBoiling << "%\n";
cout << "High temperature: " << isHighTemp << "\n";
return 0;
}
Аналіз ключових рядків:
* 9.0 / 5.0 використовує дійсні літерали (9.0, 5.0), щоб ділення не було цілочисельним. Якщо написати * 9 / 5, при celsius = 37 отримуємо 37 * 9 / 5 = 333 / 5 = 66 (ціле ділення!), а не правильне 66.6.100.0 (дійсне), а не 100.bool isHighTemp і виводиться як 0 або 1.Приклад роботи:
Визначте значення виразів, не запускаючи програму. Потім перевірте свої відповіді кодом:
int a = 10, b = 3;
cout << a / b << "\n"; // ?
cout << a % b << "\n"; // ?
cout << a / 3.0 << "\n"; // ?
cout << (a > b) << "\n"; // ?
cout << (a == 10) << "\n"; // ?
cout << (a != b) << "\n"; // ?
cout << !true << "\n"; // ?
cout << (a > 5 && b < 5) << "\n"; // ?
Знайдіть та виправте всі помилки у фрагменті коду:
int x = 7, y = 2;
double result = x / y; // Має бути 3.5
bool isEqual = (x = y); // Має перевіряти рівність
bool isPositive = x > 0 && < 100; // Синтаксична помилка
Скільки помилок ви знайшли?
Напишіть програму, яка зчитує ціле число та виводить 1, якщо воно парне, і 0, якщо непарне. Використовуйте оператор % та збережіть результат у bool.
Перевірка:
14 → 1 (парне)7 → 0 (непарне)Напишіть програму, яка зчитує тризначне число (наприклад, 357) та виводить окремо кожну цифру:
357Підказка: цифра одиниць — n % 10, цифра десятків — (n / 10) % 10, цифра сотень — n / 100.
Напишіть програму, яка зчитує рік та виводить 1, якщо він високосний, і 0 — якщо ні.
Рік є високосним, якщо:
Збережіть результат у bool leapYear та виведіть його.
Перевірка: 2000 → 1, 1900 → 0, 2024 → 1, 2023 → 0
Реалізуйте програму-калькулятор індексу маси тіла (BMI). Програма повинна:
BMI = weight / (height * height)1/0 для двох перевірок:
isNormal: чи знаходиться BMI у нормальному діапазоні (від 18.5 до 24.9 включно)isOverweight: чи BMI більший або рівний 25.0Приклад:
Enter weight (kg): 75
Enter height (m): 1.75
BMI: 24.49
Normal weight: 1
Overweight: 0
Напишіть програму, яка зчитує цифру від 0 до 9 (як char), конвертує її в числове значення (int) та виводить її квадрат.
Підказка: якщо char digit = '7', то числове значення — (int)digit - (int)'0' (різниця між кодом символу та кодом символу '0').
Приклад:
Enter digit: 7
Digit value: 7
Square: 49
📌 Арифметичні оператори
+, -, *, /, %. Ціле ділення відкидає дробову частину — для дійсного результату хоча б один операнд має бути double/float.📌 Оператори присвоєння
=, +=, -=, *=, /=, %= — суміщують операцію з присвоєнням. ++/-- — інкремент та декремент.📌 Перетворення типів
(тип)вираз — свідоме перетворення. Звуження типу (double → int) знищує дробову частину.📌 Оператори порівняння
==, !=, <, >, <=, >= — повертають bool. Пам'ятайте: == (порівняння) ≠ = (присвоєння)!📌 Логічні оператори
&& (AND) — обидві умови, || (OR) — хоча б одна, ! (NOT) — інверсія. Підтримують короткочасне обчислення.📌 Пріоритет
! → */% → +- → <><=>= → ==!= → && → || → =. Сумнівно — ставте дужки.Ввід даних з клавіатури
Оператор cin для зчитування даних з клавіатури. Інтерактивні програми з введенням та виведенням, арифметичні оператори та практичні приклади.
Цикли
Цикли for, while та do-while у C++. Оператори break та continue. Вкладені цикли. Алгоритми з накопиченням, пошуком та лічильниками. Практичні задачі.