Вычисление по сокращенной схеме

Предположим, компилятору повстречалось следующее логическое выражение:

if ( (x == 5) && (у == 5) )

В таком случае компилятор сначала оценит первое выражение (x == 5) и, если оно возвратит false (т.е. x не равно числу 5), не станет вычислять второе выражение (у == 5), поскольку для истинности всего выражения с оператором И нужно, чтобы обе его составляющие были истинными.

Аналогично, если компилятору повстречается выражение с оператором ИЛИ

if ( (x == 5) || (у == 5) )

и первое выражение окажется истинным (x == 5), то компилятор также не станет вычислять второе выражение (у == 5), поскольку ему достаточно одного истинного результата, чтобы признать истинным все выражение.

Приоритеты операторов отношений

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

if ( x > 5 && у > 5 || 2 > 5)

В данном случае о намерениях программиста можно только догадываться. Возможно, он хотел, чтобы это выражение возвращало значение true, если x и у больше 5 или если z больше 5. С другой стороны, может быть, программист хотел, чтобы это выражение возвращало true только в том случае, если x больше 5 и либо у, либо z больше 5.

Если x равен 3, а у и z оба равны 10, то при использовании первой интерпретации намерений программиста это выражение возвратит значение true (z больше 5, поэтому игнорируем значения x и у), но при использовании второй интерпретации вернется значение false (oHp не может дать значение true, поскольку для этого требуется, чтобы значение x было больше 5, а после установления этого факта результат вычисления выражения справа от оператора && не важен, ведь для истинности всего выражения обе его части должны быть истинными).

Разобраться в приоритетах операторов в подобных выражениях довольно сложно, поэтому стоит воспользоваться круглыми скобками — ведь с их помощью можно не только изменить последовательность выполнения операторов, обусловленную их приоритетами, но и сделать ясными подобные запутанные выражения:

if ( (x > 5) && (у > 5 | | z > 5) )

При использовании предложенных выше значений это выражение возвращает значение false. Поскольку оказалось, что x (его значение равно 3) не больше 5, то выражение слева от оператора И возвращает false, а следовательно, и все выражение целиком тоже возвратит false. Помните, что оператор И возвращает true только в том случае, когда обе части выражения возвращают true. Например, ваш вкус можно считать хорошим только в том случае, если о надетой на вас вещи можно сказать, что она модная и что вам она идет.

Примечание: Часто дополнительные круглые скобки стоит использовать только для четкого определения того, что именно вы хотите сгруппировать. Помните, что цель программиста — написать программу, которая прекрасно работает, а также легко читается и понимается.

Подробнее об истине и лжи

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

if (x) // если x не равен нулю, то условие истинно

x = 0;

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

if (x ! = 0) // если x не нуль

x = 0;

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

Следующие два выражения также эквивалентны:

if (!x) // истинно, если x равен нулю

if (x == 0) // если x равен нулю

Однако, второе выражение проще для понимания и гораздо очевиднее, поскольку явно проверяется математическое значение переменной x.

Рекомендуется:Используйте круглые скобки, чтобы более четко указать порядок выполнения операторов или изменить их приоритеты.

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

Не рекомендуется:Не используйте выражение if(x) как эквивалент выражения if(x ! = 0). Последний вариант предпочтительнее, поскольку четче видна логика проверки условия.

Не используйте выражение if(!х) как эквивалент выражения if(x == 0). Последний вариант предпочтительнее, поскольку четче видна лотка проверки условия.

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

Условный оператор (?:) — это единственный оператор в языке C++, который работает сразу с тремя операндами.

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

(выражение1) ? (выражение2) : (выражениеЗ)

Эта строка читается таким образом: если выражение1 возвращает true, то выполняется выражение2, в противном случае выполняется выражениеЗ. Обычно возвращаемое значение присваивается некоторой переменной.

В листинге 4.10 показано использование условного оператора вместо оператора if.

Листинг 4.10. Пример использования условного оператора

1: // Листинг 4.10. Пример использования условного оператора

2: //

3: #include <iostream.h>

4: int main()

5: {

6: int x. у, z;

7: cout << "Enter two numbers.\n";

8: cout << "First: ";

9: cin >> x;

10: cout << "\nSecond: ";

11: cin >> у;

12: cout << "\n";

13:

14: if (x > у)

15: z = x;

16: else

17: z = у;

18:

19: cout << "z: " << z;

20: cout << "\n";

21:

22: z = (x > у) ? x : у;

23:

24: cout << "z: " << z;

25: cout << "\n";

26: return 0;

27: }

Результат:

Enter two numbers.

First: 5

Second: 8

z: 8

z: 8

Анализ: Сначала создается три целочисленные переменные: x, у и z. Значения первых двух вводятся пользователем. Затем в строке 14 выполняется инструкция if, которая позволяет узнать, какое из введенных значений больше, причем выявленное большее значение присваивается переменной z. Это значение выводится на экран в строке 19.

