Программирование >>  Динамические структуры данных 

1 2 3 [ 4 ] 5 6 7 ... 38


ШаШа

Тестовые примеры для этой программы должны включать по крайней мере по одному значению аргумента из каждого интервала, а для проверки храничных условий - еще и все точки перегиба (если это кажется вам излишним, попробуйте в последнем условии забыть знак =, а затем ввести значение х, равное 2).

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

Операции отношения (<, >, -, <, >, !=) являются бинарными, то есть имеют два операнда, и формируют результат типа bool, равный true или false . Поскольку необходимо, чтобы эти условия выполнялись одновременно, они объединены с помощью операции логического И (&&) - не путать с поразрядным И! Приоритет у операции И ниже, чем у операций отношения, поэтому заключать их в скобки не требуется.

Весьма )аспространенная ошибка начинающих - запись подобных условий в виде кальки с математической формулы, то есть как а<Ь<с. Синтаксической ошибки в этом выражении нет, поэтому компилятор не выдает каких-либо сообщений. Давайте посмотрим, что же происходит при вычислении. Операции отношения одного приоритета выполняются слева направо, поэтому сначала будет выполнена операция а<Ь и сформирован результат в виде true или false. Следующая операция будет выглядеть как true<c или false<c. Для ее выполнения значения true и fal se преобразуются соответственно в единицу и ноль того же типа, что и с, и формируется результат, смысл которого вряд ли соответствует ожиданиям.

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

if ( X <= -2 ) у = 0:

else if ( X < -1 ) у = -х - 2:

else if ( X < 1 ) у * х:

else if ( X < 2 ) у = -х + 2;

else у 0:

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

у = 0:

if ( X > -2 ) у = -X - 2:

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

if ( X > -1 ) у - х:

if ( X > 1 ) у - -X + 2:

if ( X > 2 ) у = 0:

Запись фрагмента стала еще короче, но появились два недостатка: значение функции вычисляется многократно (от двух до пяти раз в зависимости от интервала, которому принадлежит х), значит, увеличилось время выполнения, а главное - программа потеряла универсальность, то есть таким способом можно вычислить не всякую функцию. Для того чтобы в этом убедиться, попробуйте заменить у-х на, к примеру, фрагмент окружности y sqrt(1-х*х) и ввести значение х, большее 1 - это приведет к ошибке в программе, связанной с вычислением квадратного корня из отрицательной величины.

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

СОВЕТ -

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

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

В заключение приведем вариант с использованием функций ввода-вывода в стиле С:

#inclucle <stdio.h> int main(){ float X. у:

printfC Введите значение аргумента:\n ):

scanfCXf . &x):

if ( X < -2 ) у - 0:

if ( X >= -2 && X < -1 ) у - -X - 2:

if ( X >- -1 && X < 1 ) у = x:

if ( X >= 1 && X < 2 ) у = -X + 2:

if ( X >= 2 ) у = 0:

printfC Для X = %S.2f значение функции у *5.2f\n . x, у): return 0:

Задача 2.2. Выстрел по мишени

Дана заштрихованная область (рис. 2.2) и точка с координатами (х,у). Написать программу, определяющую, попадает ли точка в область. Результат вывести в виде текстового сообщения.

2 Зак.784




Рис. 2.2. Графически згщанная область для задачи 2.2

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

{сЧ/<1}илм

х<0 >;<0 у>-х-2

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

#include <iostream.h> int main(){ float X. у:

cout Введите значения x и у: endl: cin X у:

if ( x * X + у * у 1 II X О && у <= О && у >= - X - 2)

cout Точка попадает в область endl: else cout Точка не попадает в область endl: return 0:

Три условия из правых фигурных скобок должны выполняться одновременно, поэтому в программе они объединяются с помощью операции И. Ее приоритет выше, чем у ИЛИ ( ), и ниже, чем у операций отношения, поэтому дополнительных скобок не требуется.

Рассмотрим пример дрзах)й заштрихованной области (рис. 2.3). Условный оператор для определения попадания точки в эту область имеет вид:

if ( у < О && ((X - 1) * (X - 1) + у * у <= 1 II (X + 1) * (X + 1) +у *у 1 )) cout Точка попадает в область : else cout Точка не попадает в область :


Рис. 2.3. пример еще одной области

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

ПРИМЕЧАНИЕ------

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

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

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

if ( int к - f(x) ) а к * к: else а к - 1:

Область видимости этой переменной ограничивается условным оператором*.

ВНИМАНИЕ---

Если по какой-либо ветке условия необходимо выполнить более одного действия, их следует объединить в блок с помощью фигурных скобок.

В блоке можно также объявлять локальные переменные; их областью видимости является этот блок:

if ( X < О ){ int i: i - 2: cout i: }

Следует избегать проверки вещественных величин на равенство; вместо этого лучше сравнивать модуль их разности с некоторым малым числом. Это связано с погрешностью представления вещественных значений в памяти:

float а. b: ...

if ( а b ) cout равны : else cout не равны : /* Не

рекомендуется! */

if ( fabs(a - b) < le-6 ) cout равны : else cout не равны : Верно!

Эта возможность в старых компиляторах не реализована.



Значение величины, с которой сравнивается модуль разности, следует выбирать в зависимости от решаемой задачи и точности участвующих в выражении переменных. Снизу эта величина ограничена определенными в заголовочном файле <f 1 oat. h> константами FLTJPSILON 1.192092896e-07FHDBL EPSIL0N - 2.2204460492503131e-016. (FL7 EPSIL0N - это минимально возможное значение переменной типа float, такое, что 1.0 + FLT EPSILON != 1.0, DBL EPSILON - аналогичная константа для типа double).

Для присваивания какой-либо переменной в зависимости от выполнения условия двух различных значений лучше пользоваться не оператором i f, а тернарной условной операцией, например:

if ( а < b ) с - х: else с - у: Нерационально

с (а<Ь)?х:у: Реконендуется

Тернарной эта операция называется потому, что у нее три операнда. Первый операнд представляет собой выражение, результат вычисления которого преобразуется в значение true или fal se. После знака вопроса через двоеточие записываются два выражения. Результат вычисления первого из них принимается за результат всей операции, если первый операнд имеет значение true. В противном случае результатом всей операции является результат вычисления второго выражения. Таким образом, переменной с будет присвоено значение либо переменной х, либо у. Давайте теперь рассмотрим простой пример применения оператора switch.

Задача 2.3. Клавиши курсора

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

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

#include <stdio.h> #include <conio.h> int main(){ int key:

printf( \n Нажмите одну из курсорных клавиш:\n ): key - getchO: key getchO: switch (key){

case 77: printf( стрелка вправоХп ): break: case 75: printf( стрелка влевоХп ): break; case 72: printf( стрелка вверхХп ): break case 80: printf( стрелка внизХп ): break default: printf( He стрелкаХп ):

return 0:

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

case 77: case 75: case 72: case 80: printf( стрелки ): break:

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

СОВЕТ-

Хотя наличие слова default и не обязательно, рекомендуется всегда обрабатывать случай, когда значение выражения не совпадает ни с одной из констант. Это облегчает поиск ошибок при отладке программы.

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

Циклы

Теоретический материал: с. 44-49,237.

Цикл - участок программы, повторяемый многократно. В С++ три взаимозаменяемых оператора цикла - whi 1е, do whi 1е и for. При написании любого цикла надо

Начальные установки

Тело цикла

Модификация параметров цикла


Рис. 2.4. Блок-схема цикла



1 2 3 [ 4 ] 5 6 7 ... 38

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика