Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КТіП Лекції 20110516 (1).doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1 Мб
Скачать
☆
    1. Операції порівняння

Операції порівняння (ще їх називають операціями відношення) є бінарними. Результатом виконання операцій є величина логічного типу – true або false. До операцій порівняння відносять:

  1. > більше;

  2. >= не менше;

  3. < менше;

  4. <= не більше;

  5. == дорівнює;

  6. != не дорівнює.

Поширеною помилкою є використання знаку присвоєння = замість знака рівності ==. Оскільки присвоєння це також операція, що повертає присвоєне значення, компілятор може не фіксувати помилку в таких виразах, але часто видає попередження.

    1. Логічні операції

В мові програмування С++ застосовуються три логічні операції:

  1. ! логічне заперечення, унарна операція;

  2. && логічне І, бінарна операція;

  3. || логічне АБО, бінарна операція.

Операндами логічних операцій є логічні дані – істина (true) і хибність (false). Результатом логічної операції є величина логічного типу. Операндами також можуть бути числові дані: будь яке не нульове значення – це істина, нуль – хибність. Цей підхід використовується в мові програмування С, в якій немає логічного типу даних bool.

Операція логічного заперечення змінює логічне значення на протилежне. Тобто,

#include <iostream>

using namespace std;

int main(){

bool a = true;

cout << a << endl; // 1

cout << !a << endl; // 0

}

Результат бінарної операції && буде істинним (не буде дорівнювати нулю), тільки в тому разі, коли обидва операнди є істинними (не дорівнюють нулю). Результат виконання операції || буде істинним, коли істинним є хоча б один з операндів.

Логічні вирази в С++ не обов’язково мають бути обчислені повністю. Як тільки значення виразу стає однозначним, подальші обчислення припиняються. При цьому, лівий операнд логічної операції обчислюється першим, а правий – другим. Це дає можливість записувати вирази, в яких одразу виконується зміна даних і перевірка. В деяких випадках це може призводити до некоректної роботи програми. Наприклад:

1 #include <iostream>

2 using namespace std;

3 int main(){

4 int a1 = 0, b1 = 1, c1 = 2;

5 int a2 = 0, b2 = 1, c2 = 2;

6 bool r;

7 r = b1 < c1 && ++a1 > 0; // r = true

8 cout << "a1 = " << a1 << endl; // a = 1

9 r = b2 > c2 && ++a2 > 0; // r = false

10 cout << "a2 = " << a2 << endl; // a = 0

11 }

В програмі обчислення значення змінної r виконується в рядках 7 і 9. В обох випадках використовують логічну операцію І. При виконанні операції І першим буде обчислене значення лівого операнда. Якщо це false, то незалежно від значення правого операнда результат виконання операції буде false, і вираз справа від знака операції І обчислений не буде. В прикладі в рядку 7 обчислюються вирази і зліва, і заправа від знака операції І, в рядку 9 – лише зліва. Таким чином, незважаючи на те, що пріоритет операції префіксного інкременту більший пріоритетів логічних операцій і операцій порівняння, в рядку 9 змінна а не буде збільшена на одиницю.

    1. Операції присвоєння

Операції присвоєння можна поділити на 2 групи:

  1. унарні операції:

    1. ++ (постфіксний і префіксний інкремент, збільшення на одиницю),

    2. -- (постфіксний і префіксний інкремент, зменшення на одиницю);

  2. бінарні операції:

    1. = (звичайне присвоєння),

    2. *= (множення з присвоєнням),

    3. /= (ділення з присвоєнням),

    4. %= (остача від ділення з присвоєнням),

    5. += (додавання з присвоєнням),

    6. -= (віднімання з присвоєнням),

    7. &= (побітове І з присвоєнням),

    8. ^= (побітове виключне І з присвоєнням),

    9. |= (побітове АБО з присвоєнням),

    10. <<= (зсування вліво з присвоєнням),

    11. >>= (зсування вправо з присвоєнням).

На відміну від інших операцій, операції присвоєння змінюють значення свого операнда: для бінарних операцій лівий операнд набуває значення виразу, записаного справа від знака присвоєння, для унарних операцій – змінюється значення єдиного операнда даної операції. Тому операнд, якому присвоюється значення, повинен бути так званим l-операндом (l-value, left side value) – змінною розадресованим вказівником, тобто він має задавати адресу оперативної пам'яті, куди буде записане значення, яке присвоюється.

Результатом операції присвоєння є значення, яке набуває змінна (l-операнд) після присвоєння. Це значення можна використовувати як операнд у наступних операціях, для яких присвоєння є підвиразом. Операції присвоювання виконуються справа наліво, що дозволяє записати вираз, який складається з декількох присвоєнь (рядок 5 і 7).

1 #include <iostream>

2 using namespace std;

3 int main(){

4 int a, b, c;

5 a = b = c = 123;

6 cout << a << endl; // 123

7 a = b = c + 321;

8 cout << a << endl; // 444

9 }

Бінарні присвоєння стоять у кінці списку пріоритетів, тому іноді підвираз присвоювання слід охоплювати дужками:

#include <iostream>

using namespace std;

int main(){

int a, b = 1, c = 2;

bool r;

r = a = b + c < 2; // 0, a = 3 < 0, a = 0

cout << a << endl;

r = (a = b + c) < 2; // 3

cout << a << endl;

}

Комбіновані присвоєння є окремим випадком звичайних присвоювань. Вираз

операнд1 операція= операнд2;

є скороченим записом операції присвоєння:

операнд1 = операнд1 операція операнд2;

Операція виключне АБО має таку особливість: (a ^ b) ^ b = a. Тобто, якщо виконати операцію 2 рази з однаковим другим операндом, ми отримаємо значення першого операнда. Це дозволяє виконувати обмін двох цілочислових змінних значеннями.

#include <iostream>

using namespace std;

int main(){

int a = 123, b = 321;

a ^= b ^= a ^= b;

cout << "a = " << a << endl; // 321

cout << "b = " << b << endl; // 123

}

В програмах на С++ широко застосовують унарні операції присвоєння ++ і --. Перша з них називається інкрементом, вона збільшує значення операнда на одиницю. Друга – декрементом, зменшує значення операнда на одиницю. Можна застосовувати дві форми запису операцій інкремента і декремента: префіксну, коли знак ++/-- записується перед операндом, і постфіксну – коли знак операції вказується після операнда.

Якщо унарне присвоєння використовується як окремий оператор, то обидві форми запису – префіксна і постфіксна – рівнозначні. В наступному прикладі наведені чотири альтернативні способи збільшення і зменшення значення змінної на одиницю.

#include <iostream>

using namespace std;

int main(){

int a = 0, b = 0;

a++; ++a; a += 1; a = a + 1; // Збільшення на 1

b--; --b; b -= 1; b = b - 1; // Зменшення на 1

cout << "a = " << a << endl;

cout << "b = " << b << endl;

}

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

#include <iostream>

using namespace std;

int main(){

int a = 3, b = 3, ta, tb;

ta = ++a + 1;

tb = b++ + 1;

cout << "ta = " << ta << endl; // 5

cout << "tb = " << tb << endl; // 4

}