§7 Логический тип данных. Инструкция if. Тернарная операция. Вложенные инструкции if. Инструкция switch

Логический тип данных

В языке C++ существует логический тип данных bool. Переменные этого типа могут содержать всего два значения – true (истина) и false (ложь). True и False являются логическими константами. В С++ true интерпретируется, как 1, а false как 0. Этот тип данных назван в честь Дж. Буля, разработавшего математическое представление законов логики. Поэтому переменные этого типа часто называются булевскими или логическими.

bool l, q = true, k = false;

Операции отношения (сравнения)

Операции отношения сравнивают два значения. В С++ определены следующие операции сравнения:

-----------------------------------
<  меньше
<= меньше либо равно
>  больше
>= больше либо равно
-----------------------------------
== равно
!= не равно
-----------------------------------

Примечание: выделены операции с равным приоритетом, последние две операции имеют более низкий приоритет.
Результатом сравнения двух выражений является true или false. Примеры:

int a = 2, b = 4;
bool f;
f = a > b;      // f => false
f = b % a == 0; // f => true
f = b * a != 0; // f => true
f = b / a >= 2; // f => true
f = a / b != 0; // f => false
f = b == 2 * a; // f => true

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

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

Логическое "И" (&&, and)

Логическая операция "И" (конъюнкция, логическое умножение) обозначается &&. Эта операция бинарная, т. е. имеет два операнда, в качестве которых могут выступать, например, операции отношения. Результат логического выражения true, если оба операнда истинны. Пример:

int a = 2, b = 4;
bool f;
f = a < b && b != 0;           //  f => true
f = a % 2 == 0 && b % a != 0;  //  f => false
f = a == 2 && b == b / 2;      //  f => true
f = b > a && b * b == 16;      //  f => true

Поскольку приоритет операций сравнения выше, чем у логических операций, их не нужно заключать в круглые скобки.

Логическое "ИЛИ" (||, or)

Логическая операция "ИЛИ" (дизъюнкция, логическое сложение) обозначается ||. Эта операция, тоже является бинарной. Результат логического выражения false, если оба операнда ложны. Пример:

int a = 2, b = 4;
bool f;
f = a > b || b == 0;           //  f => false
f = a % 2 == 0 || b % a != 0;  //  f => true
f = b == 2 || b == a / 2;      //  f => false
f = b <= a || b * b == 3;      //  f => false
Логическое "НЕ" (!, not)

Логическое "НЕ" или логическое отрицание (инверсия) является операцией унарной (один операнд). Обозначается !. Результат true, если операнд false, и наоборот. Например:

!(x > 5)  // "не больше 5", иначе x <= 5
!(x == 7) // "не равно 7", что эквивалентно x != 7

Среди остальных операций - логическое отрицание обладает высшим приоритетом, поэтому выражение с арифметическими операциями и/или операциями сравнения нужно заключать в скобки.

    Примечание:

  • В С++ предусмотрено альтернативное представление логических операций: and, or и not.
  • Логическая операция and имеет более высокий приоритет, чем or, следовательно, выражение
     a && b || c

    должно восприниматься как

     (a && b) || c

Если в выражении с && первый операнд определяется как false, то все оставшееся выражение не вычисляется. Аналогично, если в выражениях с || первый операнд определяется как true, то все оставшееся выражение не вычисляется (т. н. "ленивые вычисления", вытекающие из свойств данных операций).

Условная инструкция if

Условная инструкция if позволяет выбрать направление выполнения алгоритма в зависимости от поставленного условия. Условная инструкция реализует алгоритмическую структуру ветвление. Общий синтаксис инструкции:

if (логическое выражение)
{
    инструкция_1; // Если условие true
}
else 
{ 
    инструкция_2; // Если условие false
}

Существует несколько стилей представления кода в котором присутствуют блоки. Для компактности кодинга рекомендуется использовать следующий стиль:

