C++; Логика и условный оператор

Логические операции

Мы уже знаем, что для разных данных есть разные типы. Есть специальных тип для работы с данными логического типа (bool). Все это звучит зловеще, но сейчас все станет понятно.

Мы познакомимся с основами логики высказываний, которая занимается анализом выражений, состоящих из высказываний и нескольких операций (и, или и т.д.).

Если немного упростить, то основные положения логики высказываний таковы.

  1. Каждое из высказываний либо истинно либо ложно.
    • В языке C++ ложью считается нулевое значение (false = 0), а истиной все остальные, чаще всего берут единицу (true = 1).
    • Выражения ture и false корректны.
  2. Есть операция отрицания, которая true переводит в false, а false в true.
    • Отрицание в C++ обозначается восклицательным знаком (!).
    • Если A — корректное выражение, то !A тоже корректное выражение.
  3. Есть бинарные операции, например и (обозначается &&), или (обозначается ||).
    • Если @ — бинарная операция, а A и B — корректные выражения, то (A @ B) тоже корректное выражение.
    • Обратите внимание на скобки, они обязательно должны присутствовать. Порядок действий определяется скобками по обычным правилам.

Приведем несколько корректных примеров логических выражений.

true && false
true && !(true || true)

Обычно логические значения возникают при работе с условиями, например n > 5. На практике использование логических операций сводится к работе с составными условиями. Например, n > 5 и m > 1.

Бинарные логические операции, таблицы истинности

Для того, чтобы определить логическую операцию, достаточно определить ее значение на всех входных данных. Это сделать просто, так как вариантов входных данных всего четыре:

  1. (false, false)
  2. (false, true)
  3. (true,false)
  4. (true, true)

Чаще всего на практике встречаются логические операции и и или. Если коротко, то операция и (&&) возвращает истину, если оба аргумента истины, а или (||), если истинен хотя бы один из них. Давайте посмотрим на программу, которая выводит результат применения этих операций на всех возможных входных данных.

Программа:

#include<iostream>

using namespace std;

int main()
{
    cout << "true  && true  = " <<  (true  && true ) << endl;
    cout << "false && true  = " <<  (false && true ) << endl;
    cout << "true  && false = " <<  (true  && false) << endl;
    cout << "false && false = " <<  (false && false) << endl;
    cout << "------------------" << endl;
    cout << "true  || true  = " <<  (true  || true ) << endl;
    cout << "false || true  = " <<  (false || true ) << endl;
    cout << "true  || false = " <<  (true  || false) << endl;
    cout << "false || false = " <<  (false || false) << endl;
}

Вывод:

true  && true  = 1
false && true  = 0
true  && false = 0
false && false = 0
------------------
true  || true  = 1
false || true  = 1
true  || false = 1
false || false = 0

Удобно записывать логические операции в виде таблицы, напоминающей таблицу умножения или сложения. Давайте перепишем вывод нашей программы в виде таблицы. Для краткости вместо true и false в таблице запишем 1 и 0.

|| 0 1
0 0 1
1 1 1
&& 0 1
0 0 0
1 0 1

В качестве упражнения проверьте, что значение обоих выражений из примера равно false.

true && false
true && !(true || true)

Условный оператор

Для того, чтобы обсуждать новые структуры языка, давайте вспомним то, что уже знаем. На данный момент мы умеем писать программы, состоящие из простых инструкций (команд), которые выполняются последовательно, одна за другой.

До сих пор все наши программы «были очень глупыми», у них с самого начала была какая-то тактика и они ее придерживались. «Я буду делать, то что написано, и ничто не изменит моего поведения.» Ясно, что с таким подходом ничего особенного умного не сделать, нужно действовать хитрее, для разных входных данных нужно действовать по разному.

Синтаксис условного оператора

Для того чтобы реализовать разное поведение в разных условиях существует специальная конструкция, которая называется условным оператором. Ее структура проста, она состоит из условия и инструкции, если условие выполнено, то инструкция исполняется.

if (условие) инструкция;

Заметьте, что условие записано в скобках. Все из-за того, что на самом деле оператор if получает на вход логическое значение. Скобки нужны для того, чтобы сначала вычислилось условие , получилось логическое значение, и уже оно передалось в if.

Давайте рассмотрим пример — программу, которая на вход получает целое число, и если число четное, то сообщает об этом, а если нечетное, то ничего не выводит.

#include<iostream>

using namespace std;

int main()
{
    int n;                                  // Заводим переменную n для нашего числа.
    cin >> n;                               // Считываем в переменную n значение с клавиатуры.
    if (n % 2 == 0)                         // Если остаток от деления на 2 равен нулю, то 
        cout << n << " is even." << endl;   // выводим сообщение о том, что число четное. 
}

Здесь нам встретился новый оператор ==. Этот оператор сравнивает два значения, важно не путать операторы равно == и присвоить =. Оператор == сравнивает два значения, не меня переменные, а оператор присваивания = записывает значение выражения слева от себя в переменную.

Напрашивается улучшение наше программы, сейчас она выводит сообщение только в случае если число четное. Давайте изменим ее так, чтобы сообщение выводилось и в случае, если число нечетное. В этом нам поможет следующая конструкция:

if (условие) 
    инструкция_1;
else 
    инструкция_2;

Если условие выполнилось, то исполнится инструкция_1, а если нет, то инструкция_2. Посмотрим на пример.

#include<iostream>

using namespace std;

int main()
{
    int n;                                  // Заводим переменную n для нашего числа.
    cin >> n;                               // Считываем в переменную n значение с клавиатуры.
    if (n % 2 == 0)                         // Если остаток от деления на 2 равен нулю, то 
        cout << n << " is even." << endl;   // выводим сообщение о том, что число четное. 
    else                                    // Иначе 
        cout << n << " is odd."  << endl;   // выводим сообщение о том, что число нечетное.
}

Простые и составные инструкции

Мы описали конструкцию if-else для простых инструкций. А что, если нам хочется выполнить несколько действий и одной простой инструкцийе не обойтись. Тут нам на помощь приохдят фигурные скобки {}, которые позоволяют опбеденить несколько инструкций в одну. Так {инструкция_1; инструкция_2; инструкция_3;} воспринимается как одна инструкция. Перепишем предыдущий пример, переписанный с использованием этих скобок.

#include<iostream>

using namespace std;

int main()
{
    int n;                                  // Заводим переменную n для нашего числа.
    cin >> n;                               // Считываем в переменную n значение с клавиатуры.
    if (n % 2 == 0)                         // Если остаток от деления на 2 равен нулю, то 
    {
        cout << n << " is even." << endl;   // выводим сообщение о том, что число четное. 
    }
    else                                    // Иначе 
    {
        cout << n << " is odd."  << endl;   // выводим сообщение о том, что число нечетное.
    }
}

Инструкция по прежнему одна, но теперь появились скобки. Такой вариант тоже будет работать. Давайте теперь разделим вывод на несколько инструкций.

#include<iostream>

using namespace std;

int main()
{
    int n;                                  // Заводим переменную n для нашего числа.
    cin >> n;                               // Считываем в переменную n значение с клавиатуры.
    if (n % 2 == 0)                         // Если остаток от деления на 2 равен нулю, то 
    {
        cout << n;                          // выводим само число n в отдельной инструкции. 
        cout << " is even." << endl;        // выводим сообщение о том, что число четное. 
    }
    else                                    // Иначе 
    {
        cout << n;                          // выводим само число n в отдельной инструкции. 
        cout << " is odd."  << endl;        // выводим сообщение о том, что число нечетное.
    }
}

Такой вариант будет работать точно так же.