Wprowadzenie
Zanim zaczniesz tworzyć jakieś pożyteczne programy, musisz przebrnąć przez masę podstaw. Na szczęście operacje logiczne są ostatnim podstawowym zagadnieniem, które należy wyjaśnić przed przejściem do właściwej nauki programowania w C++. Zanim podejmiesz się dalszej nauki C++, powinieneś mieć świadomość, że cała wiedza zebrana do tej pory będzie w 100% wykorzystywana w dalszych rozdziałach oraz będzie się nieustannie przeplatała wraz z nowymi, jeszcze nie omówionymi zagadnieniami. Jeśli więc czujesz, że jakiś rozdział był dla Ciebie nie do końca zrozumiały, to wróć teraz do niego.
Co to są operatory logiczne
Operatorami logicznymi nazywamy wszystkie spójniki klasycznego rachunku zdań. W przypadku języka C++ są to
i,
lub oraz
negacja.
Podstawowe operatory logiczne
Jak już wcześniej napisałem w C++ istnieją trzy podstawowe operatory logiczne. Zapis formalny przedstawiam w poniższej tabeli:
Operator negacji
Zajmijmy się najpierw operatorem negacji. W klasycznym rachunku zdań istnieją tylko dwa stany: prawda i fałsz. Negacją prawdy jest fałsz, natomiast negacją fałszu jest prawda. Zobaczmy więc jak to możemy zapisać formalnie w C++:
#include <iostream>
int main()
{
bool wynik = true;
std::cout << "wynik = " << wynik << std::endl;
std::cout << "wynik = " <<!wynik << std::endl;
std::cout << "wynik = " <<!!wynik << std::endl;
wynik = !wynik;
std::cout << "wynik = " << wynik << std::endl;
wynik = !( 123 > 345 );
std::cout << "wynik = " << wynik << std::endl;
return 0;
}
Zobaczmy teraz wynik działania programu:
wynik = 1
wynik = 0
wynik = 1
wynik = 0
wynik = 1
Wyniki otrzymujemy takie, jakich można było się spodziewać po klasycznym rachunku zdań. Spójrzmy jednak jeszcze raz na kod źródłowy programu. Zauważ, że gdy używasz operatora negacji to nie są potrzebne zaokrąglone nawiasy, tak jak to było w przypadku operatorów porównania.
Operator sumy logicznej
Jeśli chcemy wykonać operację sumy logicznej, to tak jak w dodawaniu arytmetycznym będziemy potrzebowali co najmniej dwóch wartości - z tą różnicą, że tutaj będą to wartości logiczne. Najłatwiej będzie to zobrazować na przykładzie:
#include <iostream>
int main()
{
bool wynik = false || false;
std::cout << "wynik (false || false) = " << wynik << std::endl;
wynik = false || true;
std::cout << "wynik (false || true) = " << wynik << std::endl;
wynik = true || true;
std::cout << "wynik (true || true) = " << wynik << std::endl;
bool a = false;
bool b = false;
wynik = a || b || true;
std::cout << "wynik (a || b || true) = " << wynik << std::endl;
bool c = false;
std::cout << "(a||b||c) = " <<( a || b || c ) << std::endl;
b = true;
std::cout << "(a||b||c) = " <<( a || b || c ) << std::endl;
std::cout << "(a|| !b ||c) = " <<( a || !b || c ) << std::endl;
return 0;
}
Zawartość konsoli po uruchomieniu programu:
wynik (false || false) = 0
wynik (false || true) = 1
wynik (true || true) = 1
wynik (a || b || true) = 1
(a||b||c) = 0
(a||b||c) = 1
(a|| !b ||c) = 0
Z wyników jakie otrzymaliśmy wynika, że suma logiczna faktycznie zwraca prawdę zawsze wtedy, gdy co najmniej jedna z wartości jest prawdziwa. Zwróć uwagę, że jeśli chcemy pisać wyrażenie bezpośrednio na ekran to musimy je 'opakować' w nawiasy z tego samego powodu, który został opisany w rozdziale poświęconym operatorom porównania.
Warto tutaj również wspomnieć, że klasyczny rachunek zdań w połączeniu z operatorami porównania daje bardzo duże możliwości manipulacji wynikami, jakie chcemy otrzymać. Oto przykład:
#include <iostream>
int main()
{
bool wynik;
int liczba;
liczba = - 100;
wynik = liczba >= 10 || liczba < 0 || liczba == 7;
std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
liczba = 0;
wynik = liczba >= 10 || liczba < 0 || liczba == 7;
std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
liczba = 7;
wynik = liczba >= 10 || liczba < 0 || liczba == 7;
std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
liczba = 8;
wynik = liczba >= 10 || liczba < 0 || liczba == 7;
std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
liczba = 10;
wynik = liczba >= 10 || liczba < 0 || liczba == 7;
std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
liczba = 100;
wynik = liczba >= 10 || liczba < 0 || liczba == 7;
std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
return 0;
}
Wynik działania powyższego programu będzie następujący:
liczba = -100, wynik = 1
liczba = 0, wynik = 0
liczba = 7, wynik = 1
liczba = 8, wynik = 0
liczba = 10, wynik = 1
liczba = 100, wynik = 1
Operator iloczynu logicznego
Iloczyn logiczny jest analogiczny w zapisie do sumy logicznej. Istotną różnicą są jednak otrzymywane wyniki. Prawdę otrzymamy wtedy i tylko wtedy gdy wszystkie wartości logiczne będą spełnione (czyli prawdziwe). Przejdźmy więc do kodu źródłowego kolejnego programu:
#include <iostream>
int main()
{
bool wynik = false && false;
std::cout << "wynik (false && false) = " << wynik << std::endl;
wynik = false && true;
std::cout << "wynik (false && true) = " << wynik << std::endl;
wynik = true && true;
std::cout << "wynik (true && true) = " << wynik << std::endl;
bool a = false;
bool b = false;
wynik = a && b && true;
std::cout << "wynik (a && b && true) = " << wynik << std::endl;
bool c = false;
std::cout << "(a&&b&&c) = " <<( a && b && c ) << std::endl;
b = true;
std::cout << "(a&&b&&c) = " <<( a && b && c ) << std::endl;
std::cout << "(a&& !b &&c) = " <<( a && !b && c ) << std::endl;
std::cout << "(!a && b && !c) = " <<( !a && b &&!c ) << std::endl;
return 0;
}
Tekst, który otrzymamy będzie następujący:
wynik (false && false) = 0
wynik (false && true) = 0
wynik (true && true) = 1
wynik (a && b && true) = 0
(a&&b&&c) = 0
(a&&b&&c) = 0
(a&& !b &&c) = 0
(!a && b && !c) = 1
Przeanalizuj otrzymane wyniki i sprawdź czy zgadzają się z zasadą przedstawioną w tym paragrafie.
Kolejność wykonywania operacji logicznych
Pamiętajmy, że tak samo jak w rachunku arytmetycznym, również tutaj obowiązuje kolejność wykonywania działań. Najważniejszy jest operator negacji, później wykonywane są operacje iloczynu logicznego, a na samym końcu sumy logicznej. Kolejnością wykonywania operacji można jednak manipulować poprzez zaokrąglone nawiasy - tak samo jak to miało miejsce w przypadku działań arytmetycznych. Zobaczmy na koniec program, który wykorzystuje całą omówioną w tym rozdziale wiedzę:
#include <iostream>
int main()
{
bool wynik;
wynik = true && false || !true && false || !( !true && false );
std::cout << "wynik = " << wynik << std::endl;
return 0;
}
Zadanie domowe
Eksperymenty z programem
Poeksperymentuj z wartościami logicznymi ostatniego programu i sprawdź jak będą się zmieniały wyniki. Przeanalizuj swoje zmiany i sprawdź czy wiesz dlaczego otrzymujesz dane wyniki. Odpowiedz sobie na pytanie: czy mając dowolne wyrażenie logiczne zapisane na kartce, będziesz w stanie podać prawidłowo wartość końcową (wynik)?
Test kolejności operacji logicznych
Napisz odpowiedni program dzięki któremu przetestujesz kolejność wykonywania operacji logicznych. Zrób co najmniej dwa programy. Pierwszy z nich niech nie wykorzystuje nawiasów zaokrąglonych, drugi program natomiast niech będzie modyfikacją pierwszego, który wymusi inną kolejność wykonania działań niż jest to standardowo zapewnione przez język C++.