ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 30.03.2021

Просмотров: 456

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


Остаток от деления можно получить с помощью оператора деления по модулю (%). Этот оператор работает практически так же, как в других языках программирования: возвращает остаток от деления нацело. Например, 10%3 равно 1. Это означает, что в C++ оператор "%" нельзя применять к типам с плавающей точкой (float или double). Деление по модулю применимо только к целочисленным типам.


Инкремент и декремент

В C++ есть два оператора, которых нет в некоторых других языках программирования. Это операторы инкремента (++) и декремента (--). Они упоминались в главе 2, когда речь шла о цикле for. Оператор инкремента выполняет сложение операнда с числом 1, а оператор декремента вычитает 1 из своего операнда. Это значит, что инструкция


х = х + 1;

аналогична такой инструкции:


++х;

А инструкция


х = х - 1;

аналогична такой инструкции:


--x;

Операторы инкремента и декремента могут стоять как перед своим операндом (префиксная форма), так и после него (постфиксная форма). Например, инструкцию


х = х + 1;

можно переписать в виде префиксной формы


++х; // Префиксная форма оператора инкремента.

или в виде постфиксной формы:


х++; // Постфиксная форма оператора инкремента.


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


х = 10;


у = ++x;

В этом случае переменная у будет установлена равной 11. Но если в этом коде префиксную форму записи заменить постфиксной, переменная у будет установлена равной 10:


х = 10;


у = x++;

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

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

Арифметические операторы подчиняются следующему порядку выполнения действий.


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



Операторы отношений и логические операторы

Операторы отношений и логические (булевы) операторы, которые часто идут "рука об руку", используются для получения результатов в виде значений ИСТИНА/ЛОЖЬ. Операторы отношений оценивают по "двубалльной системе" отношения между двумя значениями, а логические определяют различные способы сочетания истинных и ложных значений. Поскольку операторы отношений генерируют ИСТИНА/ЛОЖЬ-результаты, то они часто выполняются с логическими операторами. Поэтому мы и рассматриваем их в одном разделе.

Операторы отношений и логические (булевы) операторы перечислены в табл. 3.6. Обратите внимание на то, что в языке C++ в качестве оператора отношения "не равно" используется символ "!=", а для оператора "равно" — двойной символ равенства (==). Согласно стандарту C++ результат выполнения операторов отношений и логических операторов имеет тип bool, т.е. при выполнении операций отношений и логических операций получаются значения true или false. При использовании более старых компиляторов результаты выполнения этих операций имели тип int (нуль или ненулевое целое, например 1). Это различие в интерпретации значений имеет в основном теоретическую основу, поскольку C++ автоматически преобразует значение true в 1, а значение false — в 0, и наоборот.

Операнды, участвующие в операциях "выяснения" отношений, могут иметь практически любой тип, главное, чтобы их можно было сравнивать. Что касается логических операторов, то их операнды должны иметь тип bool, и результат логической операции всегда будет иметь тип bool. Поскольку в C++ любое ненулевое число оценивается как истинное (true), а нуль эквивалентен ложному значению (false), то логические операторы можно использовать в любом выражении, которое дает нулевой или ненулевой результат.


Помните, что в C++ любое ненулевое число оценивается как true, а нуль— как false.

Логические операторы используются для поддержки базовых логических операций И, ИЛИ и НЕ в соответствии со следующей таблицей истинности. Здесь 1 используется как значение ИСТИНА, а 0 — как значение ЛОЖЬ.


Несмотря на то что C++ не содержит встроенный логический оператор "исключающее ИЛИ" (XOR), его нетрудно "создать" на основе встроенных. Посмотрите, как следующая функция использует операторы И, ИЛИ и НЕ для выполнения операции "исключающее ИЛИ".


bool хоr(bool a, bool b)


{


 return (а || b) && !(а && b);


}

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


// Эта программа демонстрирует использование функции хоr().

#include <iostream>

using namespace std;

bool хоr(bool a, bool b);

int main()

{

 bool p, q;

 cout << "Введите P (0 или 1): ";

  cin >> p;

 cout << "Введите Q (0 или 1): ";

  cin >> q;

 cout << "P И Q: " << (p && q) << ' \n';


 cout << "P ИЛИ Q: " << (p || q) << ' \n';

 cout << "P XOR Q: " << xor(p, q) << '\n';

 return 0;

}

