Typ boolowski
Typ bool
Jeśli pamiętasz z lekcji o zmiennych,
jednym z podstawowych typów jest bool
. Typ ten reprezentuje wartość logiczną
(wartość boolowską), która ma tylko jedną wartość true
lub false
.
Wyrażenia boolowskie,
o których dowiedzieliśmy się na początku tej lekcji o warunkach, ewaluują się do wartości logicznej (boolowskiej).
Możemy więc stworzyć zmienne, które są wynikami takich wyrażeń logicznych, a następnie
dalej używać tych zmiennych bool
w warunkach instrukcji if.
W C++ istnieją dwie wbudowane wartości logiczne - true
i false
. Można ich użyć wszędzie tam,
gdzie oczekiwany jest typ bool
lub wyrażenie boolowskie. Dla przykładu:
bool var1 = true;
bool var2 = false;
Są też ciekawsze rzeczy, które możemy zrobić ze zmiennymi bool
.
Każde wyrażenie boolean można przypisać do zmiennej. Połączenie tego z
instrukcjami if może w niektórych przypadkach skrócić kod i uczynić go bardziej czytelnym.
std::string name;
std::cout << "Enter your first name: ";
std::cin >> name;
// Użytkownik jest szczęśliwy, jeśli jego imię ma więcej niż 5 znaków
bool is_lucky = name.size() > 5;
// Spróbuj pozmieniać te wartości i zobacz co się stanie!
bool is_tuesday = true;
bool is_cloudy = false;
std::string weather = "sunny";
if (not is_tuesday and is_cloudy) {
weather = "raining";
} else if (is_tuesday) {
if (is_cloudy) {
weather = "overcast";
} else if (not is_lucky) {
weather = "downpouring";
}
}
std::cout << "It is currently " << weather << " in your location!";
Wcześniej wprowadzone operatory logiczne mogą zostać użyte do stworzenia nowych zmiennych boolowskich:
bool is_precipitating = weather == "raining" or weather == "downpouring";
bool is_rainbow_made = is_precipitating and not is_cloudy;
bool is_boring_day = not is_rainbow_made;
Wczytywanie/Wypisywanie typów boolowskich
Jeśli próbowałeś sam eksperymentować z typem bool
, mogłeś zauważyć, że wypisanie zmiennej lub wyrażenia
tego typu nie wyświetla true
czy false
, a 1
lub 0
.
Jest to domyślne zachowanie w C++, które jest związane z następną sekcją.
Możesz zmienić to zachowanie w prosty sposób zmieniając jedno z domyślnych ustawień std::cout
.
Po prostu "wypisz" flagę std::boolalpha
za pomocą std::cout
. Spowoduje to, że każde przyszłe wyrażenie logiczne lub
zmienna typu bool
zostanie wypisana w postaci true
/false
, zamiast 1
/0
.
Upewniej się, że dołączyłeś nagłówek <iomanip>
(#include <iomanip>
), aby móc użyć std::boolalpha
.
std::cout << true << " " << false << "\n";
std::cout << std::boolalpha;
std::cout << true << " " << false << "\n";
1 0
true false
Tak samo std::cin
domyślnie akceptuje tylko 0
lub 1
przy wprowadzaniu do zmiennej bool
.
To zachowanie może być również zmienione przez "wprowadzenie" do flagi std::boolalpha
.
W poniższym przykładzie, użytkownik najpierw wprowadzi 0
, co reprezentuje false
.
Następnie, wprowadzi true
po zastosowaniu ustawienia std::boolalpha
.
bool var;
std::cout << "Integral form: ";
std::cin >> var;
std::cin >> std::boolalpha;
std::cout << "Alphanumeric form: ";
std::cin >> var;
Integral form: 1
Alphanumeric form: true
Jako ćwiczenie, spróbuj zmodyfikować nasz program pogodowy, tak, aby przyjmował true
/false
,
zamiast 1
/0
.
Nazwa "boolalpha" pochodzi ze złączenia słów boolean i alphanumeric (ang.: alfanumeryczny)
Konwersja pomiędzy int
a bool
C++ posiada kolejne, dość denerwujące, zachowanie, które powoduje, że liczby i typy boolowskie mogą
się niejawnie konwertować pomiędzy sobą.
Wartość boolowska false
odpowiada liczbie o wartośći 0
, a true
wartości 1
.
Tak samo liczba o wartości 0
odpowiada wartości boolowskiej false
, a każda inna od 0
odpowiada wartości true
.
int x = true; // x to 1
int y = false; // y to 0
bool a = 1; // a to true
bool b = 25; // b to true
bool c = -194; // c to true
bool d = 0; // d to false
Mimo, że to zachowanie może się wydawać przydatne, czasem może się zdarzyć, że konwersja wydarzy się wtedy,
kiedy nie jest chciana.
Z tego powodu, jeśli chcesz intencjonalnie spowodować konwersję pomiędzy int
(lub każdym innym typem całkowitoliczbowym),
a bool
użyć casta.
int x = static_cast<int>(true); // Nowoczesny styl castowania
int y = (int) false; // Castowanie w stylu C
bool a = static_cast<bool>(1);
bool b = (bool) 0;
Są dwa sposoby na jakie możemy przeprowadzić takie castowanie w C++ - castowanie nazwane, a konkretnie static_cast (nowoczesny sposób), lub castowanie w stylu C.
Różnice między nimi poznasz w kursie dla średniozaawansowanych. Na razie wiedz tylko, że,
w przypadku konwersji pomiędzy int
, a bool
, obie opcje są równoważne.
Jednak w nowoczesnym C++ generalnie preferowane jest używanie static_cast
.
Niechciane konwersje
Niechciane konwersje mogą powodować problemy tak, gdzie najmniej się ich spodziewasz. Jednym z przykładów jest problem, który omówiliśmy w złożone warunki logiczne. Normalnie, jeśli chcemy połączyć dwa wyrażenia logiczne, używamy do tego operatorów logicznych:
if (x > 10 && x < 25) { ... }
Może Cię kusić, aby przepisać ten warunek jako 10 < x < 25
.
To spowoduje, że program będzie się zachowywać niepoprawnie, ponieważ to wyrażenie będzie zawsze prawdziwe.
Dzieje się tak, ponieważ zachodzi tutaj ukryta konwersja z bool
na int
.
To wyrażenie jest interpretowane w taki sposób: (10 < x) < 25
.
Zobaczmy więc w jaki sposób to wyrażenie zawsze ewaluuje się do true
odnosząc się do
naszej tabeli priorytetów operatorów:
10 < x < 25 // Początkowe wyrażenie
10 < 15 < 25 // Podstawiamy x
(10 < 15) < 25 // Kolejność operatorów
(true) < 25 // Ewaluujemy podwyrażenie
1 < 25 // Konwersja z bool na int
true // Ewaluujemy wyrażenie
10 < x < 25 // Początkowe wyrażenie
10 < 7 < 25 // Podstawiamy x
(10 < 7) < 25 // Kolejność operatorów
(false) < 25 // Ewaluujemy podwyrażenie
0 < 25 // Konwersja z bool na int
true // Ewaluujemy wyrażenie
Ten sam problem może wystąpić również w innych, podobnych scenariuszach.
Na przykład, podczas sprawdzania, czy pojedyncza zmienna jest jedną z wielu możliwości,
poprawnym sposobem byłoby x == 5 || x == 10 || x == 15
.
Kusząca opcja x == 5 || 10 || 15
nie zadziała z podobnego powodu jak wyżej -
zawsze będzie to prawda. Zobaczmy dlaczego:
x == 5 || 10 || 15 // Początkowe wyrażenie
5 == 5 || 10 || 15 // Podstawiamy x
((5 == 5) || 10) || 15 // Kolejność operatorów
((true) || 10) || 15 // Ewaluujemy podwyrażenie
(true || true) || 15 // Konwersja z int na bool
true || 15 // Ewaluujemy podwyrażenie
true || true // Konwersja z int na bool
true // Ewaluujemy wyrażenie
x == 5 || 10 || 15 // Początkowe wyrażenie
7 == 5 || 10 || 15 // Podstawiamy x
((7 == 5) || 10) || 15 // Kolejność operatorów
((false) || 10) || 15 // Ewaluujemy podwyrażenie
(false || true) || 15 // Konwersja z int na bool
true || 15 // Ewaluujemy podwyrażenie
true || true // Konwersja z int na bool
true // Ewaluujemy wyrażenie
Konkluzja
Podsumowaując, nauczyliśmy się:
- Rozdzielać warunkowe ścieżki w programie za pomocą instrukcji warunkowej if
- Tworzyć wyrażenia logiczne
- Łączenia kilka warunków we wzajemnie wykluczające się grupy
- Zagnieżdżać ify wewnątrz siebie
- Redukować powtarzanie się kodu poprzez stosowanie zasady DRY
- Używać zmiennych boolowskich, aby ulepszyć nasz kod
To była długa podróż, ale umiejętności, które zebrałeś w tej lekcji są bardzo ważne dla przyszłej drogi. Przeczytaj kilka razy koncepcje przedstawione w tej lekcji, ponieważ podstawy wyrażeń logicznych i instrukcji warunkowych są bardzo ważną umiejętnością.