Порядок выполнения работы. 1. Операции отношения и логические операции.




 

1. Операции отношения и логические операции.

 

Таблица 1. Сводная таблица с приоритетами

Операция Назначение Использование
! логическое НЕ ! a
< <= > >= меньше меньше или равно больше больше или равно a < a a <= a a > a a >= a
== != равно не равно a == a a!= a
&& логическое И a && a
|| логическое ИЛИ a || a

 

Приоритет операций отношения и логических операций ниже, чем у арифметических операций (i < j+1 трактуется как i < (j+1)).

Одним из основополагающих идейных отличий С и С++ от Паскаля, является то, что все операции отношения и логические операции возвращают целое значение -

1 - если условие истинно,

0 - если условие ложно.

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

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

if (i=0) {... }

Компилятор здесь не выдаст ошибки (только предупреждение), но программа, скорее всего, будет работать неправильно. Операция "=" это операция присваивания в С++. Необходимо писать

if (i= =0) {... }

Почему компилятор здесь не выдаст ошибки – рассмотрено (смотри тему «операции присваивания»). Логические операции && и || аналогичны по принципу действия паскалевским and и or. Результат && - истина (1) если оба ее операнда истинны (не равны 0). Результат || истина если хотя бы один из ее операндов истина. Гарантируется, что операнды вычисляются слева направо. Вычисление прекращается, как только определится, является ли выражение истинным или ложным. Это значит, что для выражения

выр1 && выр2

выр2 не будет вычисляться, если значение выр1 ложно (равно 0), а для выражения

выр1 || выр2

выр2 не будет вычисляться, если значение выр1 истинно (не равно 0).

Следует отметить, что, в отличие от Паскаля, приоритет && и || ниже, чем у операций равенства и отношения и поэтому если нужно, к примеру, проверить, попала ли переменная в диапазон от 0 до 100, то такая запись корректна

if (i1 >= 0 && i1 <= 100)

и не требует дополнительных скобок.

Логическое отрицание! преобразует свой операнд в истину (1) если он равен 0 и в ложь (0) если он не равен нулю.

Выражение (!found) возвращает истину, пока found равен нулю.

Можно писать

if(!found)

а можно

if(found = = 0)

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

Так же точно вместо

if (found!= 0)

можно просто написать

if (found).

 

2. Условная операция

 

В программах очень часто встречается следующая конструкция:

if (a > b)

z = a;

else

z = b;

Здесь в z пересылается максимальное из двух значений a и b. В С++ все это можно записать одной строкой. Для этого используется условная операция.

Это единственная тернарная (с тремя операндами) операция в С++. Она имеет следующую синтаксическую форму:

выр1? выр2: выр3

В этом выражении первым вычисляется значение выр1. Если оно истинно (не нуль) то вычисляется значение выражения выр2 и значение этого выражения становится значением, которое возвращает сама условная операция. В противном случае (если значение выр1 - нуль) вычисляется значение выр3 и становится значением, возвращаемым условной операцией. Следует отметить, что из выражений выр2 и выр3 вычисляется только одно.

В нашем случае можно записать:

z = (a > b)? a: b;

Условная операция может встречаться в программе в любом месте, где допустима операция. Заключать в скобки первое выражение в условной операции не обязательно, так как приоритет?: очень низкий (более низкий приоритет имеют только присваивание и операция запятая), но лучше так делать, поскольку в этом случае условие легче воспринимается. Условная операция часто позволяет сократить программу.

 

3. Составные операторы и блоки.

 

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

if (i < 0)

{

i = 200;

j = i + 600;

}

Cоставной оператор или блок - это последовательность операторов, заключенная в фигурные скобки. Такие скобки аналогичны операторным скобкам begin...end в Паскале. Составной оператор может встречаться в программе везде, где может быть отдельный оператор. После правой закрывающей фигурной скобки в конце блока точка с запятой не ставится. Обратите внимание на отличие от Паскаля: в Паскале перед end после последнего оператора (здесь j:= i+600) может и не стоять точка с запятой, а в С++ она обязательна, т.к. заканчивает оператор. Внутри блока могут быть описания.

 

4. Операции присваивания.

 

