- •Информатика и программирование
- •Лабораторная работа № 04
- •Лабораторная работа № 04
- •1. Краткие теоретические сведения
- •1.1. Операции
- •1.2. Порядок (старшинство) выполнения операций
- •1.4. Разделители
- •1.5. Переменные
- •1.5.1. Объявление переменных
- •1.5.2. Смысловые имена переменных
- •1.5.3. Таблица идентификаторов
- •1.5.4. Слова, которые нельзя использовать для имен переменных
- •1.5.5. Присваивание значения переменной
- •1.5.6. Присваивание значения при объявлении
- •1.5.7. Использование значения переменной
- •1.5.8. Превышение диапазона значений переменной
- •1.5.9. Представление о точности
- •1.5.10. Следите за ошибками переполнения при арифметических операциях
- •1.6. Константы
- •1.7. Перечисления
- •1.8. Выражения
- •1.9. Правила записи выражений
- •1.10. Преобразования типов
- •1.11. Операции (операторы) инкремента и декремента
- •1.11.1. Увеличение значения переменной на 1
- •1.11.2. Представление о префиксной (до) и постфиксной (после) операциях увеличения
- •2. Задание
- •2.11. Задания
- •Варианты задания приведены в табл. 4.14. Вариант соответствует номеру в журнале группы.
- •Варианты задания приведены в табл. 4.15. Вариант соответствует номеру в журнале группы.
- •2.11.3. Задание 3. (Домашнее).
- •2.11.3.1. Содержание работы
- •2.11.3.2. Теоретические сведения
- •2.11.3.3. Варианты задания 3
- •Варианты задания приведены в табл. 4.15. Вариант соответствует номеру в журнале группы.
- •2.11.3.4. Пример программы
- •2.11.3.5. Программа
- •2.11.3.6. Результаты работы программы.
- •2.11.3.7. Типичные ошибки при выполнении работы
- •3. Выводы
- •4. Требование к отчету
- •5. Вопросы для самоконтроля
- •Литература
- •1. Краткие теоретические сведения 2
1.2. Порядок (старшинство) выполнения операций
Полный список операций (операторов), упорядоченный по приоритетам, приведен в табл. 4.4. Таблица разделена на сегменты двойными линиями. Операторы в каждом сегменте имеют одинаковый приоритет, причем более высокий, чем у операторов в последующих сегментах. Например, префиксный оператор инкремента и оператор обращения к значению расположены в одном сегменте. Следовательно, они имеют одинаковый приоритет, превосходящий приоритет арифметических операторов и операторов сравнения. Более подробно некоторые из этих операторов рассматриваются в последующих лабораторных работах.
В языке Си++ определено 19 категорий приоритетов операций. В табл. 4.4 категории приоритетов названы рангами. Операции ранга 1 имеют наивысший приоритет. Операции одного ранга имеют одинаковый приоритет, и если их в выражениях несколько, то они выполняются в соответствии с правилом ассоциативности либо слева направо (Л), либо справа налево (П). Если один и тот же знак операции приведен в таблице дважды, то первое появление (с меньшим но номеру, т.е. старшим по приоритету, рангом) соответствует унарной операции, а второе – бинарной. Отметим, что кроме стандартных режимов использования операций язык С++ допускает расширение их действий на объекты классов, вводимых пользователем или уже определенных в конкретной реализации языка. Примером такого расширения (перегрузки) является операция извлечения данных из потока << и операция передачи данных в выходной поток >>, применяемые к потокам ввода cin и вывода cout.
Таблица 4.4
Приоритеты операций
Ранг |
Порядок |
Операция (оператор) |
Действие |
Применение |
1 |
Л |
: : |
Глобальная область видимости |
: : имя |
1 |
Л |
: : |
Область видимости класса |
класс::имя |
1 |
Л |
: : |
Область видимости пространства имен |
пространствоимен::имя |
2 |
Л |
. |
Обращение к члену класса |
объект.член |
2 |
Л |
- > |
Обращение к члену класса |
указатель->член |
2 |
Л |
[] |
Индексирование |
переменная [выражение] |
2 |
Л |
() |
Вызов функции |
имя(список_выражений) |
2 |
Л |
() |
Создание типа |
тип(список_выражений) |
3 |
П |
++ |
Постфиксный инкремент |
1 -значение++ |
3 |
П |
-- |
Постфиксный декремент |
1-значение-- |
3 |
П |
typeid |
Идентификатор типа |
typeid(тип) |
3 |
П |
typeid |
Идентификатор типа времени выполнения |
typeid(выражение) |
3 |
П |
Явное приведение |
Преобразование типов |
имя_приведения<тип>(выражение) |
4 |
П |
sizeof |
Размер объекта |
sizeof выражение |
4 |
П |
sizeof |
Размер типа |
sizeof(тип) |
4 |
П |
++ |
Префиксный инкремент |
++1 -значение |
4 |
П |
-- |
Префиксный декремент |
- -1 -значение |
4 |
П |
~ |
Побитовый NOT |
~выражение |
4 |
П |
! |
Логический NOT |
!выражение |
4 |
П |
- |
Унарный минус |
-выражение |
4 |
П |
+ |
Унарный плюс |
+выражение |
4 |
П |
* |
Обращение к значению |
*выражение |
4 |
П |
& |
Обращение к адресу |
&выражение |
4 |
П |
() |
Преобразование типов |
(тип) выражение |
4 |
П |
new |
Создание объекта |
new тип |
4 |
П |
delete |
Освобождение объекта |
delete выражение |
4 |
П |
delete [] |
Освобождение массива |
delete [] выражение |
5 |
Л |
->* |
Указатель на член класса |
указатель ->* указатель_на_ член |
5 |
Л |
. * |
Указатель на член класса |
объект .* указатель_на_ член |
6 |
Л |
* |
Умножение |
выражение * выражение |
6 |
Л |
/ |
Деление |
выражение / выражение |
6 |
Л |
% |
Деление по модулю (остаток) |
выражение % выражение |
7 |
Л |
+ |
Сумма |
выражение + выражение |
7 |
Л |
- |
Разница |
выражение - выражение |
8 |
Л |
<< |
Побитовый сдвиг влево |
выражение << выражение |
8 |
Л |
>> |
Побитовый сдвиг вправо |
выражение >> выражение |
9 |
Л |
< |
Меньше |
выражение < выражение |
9 |
Л |
< = |
Меньше или равно |
выражение <= выражение |
9 |
Л |
> |
Больше |
выражение > выражение |
9 |
Л |
> = |
Больше или равно |
выражение >= выражение |
10 |
Л |
== |
Равенство |
выражение == выражение |
10 |
Л |
!= |
Неравенство |
выражение != выражение |
11 |
Л |
& |
Побитовый AND |
выражение & выражение |
12 |
Л |
^ |
Побитовый XOR |
выражение ^ выражение |
13 |
Л |
| |
Побитовый OR |
выражение | выражение |
14 |
Л |
&& |
Логический AND (конъюнкция «И») |
выражение && выражение |
15 |
Л |
|| |
Логический OR (дизъюнкция «ИЛИ») |
выражение || выражение |
16 |
П |
?: |
Условная операция |
выражение ? выражение : выражение |
17 |
П |
= |
Присвоение |
1-значение = выражение |
17 |
П |
*=, /=, %=, |
Составные операторы присвоения |
1-значение += выражение и т.д. |
17 |
П |
+=, -= |
||
17 |
П |
<<=, >>= |
||
17 |
П |
&=, |=, ^= |
||
18 |
П |
throw |
Передача исключения |
throw выражение |
19 |
Л |
, |
Запятая |
выражение , выражение |
Порядок определяет последовательность группировки операций (операторов) при одинаковом уровне приоритета. Вопросы порядка весьма существенны и в некоторых других случаях. Например, правосторонний порядок (П) оператора присвоения позволяет создавать составные операторы присвоения.
ival - jval = kval = lval // правосторонний порядок
(ival = (jval = (kval = lval))) // эквивалентная версия со скобками
Это выражение сначала присваивает значение переменной lval переменной kval, полученный результат присваивается переменной jval и, наконец, переменной ival.
Арифметические операторы, напротив, имеют левосторонний порядок (Л).
ival * jval / kval * lval // левосторонний порядок
(((ival * jval) / kval) * lval) // эквивалентная версия со скобками
В этом выражении, например, происходит умножение значений переменных ival и jval, затем деление результата на значение переменной kval и, наконец, умножение результата деления на lval.
Замечание: поскольку в лабораторных работах с 1-й по 5-ю используются исключительно арифметические операции, то при написании программ на С++ удобнее пользоваться на первых порах более простой и компактной табл. 3.4 (лабораторная работа № 3), в которой приведен приоритет (ранг) только арифметических операций. Начиная с лабораторной работы 6 при написании программ на языке С++ будут использоваться по мимо арифметических операций и другие операции языка С++, в этом случае необходимо обращаться к табл. 4.4.
В заключение рассмотрения работы с арифметическими операциями отметим, что приоритет операций умножения и деления выше приоритета операций сложения и вычитания. Это означает, что сначала выполняются операции умножения и деления и только затем операции сложения и вычитания. Пример 4.1 демонстрирует приоритет арифметических операций:
Пример 4.1.
double n=2, SCALE = 1.2;
double arg = 25.0 + 60.0*n/SCALE;
В приведенном примере сначала будет выполнена операция умножения, затем деления и, наконец, сложения. То есть порядок вычисления соответствует математическим правилам. Для того чтобы изменить порядок вычисления (поменять приоритеты) используются круглые скобки как показано ниже
Результат выражения зависит от группировки составляющих его операторов. Например, при вычислении выражения в примере 4.2 слева направо получится 20.
Пример 4.2.
6+3*4/2+2;
Для выражения примера 4.2 вполне возможны и другие результаты: 9, 14 и 36. Напомним, что в языке С++ результат вычисления выражения составит 14.
Умножение и деление имеют более высокий приоритет, чем сложение. Их операнды связаны с операторами жестче, чем операнды операторов сложения. Умножение и деление имеют одинаковый приоритет. Операторы имеют также порядок выполнения, который определяет последовательность группировки операндов у операторов с одинаковым уровнем приоритета. Арифметические операторы имеют левосторонний порядок, т.е. они группируются слева направо. Теперь вполне очевидно, что приведенное выше выражение можно переписать следующим образом.
int temp = 3*4 //12
int temp2 = temp /2 //6
int temp3 = temp2 + 6 //12
int result = temp3 + 2 // 14
1.3. Управление порядком, в котором C++ выполняет операции
Круглые скобки позволяют переопределить приоритет операций!
Как вы уже знаете, C++ назначает операциям различный приоритет, который и управляет порядком выполнения операций. К сожалению, иногда порядок, в котором C++ выполняет арифметические операции, не соответствует порядку, в котором вам необходимо их выполнить. Например, предположим, что вашей программе необходимо сложить две стоимости и затем умножить результат на налоговую ставку:
Пример 4.3.
cost = price_a + price_b * 1.06;
К сожалению, в этом случае C++ сначала выполнит умножение (price_b * 1.06), а затем прибавит значение price_a.
Для переопределения приоритета можно использовать круглые скобки. Выражения в круглых скобках обрабатываются как отдельные модули. Когда C++ оценивает выражение, он сначала всегда выполняет операции, сгруппированные в круглых скобках, а во всех остальных случаях применяется обычные правила приоритета.
Пример 4.4.
Рассмотрим следующее выражение:
result =(2+3)* (3+4);
C++ вычисляет данное выражение в следующем порядке:
result = (2 + 3) * (3 + 4);
= (5) * (3 + 4);
= 5 * (7);
=5*7;
= 35;
Пример 4.5.
Используя круглые скобки в выражении примера 4.2, можно принудительно получить любой из четырех возможных вариантов.
// круглые скобки позволяют изменить стандартный приоритет
// и порядок выполнения операторов
cout << ((6 + ((3 * 4) / 2)) + 2) << endl; //результат 14
// круглые скобки позволяют создать альтернативные группировки
cout << (6+3) * (4/2+2) << endl; //результат 36
cout << ((6+3) * 4) /2+2 << endl; //результат 20
cout << 6+3*4/ (2+2) << endl; // результат 9
В качестве примера рассмотрим следующее выражение:
*iter++;
Приоритет оператора ++ выше приоритета оператора *. Это значит, что сначала выполняется часть iter++,a ee результат становится операндом оператора *. Таким образом, обращение к значению итератора iter происходит после его инкремента. Но если бы необходимо было увеличить значение, на которое указывает итератор iter, пришлось бы применить круглые скобки, чтобы явно указать свои намерения.
(*iter)++; // увеличить значение, на которое указывает
// итератор iter
Круглые скобки указывают, что операнд * применяется к итератору iter. Теперь как операнд оператора ++ в выражении используется часть *iter.
Группируя выражения внутри круглых скобок, вы можете управлять порядком, в котором C++ выполняет арифметические операции.
Пример 4.6.
Для задания правильного алгоритма вычислений в примере 4.6, необходимо сложить две стоимости внутри круглых скобок, как показано ниже:
cost = (price_a + price_b) * 1.06;
Рекомендация: в сомнительных случаях сами доопределяйте приоритет операций с помощью круглых скобок.
Пример 4.7:
2 + 2 * 2 = 6; (2 + 2) * 2 = 8.