Операции отношения и логические операции
Эти операции возвращают true (любое ненулевое значение, например, единицу) или false (нуль). Логические операции выполняются, как и в других языках программирования или системах, согласно следующей таблице, где A и B — некоторые операнды (части) выражения со значением true или false. Например, в выражении x>0 && y>0, в котором x и y принимают вещественные значения, первым операндом A является x>0, a вторым операндом В — вторая часть y>0.
A | B | A && B | A || B | !B |
0 (x<=0) | 0 (y<=0) | |||
0 (x<=0) | 1 (y>0) | |||
1 (x>0) | 0 (y<=0) | |||
1 (x>0) | 1 (y>0) |
В результате операции && получается true (1) тогда и только тогда, когда оба операнда истинны — в нашем примере оба числа положительные. В остальных случаях получается false (0).
В результате операции || получается true, если один из операндов либо оба истинны, то есть в примере одно из чисел или оба положительные. Результатом является false только в том случае, если оба операнда ложны.
Операция отрицания (!) одноместная и меняет значение одного операнда на противоположное, то есть true на false и false на true.
Для закрепления этих операций и для развития логического мышления полезно научиться выполнять упражнения двух типов:
1) дана некоторая область плоскости. Записать логическое выражение, принимающее значение “истина” тогда и только тогда, когда точка с вещественными координатами (x, y), принадлежит указанной области;
2) наоборот, по заданному выражению нарисовать область плоскости, в которой и только которой указанное выражение истинно.
Такие задачи, в зависимости от того, какие логические операции используются при определении областей, можно классифицировать следующим образом:
· в выражении не используются логические операции. Например, точки первой и третьей четвертей, включая и оси координат, определяются с помощью выражения x*y>=0;
· используется только операция &&, если область состоит из одной части. Например, точки внутри треугольника с вершинами
(1,1), (0,0) и (-1,1) определяются так: у>=abs(x) && y<=1;
· используется только операция ||, если область состоит из нескольких относительно несложных частей, для определения каждой из которых достаточно одного неравенства. Область, состоящая из левой половины круга радиуса 2 с центром в начале координат, включая и полуокружность, и точек справа от оси OY, не включая её, определяется так: x>0 || x*x+y*y<=4. Заметим, что круглые скобки (x>0) ||(x*x+y*y<=4) не обязательны, так как в отличие от Pascal операции сравнения имеют более высокий приоритет, чем логические;
· используются как операция &&, так и операция ||, если область “склеена” из нескольких частей. Каждая из них определяется с помощью нескольких неравенств, соединённых операцией &&. Например, ту же левую половину круга радиуса 2, включая и его границы, и правую относительно оси OY часть полукольца, образованного окружностями радиусов 2 и 3 с центром в начале координат, можно определить так:
x<=0 && x*x+y*y<=4 || x>=0 && x*x+y*y>=4 && x*x+y*y<=9;
· используется операция отрицание (!), если легче определить область, которой точки не принадлежат, или некоторую часть уже определённой области надо “выбросить” из неё. Например, так легче определить круг радиуса 5 с центром в начале координат, из которого выброшен треугольник с вершинами (1,1), (0,0) и (–1,1): x*x+y*y<=25 && ! ( у>=abs(x) && y<=1);.
Операция присваивания
1) В простейшем случае она похожа на присваивание языка Pascal:
переменная = выражение;. Вместо двух символов (:=) используется один “=”. Слева всегда записывается только переменная. Справа как частный случай выражения допускается одна константа (x=1) или только обращение к функции (y=abs(x)), или одна переменная (y=x).
2) Можно использовать так называемое многочисленное присваивание: П1=П2=…=Пn=Выражение;. Значение одного и того же выражения присваивается нескольким переменным П1,П2, …, Пn. Например, оператор R=r=v=x+y; трём переменным R, r и v присваивает одно и то же значение суммы.
3) Сокращённое присваивание в общем виде выглядит так.
Переменная = переменная операция выражение;, где слева и справа от знака = одна и та же переменная, можно записать: переменная операция = выражение;. Например, S=S+N; можно сократить: S += N;. Идентификатор переменной записывается один раз, между операцией и символом “=” не должно быть пробела. Преимущество такой записи в том, что не надо дважды повторять имя одной и той же переменной.
4) Для увеличения или уменьшения на единицу можно использовать операции инкремент (++) и декремент( - -). Эти операции могут стоять как перед операндом (префиксная), так и после него (постфиксная). Нельзя писать пробел между этими одинаковыми символами. Их можно использовать как самостоятельно, так и в выражении.
При самостоятельном использовании префиксная и постфиксная операции выполняются одинаково. Например, ++k; и k++; равносильны более простой и понятной записи k=k+1; или k+=1; Аналогично, - - number; и number - -; равносильны number=number-1; или number-=1.
В выражениях префиксная и постфиксная операции различаются. В случае префиксной операции сначала изменяется значение переменной, перед которой стоит операция, а затем используется новое изменённое значение. Например, int X=2, Y=5, Result; Result= X*(++Y); или с учётом приоритета Result=X*++Y; выполняется так: сначала увеличивается значение Y изапоминается в этой же ячейке, то есть Y=Y+1, и при умножении используется новое значение Y, равное 6. В результате получим 2*6=12, то есть Result примет значение 12.
В случае постфиксной операции сначала используется старое значение переменной, после которой стоит операция, а затем оно изменяется. Например, пусть int X=2, Y=5, Result; Result= X*Y++; Сначала вычисляется произведение со старым значением Y, то есть Result примет значение 2*5=10, а затем значение Y увеличится и станет равным 6.
Пусть int X=2, Y=5, Result; Интерес представляет следующая запись: Result=X+++Y; Какая здесь операция — постфиксная для X или префиксная для Y? Это равносильно Result=(X++)+Y; то есть сначала выполняется сложение 2+5, а затем увеличивается X. В результате получим значение Result, равное 7, X примет значение 3, а Y не изменится. Во избежание риска в таком случае рекомендуется использовать скобки, то есть вторая запись надёжнее.
5) Ещё есть одна важная особенность присваивания, не обязательная для начинающих. Присваивание может быть частью другого оператора. Например, в компактной записи cout<<(R=a*10)<<endl; не надо дважды записывать один и тот же идентификатор R. Это равносильно R=a*10; cout<<R<<endl; Запись R=(W=a)*b; равносильна двум выражениям (операторам): W=a; R=W*b;
Замечание. Наличие отмеченных выше особенностей присваивания, тернарной операции (4.2) и других профессиональных возможностей является одной из причин того, что язык С, в том числе и С++, традиционно считается сложнее языка Pascal. Но на начальном этапе изучения такого рода особенности не обязательно использовать. Можно программировать проще, в стиле языка Pascal. Например, вместо Result= X*Y++; можно написать проще: Result= X*Y; Y=Y+1;.
Программирование ветвлений
Оператор if
Полная форма оператора if следующая:
if ( выражение) { оператор 1; … оператор N; }
else { оператор 1; … оператор K; }
Следующий оператор;
Здесь if и else — ключевые слова, которые записываются только маленькими буквами. Выражение, которое записывается в круглых скобках, чаще всего в простейшем случае (но не обязательно) представляет собой логическое выражение со значением true или false, содержащее арифметические, логические операции, операции сравнения и некоторые другие. Перечень и приоритет операций приведён 3.2.
Выполняется оператор следующим образом. Если выражение истинно, то выполняется первая последовательность из N операторов, вторая пропускается и выполняется следующий оператор, записанный после if. Если выражение ложно, то первая последовательность пропускается, выполняется вторая группа операторов, а затем следующий оператор.
Фигурные скобки, влияющие на выполнение алгоритма, обязательны, если в последовательности более одного оператора, и необязательны, если оператор один. Так, если в примере 1 (§ 1) опустим фигурные скобки после else, то слово “sum: ” будет выводиться в любом случае, независимо от значения выражения. Если их не запишем в первой группе операторов, то это приведёт к синтаксической ошибке на этапе компиляции, так как else будет рассматриваться как самостоятельный оператор, не связанный с if. А такого оператора else нет, это составная часть оператора if. Выполняться программа не будет. В сложных алгоритмах не всегда очевидно, сколько операторов в первой и (или) второй ветви, один или более одного. В таком случае лучше записать фигурные скобки {}. Ошибки не будет, если они не нужны.
Сокращённая (неполная) форма if имеет следующий вид:
if ( выражение) { оператор 1; … оператор N; }
Следующий оператор;
В отличие от первой формы, отсутствует else и вторая последовательность операторов. Если выражение истинно, то последовательность из N операторов выполняется. В противном случае она пропускается и выполняется следующий после if оператор.
Аналогично решается вопрос с фигурными скобками и в этом случае.
Замечание (можно не читать, если не знакомы с языком Pascal). Сравним if с аналогичным оператором языка Pascal
· Название оператора всегда записывается маленькими буквами.
· Анализируемое после if выражение записывается обязательно в круглых скобках.
· Отсутствует ключевое слово then.
· Фигурные скобки играют ту же роль, что ключевые слова begin и end.
· Символ “;” (точка с запятой) перед else обязателен.
Определённые затруднения вызывает вложенность операторов if, когда среди операторов первой и (или) второй последовательности if есть другой, внутренний оператор if полной или сокращённой формы. Например:
if (a>0) if (b>0) cout<<”Yes”;
else cout<<”No”;
Для правильной интерпретации такой конструкции необходимо использовать следующее правило: else соответствует ближайшему предшествующему оператору if, ещё не имеющему else. В примере else связан с if (b>0). Поэтому вывод Yes или No в зависимости от b будет выполняться только в случае, если a>0. Если значение a неположительное, ничего выводиться не будет. Поэтому для наглядности желательно располагать ключевые слова так, чтобы это соответствовало логике программы, несмотря на то, что расположение операторов не влияет на их выполнение.
Чтобы else соответствовал внешнему оператору ветвления if (a>0), необходимо добавить фигурные скобки следующим образом:
if (a>0) { if (b>0) cout<<”Yes”; }
else cout<<”No”;
Этот пример показывает, что иногда на выполнение программы влияют фигурные скобки и в случае, если внутри их один оператор. Здесь имеет место полная форма внешнего оператора if и сокращённая форма внутреннего, а не наоборот, как было в первом случае.
Уровень вложенности операторов if может быть больше, чем показано выше. Часто на практике используется следующая конструкция if…else…if :
if ( 1-е выражение )
1-я последовательность операторов;
else if (2- е выражение )
2-я последовательность операторов; …
else if (n-е выражение )
n-я последовательность операторов;
else
(n+1)-я последовательность операторов;
Выражения вычисляются сверху вниз. Если будет найдено, что k-е выражение истинно, то выполняется k-я последовательность операторов, а остальные последовательности пропускаются. Если не найдено ни одного истинного выражения, то выполняется (n+1)-я последовательность операторов при условии, что последний else присутствует, или не выполняется никаких действий, если (n+1)-я последовательность вместе с последним оператором else отсутствует. Пример такой конструкции, которую иногда называют “лесенка if-else-if”, приведён дальше при описании оператора switch.
Могут быть и другие конструкции вложенных операторов if, например:
if (выражение 1)
if (выражение 2)
1-я последовательность операторов;
еlse 2-я последовательность операторов;
else 3-я последовательность операторов;
Здесь и внутренний, и внешний операторы if имеют полную форму. Во внешнем операторе в случае истинности выполняется единственный другой оператор if. Среди любой из трёх последовательностей операторов может быть также оператор if.
Ещё одна особенность оператора if и некоторых других операторов, использующих логические значения, следующая. Истине соответствует любое ненулевое значение, а значению false соответствует нуль. Поэтому в операторе if выражение в скобках не обязательно должно быть логическим, то есть в нём могут быть только арифметические операции или выражение может представлять собой просто переменную.
Пример 2. Допустима следующая запись: int a=5;
/* При объявлении инициализируем переменную, т.е. присваиваем ей начальное значение */
if (a) cout<<” ненулевое значение”; else cout<< “нулевое значение” ;
/* Этот оператор if в стиле языка Pascal можно записать проще, используя операцию сравнения “не равно”: */
if (a!=0) cout<<” ненулевое значение”; else cout<< “нулевое значение” ;
// или
if (a == 0) /* Операция сравнения на равенство — два символа “ равно” без пробела между ними */
cout<<” нулевое значение”; else cout<< “ненулевое значение” ;
Наконец, в отличие от языка Pascal, присваивание можно записать внутри другого оператора, например, внутри if в выражении в скобках. Поэтому в языке С присваивание, являясь частью выражения, называют операцией.
Пример 3. Пусть int x=5, y=2; Сравним два выражения в операторе if:
/*1*/ if (x = = y) cout<<”Yes”; else cout<<”No”;
/*2*/ if (x=y) cout<<”Yes”; else cout<<”No”;
В первом варианте значения двух переменных проверяются на равенство, и в результате будет выведено слово No. Второй вариант в стиле языка Pascal равносилен следующей последовательности:
x=y; // х примет значение y, то есть 2
if (x!=0) cout<<”Yes”; else cout<<”No”;
// или в стиле языка С
if (x) cout<<”Yes”; else cout<<”No”;
Поэтому в результате будет выведено слово Yes. Во втором варианте результат зависит только от начального значения y и не зависит от x.
Тернарная операция
Этой операции также нет в других языках, и без неё можно обойтись. С её помощью в более компактном виде в некоторых случаях можно записать полную форму оператора if. Например, вместо if (k>9) R=100; else R=x*y; можно записать R=k>9 ? 100 : x*y;.
Это единственная трёхместная операция, так как для неё требуется три операнда. Общий вид операции: выражение1 ? выражение2 : выражение3.
Операция выполняется следующим образом: вычисляется выражение1; если оно истинно (любое ненулевое значение), то вычисляется выражение2, и всё выражение получает это значение; если выражение 1 ложно (нулевое значение), то вычисляется выражение3, и всё выражение получает это значение.
Эта операция не обязательно должна быть связана с присваиванием. Например, известно, что в cout можно записать выражение, а в нём эту операцию без дополнительного присваивания значения выражения. Например:
cout<<(x>0 && y>x ? x*y : x+y); в зависимости от значений x и y выведут их произведение или сумму. Это равносильно
if (x>0 && y>x) cout<<(x*y);
else cout<<(x+y).
Не для любого оператора if можно записать тернарную операцию. Её можно использовать для замены только полной формы условного оператора. В одной и другой ветвях операции (после символов “?” и “:” ) можно использовать по одному выражению, то есть это соответствует такому оператору if, в котором в каждой ветви по одному оператору.
Эта операция, как и любая другая, в выражении не обязательно должна быть единственной. Аналогично, как и другие операции тернарную можно использовать с другой операцией. Допустимо, например, следующее присваивание: r=a+b*(x>y ? x : y); которое вычисляет r= a+b*max(x, y);
Эта операция может быть вложенной. Например, вычисление r= min(x,y), если a>b и r=x*a+y*b в противном случае можно выполнить так:
r=a>b ? (x<y ? x : y) : x*a+y*b;
4.3. Оператор выбора switch
Аналогичный оператор есть и в других языках (case в Pascal). Он используется, если уровень вложенности if достаточно большой.
Пример 4. Вывести целое однозначное число z прописью.
Это можно сделать с помощью if:
int z; cin>>z; if (z==0) cout<<”нуль”;
else if (z==1) cout <<” один”;
else if (z==2) cout <<” два”;
/* и т.д. записываем if для 3, 4, 5, 6, 7, 8 */
else if (z==9) cout <<”девять”;
else cout<<”Ошибка”;
Второй вариант с оператором switch вместо вложенного if нагляднее и легче для понимания и отладки.
int z; cin>>z;
switch (z)
{ case 0: cout<<”нуль”; break;
case 1: cout <<”один”; break;
case 2: cout <<”два”; break;
case 3: cout <<”три”; break;
case 4: cout <<”четыре”; break;
case 5: cout <<”пять”; break;
case 6: cout <<”шесть”; break;
case 7: cout <<”семь”; break;
case 8: cout <<”восемь”; break;
case 9: cout <<”девять”; break;
default: cout<<”Ошибка ”;
} // Конец оператора switch.
// Здесь оператор, следующий после switch.
Работает оператор так. Пусть,например, z=3. Тогда первые две ветви пропускаются, выполняется cout <<”три”; и break передаёт управление на оператор, следующий после switch. Если z не является однозначным числом, например, числом 30, то первые десять ветвей пропускаются, выводится “Ошибка” и выполняется оператор, следующий после switch.
Оператор switch имеет следующий общий вид:
switch (выражение)
{ case константное_выражение1:
последовательность_операторов1; break;
case константное_выражение2:
последовательность_операторов2; break;
…
case константное_выражениеN:
последовательность_операторовN; break;
default: последовательность_операторов;
}
Выражение, записываемое после ключевого слова switch обязательно в скобках, может быть целого, символьного или перечисляемого типа, который будет рассмотрен позже. В простых задачах может быть переменная. Нельзя использовать выражение вещественного или строкового типа. В константном выражении можно использовать только константы, определённые одним из указанных ранее способов, и нельзя записывать переменные или вызовы функций.
Работает оператор следующим образом. Значения константных выражений вычисляются во время компиляции. Во время выполнения вычисляется значение записанного в круглых скобках после ключевого слова switch выражения и сравнивается с первой константой на строгое равенство. Если значение выражения не совпало с одной из констант, оно же сравнивается со второй константой и т. д. Если, совпало, выполняется соответствующая последовательность операторов, и break передаёт управление на оператор, следующий после switch. Если break отсутствует, то выполняется следующая последовательность операторов, хотя значение выражения и не совпадает со следующей константой. Это основная особенность этого оператора по сравнению с другими языками. В случае отсутствия совпадений выполняются операторы, записанные после default, который необязателен. Если его нет, то в случае отсутствия соответствий ничего не выполняется.
В отличие от языка Pascal нельзя указать диапазон констант. Вместо этого разрешается для нескольких констант указать одну и ту же последовательность операторов.
Пример 5. Анализ оценки z будет выглядеть так:
switch (z)
{ case 1:
case 2:
case 3: cout <<”не удовл.” ; break;
case 4: case 5: cout <<”удовл.”; break;
case 6: case 7: case 8: cout <<”хор.”; break;
case 9:
case 10: cout <<”отл.” ; break;
default: cout<<”Ошибка ”;
}
При этом ключевые слова case желательно записывать в “столбик”, как это сделано для неудовлетворительной и отличной оценки, а не в строку, как это записано во второй и третьей ветвях.
Допускается вложенность операторов switch, когда в любой последовательности операторов используется другой switch. Константы или значения константных выражений внутреннего и внешнего операторов switch могут совпадать. На одном уровне switch они должны быть различными. Например, допустима следующая часть программы:
char flag1, flag2; ……
switch (flag1)
{ case ‘A’: switch (flag2)
{ case ‘A’: cout<<”AA”; break;
case ‘B’: cout<<”AB”;
} break;
case ‘X’: …
…
}
Упражнения и тесты
1.Дано x. Вычислить y = x*x, если x > 0, иначе y = 100.
Предлагаются следующие три варианта решения:
a) if (x>0) y=x*x; else y=100; cout<<"y= "<<y;
б) y = x>0?x*x:100; cout<<"y= "<<y;
в) cout<<"y= "<<(x>0?x*x:100);
2. Даны х, y. Вывести “+++” или “– – –” в зависимости от того, x>y или нет.
Решение: а) if (x>y) cout<<”+++”; else cout<<“– – –”;
б) x>y? cout<<" +++ " : cout<<“– – –”;
3. Вывести “Yes” или “No” в зависимости от того, точка с координатами x, y принадлежит области, ограниченной линиями y= –x, x=0 и y= –1, или нет.
Решение:
if (y<=–x && x>=0 && y>–1 ) cout<<"Yes"; else cout<<"No";
4.Нарисовать область плоскости, в которой и только в которой следующее логическое выражение истинно:
а) x>y && x<2 && y>-1; б) x>y || x<2 && y>-1; в) x>y && x<2 || y>-1; г) x>y || x<2 || y>-1; д) x>y && (x<2 || y>-1); е) x>y && !(x<2 || y>-1).
5. Определить результат, то есть значения переменных a, b и r, после выполнения оператора if. Даны, например, следующие начальные значения этих переменных: a) int a=2, b=3, r=4; b) int a=5, b=5, r=4; c) int a=-5, b=5, r=4; d) int a=0, b=3, r=4;. Варианты оператора if:
1) if (a>=1) r=a+b; else if (b>0) r=a-b;
else if (b<-5) r=a*b; else r=a;
2) if (a>=1) r=a+b; else if (b>0) r=a-b;
else if (b<-5) r=a*b;
3) if (a=b) if (b) r=a+b; else r=a-b;
4) if (a>=1) { if (b>0) r=a+b; } else r=a-b;
5) if (a>=1) if (b>0) r=a+b; else r=a-b;
6) if (a+b) if (a-b) {a*=b; b*=a++; }
else { a*=(--b); b*=(a--); }
else { a--; b=a; ++b; }
7) if (a+b) if (a-b) {a*=b; b*=a++; }
else { a*=(--b); b*=(a--); }
else a--; b=a; ++b;
8) if (a=b) { if (b) r=a+b; } else r=a-b;
9) if (a==b) if (b) r=a+b; else r=a-10;
10) if (a==b) { if (b) r=a+b; } else r=a-10;
11) if (a+b) if (a-b) {a*=b; b*=a++; } else { a*=(--b); b*=(a--); }
else { a--; b=a; ++b; }
12) if (a+b) if (a-b) {a*=b; b*=a++; } else { a*=(--b); b*=(a--); }
else a--; b=a; ++b;
6. Пусть float x=… , y=…, a=… , b=…, где a>0, b>0 (на месте многоточия конкретные числовые константы). Определить результат (true или false) для каждого логического выражения
1) y>fabs(x) && fabs(x)<a && y<b; 2) y>fabs(x) || fabs(x)<a && y<b;
3) y>fabs(x) && fabs(x)<a || y<b; 4) y>fabs(x) || fabs(x)<a || y<b;
5) (y>fabs(x) || fabs(x)<a) && y<b; 6) y>fabs(x) || ( fabs(x)<a && y<b);
7) ! (y>fabs(x) || fabs(x)<a) && y<b;
В следующих вариантах (8), 9) и т.д.) которые можно записать самостоятельно, по-разному расставлены скобки, меняются логические операции, операции сравнения и место логического отрицания.
7. Записать номера логических выражений, для которых получим true, если int x=…, y=…;(на месте многоточия конкретные числа).
Уровень А. Используются логические выражения, составленные по образцу предыдущего типа теста.
Уровень B. Используются логические выражения, в которых логические величины сравниваются по следующим правилам:
true = = true; false = = false ; true > false.
Примеры таких логических выражений:
1) (y>x) = = (x>0); 2) (y>x) ! = (x>0); 3) (y>x) > (x>0);
4) (y>x) < (x>0); 5) (y>x) >= (x>0); 6) (y>x) <= (x>0);
7) (y > x) > !(x > 0)и т. п.
8. Пусть float x=…, y=…, r; (x и y проинициализированы конкретными значениями).Записать в указанном порядке значения x, y, r, которые получатся после выполнения операции присваивания и тернарной операции
1) r= x>1 || y<=0 ?++x:y- -; 2) r= !(x>1 || y<=0) ? x++: - -y;
3) r= x>1 &&|| y<=0 ? x+1: y+1-; 4) !(x>1 && y<=0) ? r=++x: r=--y;
9.Сравнить оператор switch с оператором case языка Pascal.
10.Что будет выведено, если введём
1) 1 2) 5 3) 8 4) 0 5) 22 ?
int m; cin>>m;
switch (m)
{case 1:case 2: case 3: cout<<2; break;
case 4: case 5: cout<<3; break;
case 6: case 7: case 8: cout<< 4;
case 9: case 10: cout<< 5; break;
default: cout<<"Error";
}
Оператор break может отсутствовать в одной или нескольких других ветвях.
11. В каких строках ( //1 -- //6) есть ошибки компиляции?
#define ONE 1
int m; const n=4, float k=1; cin>>m;
switch (m+k) //1
{ case ONE: //2
case т: cout<< 2; break; //3
case ONE+2: cout<<3; //4
case n: cout<<4; //5
case k+n: cout<<"Five"; break; //6
}
12. В каких строках ( //1 — //7) есть ошибки компиляции?
char C, B='B'; C=getch();
switch (C) //1
{ case 'A': cout<<"А"; //2
case “B”: switch (B) //3
{ case 'A': cout<< " BA "; break; //4
case B : cout << " BB "; break; //5
case ‘C’ : cout<< " BC "; break; //6
}
case С: cout<<" C "; } //7
Задачи
1. Ввести число. Вывести 0 или 1 в зависимости от того, положительное число или неположительное. Выполнить это двумя способами:
#include <iostream.h>
#include <conio.h>
int main() { float x; int result;
cout<<"The number "; cin>>x;
cout<<"The first variant " ; cout<<(x>0)<<endl;
cout<<"The second variant " ;
if (x>0) result=1; else result=0;
cout<<result<<endl; getch(); return 0; }
2. Найти наибольшее из трех введенных чисел:
main() { int x, y, z, res1, res2, res3;
cout<<"The first number "; cin>>x;
cout<<"The second number "; cin>>y;
cout<<"The third number "; cin>>z;
cout<<"Max of numbers (" <<x<<" , "<<y<<" , "<<z<<" ) ";
// Полная форма оператора if:
if (x>y) res1=x; else res1=y;
if (z>res1) res1=z;
cout<<”\nVariant 1 “<<res1<<endl;
// Сокращённая форма оператора if:
res2= x; if (y > res2) res2= y;
if (z > res2) res2= z;
cout<<" Variant 2 "<< res2<<endl;
// Тернарная операция :
res3=x>y?x:y; res3=z>res3?z:res3;
cout<<" Variant 3 "<<res3;
getch(); return 0; }
Указания.Одну и ту же задачу по возможности решить несколькими способами, используя, например, сокращенную и полную формы if, if и switch, if и тернарную операцию.
Уровень А
1. Вычислить r = max(min(x, y), z).
2. Вычислить r = max(x, 0) + min(y, z).
3. Вычислить r = min(x, y, 0) + max(y, z).
4. Найти произведение двух наименьших из трех чисел.
5. Найти действительные корни квадратного уравнения, если заданы его коэффициенты. Предусмотреть следующие варианты: два различных корня; один корень; нет действительных корней.
6. Ввести часы, минуты и секунды. Определить корректность момента времени.
7. Даны длины трех отрезков A, B, C. Определить возможность построения треугольника и его вид (разносторонний, равнобедренный, равносторонний).
8. Расположить два числа a, b в порядке убывания их значений.
9. Вычислить значение функции в соответствии с заданным графиком для произвольного одного фиксированного значения аргумента.
10. Даны a, b, c, K, P. Вычислить значение функции
11. Даны два вещественных числа x, y. Если точка плоскости с координатами (x, y) принадлежит треугольнику с вершинами в точках (–2, 0), (0, 2), (2, 0), то обе координаты увеличить в 10 раз, в противном случае уменьшить их на число 10.
12. Даны два вещественных числа x, y. Вывести “Yes” или “No” в зависимости от того, точка плоскости с координатами (x, y) принадлежит кольцу, ограниченному окружностями, радиусы которых 1 и 3 c общим центром в точке с координатами (a, b), или не принадлежит этому же кольцу.
Решить задачи, аналогичные 11, 12, для других областей, параметры которых — конкретные числа.
13. В зависимости от номера месяца вывести одно из слов: зима, весна, лето или осень.
14. В зависимости от номера месяца получить номер квартала.
15. Дано целое число. В зависимости от его значения вывести в правильном падеже какое-нибудь заданное слово. Например, 563 символа, 1713 символов, 91 символ и т. п.
16. Вывести заданное целое положительное число a прописью, если
а) a<100; b) a<1000. Например, 7 — семь, 26 — двадцать шесть, 145 — сто сорок пять, 13 — тринадцать.
Уровень B
1. Расположить четыре числа a, b, c, d в порядке возрастания их значений. Массив и операторы цикла не использовать.
2. Ввести вещественные a и k. Вывести на экран одночлен a*x^k. При этом если a=1, выводить только x^k, где k — введенное число, а 1 не выводить. Если A=-1, выводить –x^k, если A=0, x^2 не выводить. Аналогично предусмотреть следующие варианты для k: k=1, k=-1, k=0.
3. Ввести коэффициенты квадратного уравнения A, B и C. Вывести на экран
A*x^2+B*x+C=0. При этом если A=1, выводить только x^2, то есть 1 не выводить, если A=-1, выводить –x^2, если A=0, x^2 не выводить. Аналогично для B. Не выводится также нулевое значение С.
4. Ввести два числа: номер месяца и день. Выполнить проверку корректности этой даты. Например, 3 и 31 определяют дату, а 4 и 31, 20 и 5 — нет. Вывести слово “да” или “нет”.
5. Даны два вещественных числа x, y. Вывести 0, если точка плоскости с координатами (x, y) не принадлежит кольцу, ограниченному окружностями, радиусы которых r и R (r<R) c общим центром в начале координат. Если точка (x, y) принадлежит этому кольцу, вывести 1, 2, 3 или 4 в зависимости от того, в какой четверти находится соответствующая часть кольца. Выполнить контроль ввода двух радиусов, которые в этом примере являются параметрами области. Если r>R или один из радиусов или оба неположительные, то вывести соответствующее сообщение, x, y не вводить, не анализировать и закончить программу.
6. Задачи 15 и 16 уровня А решить вместе в одном проекте.
7. Дано целое положительное число a<1000000. Вывести это число, отделив пробелом каждую тысячу, а также в скобках вывести его прописью, добавив слово рубль (рубля, рублей). Например, для числа 514230 вывод такой 514 230 (пятьсот четырнадцать тысяч двести тридцать рублей); для 4002 выводим 4 002 (четыре тысячи два рубля);для числа 51 выводим 51 (пятьдесят один рубль).
Г л а в а 2
ЦИКЛЫ
В этой главе будут рассмотрены циклические алгоритмы и их реализация на языке С++.
Оператор while
Пример 1.
int main()
{ int mult, to, RES=1;
cout<<"Mult="; cin>>mult; cout<<"To="; cin>>to;
while (RES< to)
RES*=mult; // или RES=RES*mult;
cout<<"\nResult= "<<RES;
getch(); return 0; }
Оператор while называется оператором цикла с предусловием и выполняется, как и в других языках, следующим образом. Вне цикла, то есть один раз вводим два целых значения и RES=1. Пусть в качестве mult ввели 2, а to=100. Проверяется условие RES<to, записанное в скобках оператора while, то есть 1<100. Так как условие истинно, выполняется RES*=mult, то есть RES=1*2=2. Без каких-либо дополнительных операторов передаётся управление на повторную проверку условия RES<to. Так как 2<100, выполняется RES*=mult, то есть RES=2*2=4. Снова проверяется 4<100, увеличивается RES и т. д., то есть переменная RES будет принимать последовательно значения 16, 32,…. До каких пор? На некотором шаге RES примет значение 64. Так как 64<100, то RES=64*2=128. Проверяется условие 128<100, и так как оно ложно, выходим из цикла. Это означает, что выполняется оператор, записанный после while, а точнее, после последнего повторяющегося оператора (после тела цикла). У нас повторяется единственный оператор, не считая условия, поэтому выполняется cout<<"\nResult="<<RES и выводится 128.
Оператор while имеет следующий общий вид:
while (выражение) { оператор1;
оператор2; …
операторN;
}
Выражение в отличие от Pascal должно записываться в круглых скобках. В простых случаях, как и в других языках, оно является логическим, то есть содержит логические и (или) операции сравнения. Но, в отличие от других языков, как и в операторе if, это не обязательно. Вместо while (X !=0 ) операторы; можно записать короче: while (X) операторы;
Фигурные скобки (Begin … End в Pascal) определяют операторы, которые наряду с вычислением и проверкой выражения будут повторяться (тело цикла). Если в теле цикла один оператор, фигурные скобки не обязательны, но не будет ошибки, если их написать. Поэтому если есть сомнения в количестве повторяющихся операторов, то лучше скобки записать. Не будет ошибки, если цикл в первом варианте в начале параграфа записать так:
while (RES< to) { RES*=mult; }
Как и в операторе if, эти скобки обязательны, если повторяется более одного оператора, не считая вычисление и анализ выражения в скобках. Например, добавление в наш цикл фигурных скобок
while ( RES<to) { RES*=mult; cout<<"\nResult= "<<RES; }
приведёт к тому, что вывод будет выполняться не один раз, как в начальном варианте, а будет повторяться. В этом случае в “столбик” будет выводиться 2, 4, 8, …, 128 каждый раз вместе с одним и тем же текстом "Result= ". так как cout<<"\nResult=”; содержит управляющий символ ‘\n’ для перехода на новую строку.
Упражнение. Как слово Result вывести один раз, а все произведения (2 4 8 и т. д.) вывести в строку?
Выполнение оператора начинается с вычисления и проверки выражения. Если оно истинно (не равно нулю), выполняется тело цикла, и управление передаётся на повторную проверку выражения. В случае его истинности снова выполняются повторяющиеся операторы. Если на некотором шаге значение выражения станет ложным (равным нулю), осуществляется выход из цикла. Это означает, что тело цикла не выполняется, и управление передаётся на оператор, записанный после while (после тела цикла), а точнее, после закрывающей фигурной скобки для while, если она есть, или после единственного повторяющегося оператора, если скобок нет.
Приведём важные с практической точки зрения правила использования и особенности оператора while.
Значения всех переменных, входящих в выражение, должны быть определены до выполнения оператора while. Для этого их можно ввести (переменная to в нашем примере), задать в виде константы (RES), вычислить с помощью выражения, обращения к функции или задать другими способами. В противном случае переменная принимает случайное значение и результат непредсказуем. В нашем примере такая ошибка будет иметь место, если, например, забыть ввести переменную to или не записать RES=1.
Выражение вычисляется и анализируется в начале перед выполнением тела цикла. Поэтому тело цикла может ни разу не выполниться, если в самом начале на первом шаге выражение ложно. Например, это произойдёт в нашем примере, если ввести в качестве переменной to