bool хоr(bool a, bool b)

{

 return (a || b) && !(a && b);

}

Вот как выглядит возможный результат выполнения этой программы.

Введите Р (0 или 1): 1

Введите Q (0 или 1): 1

Р И Q: 1

Р ИЛИ Q: 1

Р XOR Q: 0

В этой программе обратите внимание вот на что. Хотя параметры функции xor() указаны с типом bool, пользователем вводятся целочисленные значения (0 или 1). В этом ничего нет странного, поскольку C++ автоматически преобразует число 1 в true, а 0 в false. И наоборот, при выводе на экран bool-значения, возвращаемого функцией xor(), оно автоматически преобразуется в число 0 или 1 (в зависимости от того, какое значение "вернулось": false или true). Интересно отметить, что, если типы параметров функции хоr() и тип возвращаемого ею значения заменить типом int, эта функция будет работать абсолютно так же. Причина проста: все дело в автоматических преобразованиях, выполняемых С++-компилятором между целочисленными и булевыми значениями.

Как операторы отношений, так и логические операторы имеют более низкий приоритет по сравнению с арифметическими операторами. Это означает, что такое выражение, как 10 > 1+12 будет вычислено так, как если бы оно было записано в таком виде: 10 >(1 + 12)

Результат этого выражения, конечно же, равен значению ЛОЖЬ. Кроме того, взгляните еще раз на инструкции вывода результатов работы предыдущей программы на экран.


cout << "Р И Q: " << (р && q) << '\n';


cout << "Р ИЛИ Q: " << (р | | q) << '\n';

Без круглых скобок, в которые заключены выражения р && q и р || q, здесь обойтись нельзя, поскольку операторы && и || имеют более низкий приоритет, чем оператор вывода данных.

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


var>15 || !(10<count) && 3<=item

Приоритет операторов отношений и логических операторов показан в следующей таблице.


Выражения

Операторы, литералы и переменные — это все составляющие выражений. Вероятно, вы уже знакомы с выражениями по предыдущему опыту программирования или из школьного курса алгебры. В следующих разделах мы рассмотрим аспекты выражений, которые касаются их использования в языке C++.


Преобразование типов в выражениях

Если в выражении смешаны различные типы литералов и переменных, компилятор преобразует их к одному типу. Во-первых, все char- и short int-значения автоматически преобразуются (с расширением "типоразмера") к типу int. Этот процесс называется целочисленным расширением (integral promotion). Во-вторых, все операнды преобразуются (также с расширением "типоразмера") к типу самого большого операнда. Этот процесс называется расширением типа (type promotion), причем он выполняется по операционно. Например, если один операнд имеет тип int, а другой — long int, то тип int расширяется в тип long int. Или, если хотя бы один из операндов имеет тип double, любой другой операнд приводится к типу double. Это означает, что такие преобразования, как из типа char в тип double, вполне допустимы. После преобразования оба операнда будут иметь один и тот же тип, а результат операции — тип, совпадающий с типом операндов.


Рассмотрим, например, преобразование типов, схематически представленное на рис. 3.1. Сначала символ ch подвергается процессу "расширения" типа и преобразуется в значение типа int. Затем результат операции ch/i приводится к типу double, поскольку результат произведения f*d имеет тип double. Результат всего выражения получит тип double, поскольку к моменту его вычисления оба операнда будут иметь тип double.


Преобразования, связанные с типом bool

Как упоминалось выше, значения типа bool автоматически преобразуются в целые числа 0 или 1 при использовании в выражении целочисленного типа. При преобразовании целочисленного результата в тип bool нуль преобразуется в false, а ненулевое значение — в true. И хотя тип bool относительно недавно был добавлен в язык C++, выполнение автоматических преобразований, связанных с типом bool, означает, что его введение в C++ не имеет негативных последствий для кода, написанного для более ранних версий C++. Более того, автоматические преобразования позволяют C++ поддерживать исходное определение значений ЛОЖЬ и ИСТИНА в виде нуля и ненулевого значения. Таким образом, тип bool очень удобен для программиста.


Приведение типов

В C++ предусмотрена возможность установить для выражения заданный тип. Для этого используется операция приведения типов (cast). Итак, общий формат операции приведения типов таков:


(тип) выражение

