Операторите в C++

В предишната лекция разгледахме трите оператора за цикли в C++, както и някои помощни понятия като логическите стойности истина (True) и лъжа (False). В тази лекция ще разгледаме логическите оператори и (and), или (or) и не (not) и ще систематизираме старшинството при изпълнение на операторите.

1. Оператори за сравняване (relational operators). В таблица 1 са дадени така наречените оператори за сравняване, чието значение разяснихме в предишната лекция. С тези оператори се извършва сравняване на стойности на променливи, изрази и константи.

Таблица 1. Операторите за сравняване (relational operators).
 

--------------
Символ
Symbol
--------------

------------------------
Значение
Meaning
------------------------

----------------
Пример
Example
----------------

== 

равно на
equal to

a == b

!= 

неравно на
not equal to

a != b 

по-малко от
less than

a < b 

> 

по-голямо от
greater than

a > b

<=

по-малко или равно на
less than or equal to

a <= b 

>=

по-голямо или равно на
greater than or equal to

a >= b

--------------

------------------------

----------------

Ето няколко примера:

j >= 10            // сравнява променливата j с константата 10

j < k              // сравнява променливата j с променливата k

j != k + n         // сравнява променливата j с израза k + n

i + j = k + l      // сравнява израза i + j с израза k + l

Обикновено е необходимо едновременното сравняване на няколко такива израза. Комбинирането им се извършва с така наречените логически оператори.

2. Логически оператори (Logical Operators). Т.н. бинарни логически оператори съставляват основата на формалната логика. Общо могат да се съставят 8 (8 = 23) такива оператора, но най-важните са логическото и (and), логическото или (or), изключващото или (xor), и логическото следствие (implication, импликация). Първите два бинарни логически оператора се използват директно в повечето програмни езици, включително в C++, и са разгледани по-долу. Изключващото или (xor) има стойност истина (True) само когато първият операнд има стойност истина, а вторият - лъжа (False), или обратно. Ако двата операнда имат еднакви стойности, то изключващото или дава лъжа. Логическото следствие (implication) има стойност лъжа само ако първият операнд (който играе ролята на причина) е истина, а вторият (който играе ролята на следствие) е лъжа. Това е така, защото очакваме, че ако се изпълни причината, то да настъпи следствието. В останалите случаи импликацията има стойност истина. По-принцип всички възможни осем логически операции могат да се представят с логическото и (and), логическото или (or) и логическото не (not). Последният логически оператор е унарен (действа на един операнд) и превръща стойност истина в лъжа, както и лъжа в истина.

В таблица 2 са дадени трите логически оператора, които са имплементирани в C++.

Таблица 2. Логическите оператори (Logical Operators).
 

--------------------
Логически оператор
Logical Operator
--------------------

------------------------
Значение
Meaning
------------------------

------------------
Пример
Example
------------------

&& 

и
AND

x > 0 && x < 5

||

или
OR

 x == 1 || x >= 2

!

не
NOT

!b

--------------------

------------------------

------------------

Символът "|" е две черти една под друга, но често на екрана излиза като една черта, което затруднява намирането и на клавиатурата от начинаещите програмисти. Ето защо ще добавим, че той се пише с комбинацията от клавиши <Shift>-<>.

Резултатът от оператора && има стойност истина само когато и двата му операнда са истина, иначе в останалите три случая той дава неистина. В дадения в таблицата пример изразът x > 0 && x < 5 ще има истина само когато едновременно x > 0 и x < 5, което е равнозначно на проверка дали числото x е в отворения интервал (0, 5).

Друг често използван израз с логическото и е следният, който проверява дали ch е малка латинска буква:

  1. ch >= `a` && ch <= `z`

Резултатът от оператора || има стойност неистина само когато и двата му операнда са едновременно неистина. Или казано по друг начин, изразът ще бъде истина когато поне единият от двата операнда е истина. В дадения в таблицата пример изразът x == 1 || x >= 2 ще има стойност истина когато или x == 1 е истина или x >= 2 е истина, което е равнозначно на проверка дали числото x е равно на едно или е в отворения от дясно интервал [2, v).

Ето още един пример, изпълзващ логическото или: temp < 36.0 || temp > 36.9, който дава истина (сигнализира) когато температурата на човек е извън нормалния интервал [36.0, 36.9].