Еще одним коренным и чрезвычайно важным отличием С++ от Паскаля, которое обуславливает компактность программ на С++ является то, что здесь присваивание является не оператором, а операцией, которая может находиться на любом месте в выражении. Об этом всегда нужно помнить. В С++ различаются простое и составное присваивание. Простое присваивание обозначается как =. Левый операнд операции присваивания должен быть lvalue-выражением, т.е. обозначать объект в памяти, которому присвоится значение правого операнда.

Например:

int i;

i = 0;

 

Результат операции присваивания есть значение того выражения, которое присваивается левому операнду. Это rvalue. Тип результата - тип левого операнда. Т.е. присваивание действует "насквозь" справа налево.

Что следует из того, что присваивание является операцией?

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

int i,j,k;

i = j = k = 0;

i,j и k присваивается 0. Порядок выполнения присваиваний - справа налево.

2) можно короче записывать выражения. Например в фрагменте программы:

char ch; // получаемый символ

char next_char(); // выдает следующий символ

if ((ch = next_char())!= '\n') {... }

присваивание значения символьной переменной ch совмещается с проверкой.

Вообще здесь нужно знать меру, чтобы не запутать программу.

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

if (i=0) {... }

компилятор не выдал ошибки. Он воспринял выражение в скобках как операцию присваивания и сделал проверку в соответствии с результатом этой операции. При выполнении программы сначала i присвоится ноль, а затем осуществится проверка if (0) и операторы в фигурных скобках не выполнятся никогда.

Составное присваивание - это новая операция. Она также позволяет записывать выражения короче. Общий вид составного присваивания следующий:

a op= b

где op – (operation) одна из десяти операций:

+ - * / % << >> & ^ |

Каждая составная операция эквивалентна следующему присваиванию:

a = (a) op (b);

за тем исключением, что здесь a вычисляется два раза, а при использовании составного присваивания - один раз.

Например:

i *= 4 эквивалентно i = i * 4

Обратите внимание на скобки вокруг b: запись

i *= y+1

эквивалентна записи

i = i * (y+1) а не i = i * y + 1

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

 

5. Операции инкремента и декремента (увеличения и уменьшения).

 

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

Например:

int c;

++c; // префиксный инкремент

c++; // постфиксный инкремент

В обоих случаях значение с увеличится на единицу. Но выражение ++с увеличивает с до того, как его значение будет использовано, а с++ - после того. Когда, как в нашем примере, с++ стоит в операторе отдельно, то разницы нет. Но если инкремент или декремент поставить в выражение, то разница появится:

Если с равно 5 то запись

x = c++;

эквивалентна операторам

x = c; с = c + 1;

и x будет равен 5, а запись

x = ++c;

эквивалентна операторам

с = c + 1; x = c;

и x будет равен 6. (с будет равно 6 в обоих случаях).

Аналогично обстоят дела с декрементом --. Он уменьшает свой операнд на единицу. Инкремент и декремент - это присваивания и их операнд должен быть lvalue.

Здесь будет ошибка:

x = (a+b)--;

(значение выражения a+b - rvalue и не связано с объектом в памяти) и здесь тоже:

++a++;

(значение, которое выдает присваивание (и в том числе инкремент) тоже не связано с объектом в памяти).

В отличие от операций простого и составного присваивания, инкремент и декремент имеют высокий приоритет - такой же, как унарный минус или логическое отрицание!.

 

 

6. Оператор if-else

 

Оператор if-else в С++ имеет следующий формат:

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

оператор1;

else

оператор2;

причем else - часть которая может быть, а может и отсутствовать.

Сначала вычисляется выражение и если оно истинно (отлично от 0) то выполняется оператор1 а иначе - оператор2.

Например:

if (a < b)

x = a;

else

x = b;

или с блоками

if (val) // val – переменная любого типа, которую можно сравнить с нулем

{ // то же, что и if(val!= 0)

print();

i--;

}

else

i++;

 

Обратите внимание на три особенности (отличия от Паскаля):

1) скобки в условии обязательны;

2) then не нужно;

3) если первый оператор - одиночный оператор, то он заканчивается точкой с запятой, которая будет стоять перед else (в Паскале перед else никогда не должна стоять точка с запятой). Об этой точке с запятой очень часто забывают. Также обратите внимание на краткую запись условия во втором примере. Такая запись встречается очень часто.

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