Здесь элемент тип означает тип, к которому необходимо привести выражение. Например, если вы хотите, чтобы выражение х/2 имело тип float, необходимо написать следующее:


(float) х / 2

Приведение типов рассматривается как унарный оператор, и поэтому он имеет такой же приоритет, как и другие унарные операторы.

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


#include <iostream>

using namespace std;

int main() /* Выводим i и значение i/2 с дробной частью.*/

{

 int i;

 for(i=1; i<=100; ++i )

  cout << i << "/ 2 равно: " << (float) i / 2 << '\n';

 return 0;

}

Без оператора приведения типа (float) выполнилось бы только целочисленное деление. Приведение типов в данном случае гарантирует, что на экране будет отображена и дробная часть результата.


Использование пробелов и круглых скобок

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


х=10/у*(127/х);


х = 10 / у * (127/х);

Круглые скобки (так же, как в алгебре) повышают приоритет операций, содержащихся внутри них. Использование избыточных или дополнительных круглых скобок не приведет к ошибке или замедлению вычисления выражения. Другими словами, от них не будет никакого вреда, но зато сколько пользы! Ведь они помогут прояснить (для вас самих в первую очередь, не говоря уже о тех, кому придется разбираться в этом без вас) точный порядок вычислений. Скажите, например, какое из следующих двух выражений легче понять?



х = у/3-34*temp+127;


X = (у/3) - (34*temp) + 127;


Глава 4: Инструкции управления

В этой главе вы узнаете, как управлять ходом выполнения С++-программы. Существует три категории управляющих инструкций: инструкции выбора (if, switch), итерационные инструкции (состоящие из for-, while- и do-while-циклов) и инструкции перехода (break, continue, return и goto).

За исключением return, все остальные перечисленные выше инструкции описаны в этой главе.

Инструкция if

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

Инструкция if была представлена в главе 2, но здесь мы рассмотрим ее более детально. Полный формат ее записи таков.


if(выражение) инструкция;


else инструкция;

Здесь под элементом инструкция понимается одна инструкция языка C++. Часть else необязательна. Вместо элемента инструкция может быть использован блок инструкций. В этом случае формат записи if-инструкции принимает такой вид.


if(выражение)

{

 последовательность инструкций

}

else

{

 последовательность инструкций

}

Если элемент выражение, который представляет собой условное выражение, при вычислении даст значение ИСТИНА, будет выполнена if-инструкция; в противном случае else-инструкция (если таковая существует). Обе инструкции никогда не выполняются. Условное выражение, управляющее выполнением if-инструкции, может иметь любой тип, действительный для С++-выражений, но главное; чтобы результат его вычисления можно было интерпретировать как значение ИСТИНА или ЛОЖЬ.


Условное выражение

Иногда новичков в C++ сбивает с толку тот факт, что для управления if-инструкцией можно использовать любое действительное С++-выражение. Другими словами, тип выражения необязательно ограничивать операторами отношений и логическими операторами или операндами типа bool. Главное, чтобы результат вычисления условного выражения можно было интерпретировать как значение ИСТИНА или ЛОЖЬ.

Нуль автоматически преобразуется в false, а все ненулевые значения— в true. Это означает, что любое выражение, которое дает в результате нулевое или ненулевое значение, можно использовать для управления if-инструкцией. Например, следующая программа считывает с клавиатуры два целых числа и отображает частное от деления первого на второе. Чтобы не допустить деления на нуль, в программе используется if-инструкция.


// Деление первого числа на второе.

#include <iostream>

using namespace std;

int main()

{

 int a, b;

 cout << "Введите два числа: ";

 cin >> a >> b;

 if(b) cout << a/b << '\n';

 else cout << "На нуль делить нельзя.\n";

 return 0;

}

Обратите внимание на то, что значение переменной b (делимое) сравнивается с нулем с помощью инструкции if(b), а не инструкции if(b!=0). Дело в том, что, если значение b равно нулю, условное выражение, управляющее инструкцией if, оценивается как ЛОЖЬ, что приводит к выполнению else-ветви. В противном случае (если b содержит ненулевое значение) условие оценивается как ИСТИНА, и деление благополучно выполняется. Нет никакой необходимости использовать следующую if-инструкцию, которая к тому же не свидетельствует о хорошем стиле программирования на C++.