if (expr) {
    Stm1;
} else { 
    Stm2;
}

10
Изображенный на рисунке выше тип ветвления называется полным ветвлением.
Логическое выражение не обязательно должно быть логического типа, но должно иметь скалярный результат: целое число, число с плавающей точкой, символьная величина или указатель. Если результатом вычисления выражения является ненулевое значение, то в С++ такой результат интерпретируется как true, в противном случае - false. Это позволяет сократить логическое выражение, опустив операций сравнения. Например: (!(x % 2)) "если четное число".
Примечание: очень распространенной ошибкой является использование в качестве логическое выражения a = b, вместо a == b. В С++ использование a = b (присваивание) в качестве логического выражения не является ошибкой, но может привести к семантической ошибке.
Например:

int a;
cin >> a;
if (a = 1)
    ++a;

В данном примере каким бы ни было значение переменной a, её значение, по выполнению условной инструкции, будет равно 2! Справедливости ради, нужно сказать, что современные IDE (среды разработки) могут предупреждать об использовании присваивания в качестве логического выражения.
Если инструкция_1 и инструкция_2 не являются составными (т.е. имеют не более одной инструкции в ветви), то {} можно опустить. Если ветвь на else отсутствует, то условная инструкция приобретает сокращенную форму неполного ветвления. В неполном ветвлении, если логическое выражение в условии ложно - будет выполнятся код, следующий за условной инструкцией. Примеры программ.
Программа 7.1.

//============================================================================
// Неполное ветвление. Определить является ли число N
// кратным числу K
//============================================================================
#include <iostream>
using namespace std;

int main() {
    int N, K;
    cout << "N = "; cin >> N;
    cout << "K = "; cin >> K;
    if(N % K == 0) 
        cout << N << " кратно " << K << endl;
    return 0;
}

11Блок-схема к программе 7.1

Программа 7.2

//============================================================================
// Полное ветвление. Введены два числа. Определить порядковый номер 
// большего из них.
//============================================================================
#include <iostream>
using namespace std;

int main() {
    int a, b;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    if(a > b) 
        cout << 1 << endl;
    else
        cout << 2 << endl;
    return 0;
}

12Блок-схема к программе 7.2

Поскольку конструкция if else воспринимается как одна инструкция, то она может входить внутрь другой условной инструкции, создавая, таким образом, структуру вложенного ветвления. Пример задачи.
Программа 7.3

//============================================================================
// Вложенное ветвление. Даны две переменные целого типа: A и B. 
// Если их значения не равны, то присвоить каждой переменной большее из этих 
// значений, а если равны, то присвоить переменным нулевые значения. Вывести 
// новые значения переменных A и B.
//============================================================================
#include <iostream>
using namespace std;

int main() {
	int a, b;
	cout << "a = "; cin >> a;
	cout << "b = "; cin >> b;
	if (a != b)
		if (a > b)
			b = a;
		else
			a = b;
	else
		a = b = 0;
	cout <<   "a = " << a
		 << ", b = " << b
		 << endl;
	return 0;
}

14Блок-схема к программе 7.3

Тернарная (условная) операция

В языке С++ существует операция, которая в более компактной форме может заменить (но не всегда!) условную инструкцию if else. Эта операция требует наличия трех операндов, поэтому называется тернарной или условной операцией. Общий синтаксис таков:

Условие ? Выражение_1 : Выражение_2

Например:

int c = a > b ? a : b;
// аналогично:
int с;
if (а > b)
    с = а;
else
    с = b;

Тернарная операция позволяет придать выражению более лаконичных характер, нежели при использовании условной инструкции if. Значение тернарной операции можно присваивать другим переменным и использовать его в любом выражении, как слева так и справа, где допускается использование переменной. В этом заключается различие между условной инструкцией и условной операцией. Примеры использования:

min = (a < b) ? a : b;                // присвоить минимальное
cout << (!(j % 2) ? ' ' : 'x');       // вывод в зависимости от кратности
(false ? i: j) = 10;                  // i и j одного типа!
a > b ? cout << a : cout << b;        // выводим максимальное
return (x == 0) ? 1 : x * fact(x - 1) // рекурсия

Инструкция switch

Если требуется сделать выбор из большого списка выражений и при этом избежать многократной вложенности условных операторов друг в друга вида if if else if else ... else, то можно использовать инструкцию switch. Синтаксис этой инструкции таков:

switch (Выражение-селектор){
case метка_1 : оператор_1; break;
case метка_2 : оператор_2; break;
...
case метка_n : оператор_n; break;
default : оператор_m;
}

Здесь метка_1, метка_2 и т.д. обозначают целочисленные константы, которыми помечены строки перехода начинаемые с case. Вычисляется выражение-селектор целочисленного типа. Далее управление передается на строку с меткой, имеющей значение равное выражению-селектору. Если такого значения среди меток найдено не будет, то переход осуществляется к строке на default, которая является необязательной.
Программа 7.4

//============================================================================
// Дано целое число K. Вывести строку-описание оценки, соответствующей числу 
// K (2 — «неудовлетворительно», 3 — «удовлетворительно», 4 — «хорошо», 5 — 
// «отлично»). Если K не лежит в диапазоне 1–5, то вывести строку «ошибка».
//============================================================================
#include <iostream>
using namespace std;

int main() {
    int k;
    cout << "k = "; cin >> k;
    switch(k){
		case 2:  cout << "неуд."  << endl; break;
		case 3:  cout << "удовл." << endl; break;
		case 4:  cout << "хор."   << endl; break;
		case 5:  cout << "отл."   << endl; break;
		default: cout << "ошибка" << endl;
    }
    return 0;
}

13Блок-схема к программе 7.4

Вопросы
  1. Каким должен быть результат логического выражения в инструкции if, чтобы выполнялась ветвь на иначе
  2. Когда используется неполная форма инструкции if?
  3. Объясните в чем отличие операций or и and. Какой операции соответствует "&&", а какой "||" ?
  4. Почему в условии можно опустить операции сравнения?
  5. В чем опасность использования вместо операции сравнения ==, операцию присваивания (=)?
  6. Приведите примеры когда можно заменить инструкцию if тернарной операцией.
  7. Можно ли заменить (a % 3 == 0) на (!(a % 3))? Аргументируйте свой ответ.
  8. Когда лучше использовать инструкцию switch, а не инструкцию if?
Домашнее задание
  1. Даны целочисленные координаты точки на плоскости. Если точка совпадает с началом координат, то вывести 0. Если точка не совпадает с началом координат, но лежит на оси OX или OY, то вывести соответственно 1 или 2. Если точка не лежит на координатных осях, то вывести 3.
  2. Дано целое число. Вывести его строку-описание вида «отрицательное четное число», «нулевое число», «положительное нечетное число» и т. д.
  3. Даны коэффициенты a, b и c. Найдите вещественные корни квадратного уравнения, если вещественных корней нет - сообщите об этом.
Учебник

§57, вопр. 1-12

Литература
  1. Лафоре Р. Объектно-ориентированное программирование в C++ (4-е изд.). Питер: 2004
  2. Прата, Стивен. Язык программирования C++. Лекции и упражнения, 6-е изд.: Пер. с англ. — М.: ООО «И.Д. Вильяме», 2012
  3. Липпман Б. Стенли, Жози Лажойе, Барбара Э. Му. Язык программирования С++. Базовый курс. Изд. 5-е. М: ООО "И. Д. Вильямс", 2014
  4. Эллайн А. C++. От ламера до программера. СПб.: Питер, 2015
  5. Шилдт Г. С++: Базовый курс, 3-изд. М.: Вильямс, 2010


Print Friendly, PDF & Email

Добавить комментарий