Ту же самую проверку выполняет в строке 22 условный оператор и присваивает переменной z большее значение. Он читается следующим образом: "Если x больше у, возвращаем значение x; в противном случае возвращаем значение у". Возвращаемое значение присваивается переменной z. Это значение выводится на экран в строке 24. Как видите, инструкция, содержащая условный оператор, является более коротким эквивалентом инструкции if...else.

Резюме

Данное занятие охватывает большой объем материала. Вы узнали, что представляют собой операторы и выражения в языке C++, какие разновидности операторов существуют в C++ и как работает оператор if.

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

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

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

Вопросы и ответы

Зачем нужны круглые скобки, если можно определить последовательность выполнения операторов по их приоритетам?

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

Если операторы отношений всегда возвращают значения true или false, то почему любое ненулевое значение считается истинным (true)?

Операторы отношений всегда возвращают значения true или false, но в выражениях условий можно использовать любые другие выражения, возвращающие числовые значения. Например:

if ( (x = а + b) == 35 )

Это вполне подходящее условие для выражения на языке C++. При его выполнении будет вычислено значение даже в том случае, если сумма переменных а и Ь не равна числу 35. Кроме того, обратите внимание, что переменной x в любом случае будет присвоено значение переменных а и b.

Какое воздействие оказывают на программу символы табуляции, пробелы и символы перехода на новую строку?

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

Отрицательные числа считаются истинными или ложными?

Все числа, не равные нулю (как положительные, так и отрицательные), воспринимаются как истинные.

Коллоквиум

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

Контрольные вопросы

1. Что такое выражение?

2. Является ли запись x = 5 + 7 выражением? Каково его значение?

3. Каково значение выражения 201 / 4?

4. Каково значение выражения 201 % 4?

5. Если переменные myAge, а и b имеют тип int, то каковы будут их значения после выполнения выражения:

myAge = 39;

а = myAge++;

b = ++myAge;

6. Каково значение выражения 8+2*3?

7. Какая разница между выражениями if(x = 3) и if(x == 3)?

8. Будут ли следующие выражения возвращать true или false?

а) 0

б) 1

в) -1

г) x = 0

д) x == 0 // предположим, что x имеет значение 0

Упражнения

1. Напишите один оператор if, который проверяет две целочисленные переменные и присваивает переменной с большим значением меньшее значение, используя только один дополнительный оператор else.

2. Проанализируйте следующую программу. Представьте, что вы ввели три значения. Какой результат вы ожидаете получить?

1: #include <iostream.h>

2: int main()

3: {

4: int a, b, с;

5: cout << "Please enter three numbers\n";

6: cout << "a: ";

7: cin >> a;

8: cout << "\nb: ";

9: cin >> b;

10: cout << "\nc: ";

11: cin >> c;

12:

13: if (c = (a-b))

14: { cout << "a: ";

15: cout << a:

16: cout << "minus b: ";

17: cout << b;

18: cout << "equals c: ";

19: cout << c << endl;}

20: else

21: cout << "a-b does not equal c: " << endl;

22: return 0;

23: }

3. Введите программу из упражнения 2; скомпилируйте, скомпонуйте и запустите ее на выполнение. Введите числа 20, 10 и 50. Вы получили результат, который и ожидали? Почему нет?

4. Проанализируйте эту программу и спрогнозируйте результат:

1: #include <iostream.h>

2: int main()

3: {

4: int а = 1, Ь = 1, с;

5: if (с = (a-b))

6: cout << "The value of с is: " << с;

7: return 0;

8: }

5. Введите, скомпилируйте, скомпонуйте и запустите на выполнение программу из упражнения 4. Каков был результат? Почему?

День 5-й. Функции

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

• Что такое функция и из чего она состоит

• Как объявлять и определять функции

• Как передавать параметры функциям

• Как возвращать значение функции

Что такое функция

Функция по своей сути — это подпрограмма, которая может манипулировать данными и возвращать некоторое значение. Каждая программа C++ имеет по крайней мере одну функцию main(), которая при запуске программы вызывается автоматически. Функция main() может вызывать другие функции, те, в свою очередь, могут вызывать следующие и т.д.

Каждая функция обладает собственным именем, и, когда оно встречается в программе, управление переходит к телу данной функции. Этот процесс называется вызовом функции (или обращением к функции). По возвращении из функции выполнение программы возобновляется со строки, следующей после вызова функции. Такая схема выполнения программы показана на рис. 5.1.

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

Различают два вида функций: определяемые пользователем (нестандартные) и встроенные. Встроенные функции являются составной частью пакета компилятора и предоставляются фирмой-изготовителем. Нестандартные функции создаются самим программистом.

Рис. 5.1. Когда программа вызывает функцию, управление переходит к телу функции, а затем выполнение программы возобновляется со стро­ки, следующей после вызова

Наши рекомендации