Операторът ! превръща стойността на своя операнд в противоположната, т.е. ако b  от таблицата е истина, то !b ще бъде неистина. И обратно - ако b е неистина, !b ще бъде истина. Например, горният пример може да бъде записан и по следния начин: !(temp >= 36.0 && temp <= 36.9), което буквално е твърдението "температурата не е в интервала [36.0, 36.9]".

3. Старшинство на логическите операторите (precedence relations). Тези три логически оператора имат различно старшинство по между си. Например, ако няма скоби в логическия израз, първо се изпълнява операторът  ! (не), след това && (и), и чак накрая || (или). Например кодът по-долу ще даде на екрана True!, защото първо се пресмята i && k, което е равносилно на 0 && 0, което е 0, а после се пресмята и операторът или, което е 0 || 1,  и което дава 1 (истина).

  1. int i = 0, j = 1, k = 0;
  2. if (i && k || j)
  3.   cout << "True!" << endl;         // print "True" if (i && k || j) is True
  4. else
  5.    cout << "False!" << endl;       // print "False" if (i && k || j) is False

! Тук изпреварваме малко събитията и използвахме оператора if-else. Фактически, ако (i && k || j) е истина ще се изпълни редът cout << "True!" << endl;, а ако не е - ще се изпълни този след else, който е out << "False!" << endl;.

Ако искаме да се изпълни първо изразът k || j, то трябва да го заградим със скоби, както е дадено по-долу. Този код ще дава резултат на екрана False!.

  1. int i = 0, j = 1, k = 0;
  2. if (i && (k || j))
  3.   cout << "True!" << endl;         // print "True" if (i && (k || j)) is True
  4. else
  5.    cout << "False!" << endl;       // print "False" if (i && (k || j)) is False

По същия начин има разлика и между тези два израза

!k && j

!(k && j)

Първият извършва логическо и между отрицанието на !k и j, докато втория извършва отрицание на и-то  между k и j.

Ако старшинството на логическите оператори е еднакво, то те се извършват отляво надясно.

4. Старшинство на операторите (precedence relations). Сега ще разгледаме старшинството на всички изучени досега оператори. То е дадено в таблица 3. Операторите в по-горните редове на таблицата имат по-голямо старшинство от намиращите се под тях, което ще рече, че при липса на скоби те се извършват първи. Това позволява свободното писане на следните изрази без необходимостта да се пишат скоби.

  1. temp < 36.0 || temp > 36.9  // същото като (tem < 36.0) || (temp > 36.9)
  2. y + 2 < x + 3               // същото като (y + 2) < (x + 3)
  3. bool = 2 * x < 3 * y        // същото като bool = ( (2 * x) < (3 * y) )

Таблица 3. Старшинство на операторите.
 

--------------------
Група оператори
Logical Operator
--------------------

------------------------
Тип на операторите
Operator Types
------------------------

----------------
Старшинство
Precedence 
----------------

* / % 

умножение и деление
Multiplicative 

най-високо

+ - 

сума и разлика
Additive 

 

< > <= >= == != 

за сравняване
Relational

 

&& ||

логически
Logical

 

=

присвояване
Assignment

най-ниско

--------------------

------------------------

----------------

Интересно е че операторът !(не) има по-голямо старшинство от операторите, дадени в таблица 3. Той се изпълнява първи, както може да се види от тези дефиниции и изрази, ако се поставят в програмен код и изпълнят:

 

  1. int i = 1, j = 0;
  2.   cout << "!i*j = " << !i*j << endl;       // the result is 0
  3.   cout << "!(i*j) = " << !(i*j) << endl;   // the result is 1
 

В първия израз i се превръща първо от 1 в 0 и после се умножава с j , което е 1 и дава 0. Във втория израз i и j се умножават като дават 0, която после се превръща в 1, с оператора !(не). Обърнете внимание, че 0-та се превръща в 1-ца!

Литература

[1] Robert Lafore; C++ Interactive Course. Waite Group Press, Macmillan Computer Publishing, 1996.

Проф. Процесор Аритметиков, Програмен език C++. [Част 07], Списание "Коснос", брой 14, 2007 г