Например:

if (n > 0)

if (a > b)

x = a;

else

x = b;

Здесь else относится к внутреннему if. Если требуется, чтобы было иначе, нужно использовать фигурные скобки:

if (n > 0)

{

if (a > b)

x = a;

}

else

x = b;

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

 

7. Оператор switch (переключатель)

 

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

 

switch (выражение) {

case конст-выр: операторы

case конст-выр: операторы

default: операторы

}

причем часть default может отсутствовать, а порядок меток не важен (даже default может быть не в конце).

 

Нпример:

 

int i,c0,c1,c2,c3,c4;

switch (i)

{

case 0: ++c0;

break;

case 1:

case 2: ++c1;

++c2;

break;

case 3: ++c3;

case 4: ++c4;

break;

default: ++c;

break;

}

cout << i;

Значение, которое стоит за служебным словом case, называется меткой варианта. Она должна быть константой или константным выражением целочисленного типа. Две метки варианта не могут иметь одно и то же значение.

Сначала вычисляется выражение (в нашем случае это просто i). Потом его значение сравнивается с каждой меткой варианта по очереди. Как только обнаружится совпадение, то выполняется первый оператор за данной меткой варианта. Так, если у нас i будет равно 4, то первым выполнится оператор ++с4. Если соответствие между значением выражения и множеством меток вариантов не найдено(например, если у нас i будет равно 5), то будет выполнен оператор, следующий за меткой default (у нас это ++с), а если часть default отсутствует, то выполняется оператор, следующий за оператором switch (у нас это cout << i;).

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

Рассмотрим случай, когда у нас i равно 3. Сначала выполнится оператор ++с3; После этого выполнение переключателя не прекратится, а продолжится далее через границу варианта и следующим оператором будет ++с4. Это редко имеет в виду программист. Для того, чтобы этого не было, необходимо осуществлять выход из переключателя. Обычно для этого используется оператор break. Когда встречается оператор break, выполнение оператора switch прекращается и управление передается оператору, следующему за switch (у нас cout << i). Обычно последним оператором для каждой метки варианта в switch является именно оператор break (может быть еще оператор возврата return).

В нашем случае так обстоит дело для меток 0,2,4 и default. Даже после ветви default рекомендуется ставить break, так как после нее можно потом добавлять еще ветви case и в этом случае отсутствие break может стать существенным.

Если в метке варианта оператор break опущен намеренно, то для безопасности всегда должен присутствовать комментарий, подтверждающий, что это так и задумано. Основной причиной, по которой программист может опускать break, является тот случай, когда одному действию соответствуют значения нескольких меток варианта.

В нашем случае одни и те же действия нужно делать при i==1 и i==2. Обратите внимание, что такая запись будет ошибкой:

case 1,2: ++c1;

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

switch (i) case 0: {...}

это странная форма записи для

if (i == 0) {...}

 

8. Разбор типового варианта

 

 
 

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

Разобьем нашу область по четвертям: 1, 2, 3 и 4. Из рисунка видно, что проверке подлежат 1 и 4 области. Ограничим наши четверти 1 (единицами) по осям абсцисс и ординат. Прямоугольная область затруднений не вызовет, достаточно лишь проверить на вхождение в 4 четверть, в области же ограниченной сектором круга, прибегнем к формуле окружности x2+y2=0.

 

#include <iostream.h>

#include <conio.h>

#include <math.h>

 

main (){

float x,y;

clrscr();

cout<<"x= ";

cin>>x;

cout<<"y= ";

cin>>y;

if (x>=-1 && x<=0 && y>=-1 && y <=0) //проверка на вхождение в четверть

cout<<"Tochka voshla v oblast.."; else

if (x>=0 && x<=1 && y>=0 && y<=1) //проверка на вхождение в четверть

if (pow(x,2)+pow(y,2)<=1) //проверка на вхождение в область

cout<<"Tochka voshla v oblast..";

else cout<<"Tochka ne voshla v oblast.."; //остальные случаи

else cout<<"Tochka ne voshla v oblast.."; //остальные случаи

getch();

return 0;

}

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2018-12-19 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: