Порядок выполнения внутри оператора switch Министерство финансов Российской Федерации Всероссийская государственная налоговая академия ИНФОРМАТИКА И ПРОГРАММИРОВАНИЕ Бакалавры: 230700 "Прикладная информатика" Язык программирования С++ Лабораторная работа № 06 ПРОГРАММИРОВАНИЕ РАЗВЕТВЛЯЮЩИХСЯ ВЫЧИСЛИТЕЛЬНЫХ ПРОЦЕССОВ Автор профессор кафедры "Прикладной информатики в экономике" кандидат технических наук Л.К. Кузнецов Марта 2012 г. Москва ВГНА Лабораторная работа № 06 Программирование разветвляющихся вычислительных процессов Цель работы: Ознакомиться: Ø c операциями сравнения Ø c логическими операциями; Ø со старшинством (приоритетом) операций; Ø с понятием разветвлявшегося вычислительного процесса (РВП); Ø со средствами реализации РВП в языке С++; Ø с оператором перехода; Ø с пустым оператором; Ø с условным оператором и его формами в языке С++; Ø с понятием группы операторов (с понятием составного оператора); Ø с оператором выбора switch; Ø с особенностями задания исходных значений переменных с при объявлении переменных помощью модификатора const; Ø с рекомендациями по заданию исходных значений переменным. Получить практические навыки по программированию: Ø простых РВП; Ø сложных (произвольных) РВП. Овладеть: Ø средствами языка С++ для реализации РВП. 1. КРАТКИЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ 1.1. Операции сравнения и логические операции 1.1.1. Операции сравнения В языке С++ определены следующие операции сравнения: < (меньше), > (больше), <= (меньше или равно), >= (больше или равно), == (равно), != (не равно). Все эти операции являются бинарными (двуместными). Четыре последних знака операций – составные: оба символа вместе образуют единый знак операции, их нельзя отделять пробелом. Примеры: a<b, x!=5, y==c, t>=8.1, d<>(w-c). Операции сравненияприменяются при работе с двумяоперандами и воз-вращают значение true (1), если результат сравнения – истина, и – значение false (0), если результат сравнения – ложь. Примечание. Строго говоря, в С++ значению ИСТИНА соответствует не только значение 1, но и любое другое ненулевое значение. В С++ допускаются три типа сравнений: Ø арифметическое – между арифметическими величинами (переменными и константами типа); Ø битовое – между строками бит (переменными и константами); Ø символьное – между строками символов (переменными и константами типа). Результат операции сравнения всегда есть битовая строка единичной длины: значение есть 1, если отношение истинно (например, 7> 3.5, 'АС' > 'В'), и 0, если отношение ложно (например, 7 <=3.5, 'АС' <= 'В'). Операции сравнения в основном используются в условном операторе if, обеспечивающем условный переход в программе. Например, if (у >z) x = y – z; else x = z – y; Вычисление выражения у >z дает значение 1 или 0в. если это 1, выполняется ветвь "Да" (оператор x = y – z;), если же 0 - else-ветвь (оператор x = z – y;). Однако операции сравнения применяются не только в операторах if,Так, допустим, оператор присваивания x = у > z; Если у больше z,переменной x будет присвоено значение 1, если нет – значение 0. Допустим также оператор х = у ==z; (или x = ( у==z);) Здесь первый символ = есть символ оператора присваивания, второй символ == есть символ операции сравнения. Если у равно z,значение x будет 1, если у не равно z, значение x будет 0. Наполним, что если мы хотим переменным x и у присвоить значение переменной z,то оператор присваивания должен быть записан в виде х = у = z ; В общем случае могут быть и более сложные конструкции оператора присваивания с операциями сравнения, например к3 = (а < в) * (в <с); Примеры выполнения операций сравнения в языке С++ приведены в табл. 6.1. Таблица 6.1 Операции сравнения языка C++ Операция | Проверка | Пример | == | Если два значения равны | (score == 100) | != | Если два значения не равны | (old != new) | > | Если первое значение больше второго | (cost > 50.00) | < | Если первое значение меньше второго | (salary < 20000.00) | >= | Если первое значение больше или равно второму | (stock_price >= 30.0) | <= | Если первое значение меньше или равно второму | (age <= 21) | 1.1.2. Логические операции Логические операции работают с операндами скалярных типов и возвра-щают результат булева типа. С++ поддерживает три логические операции: && – логическое И; | | – логическое ИЛИ; ! – отрицание или логическое НЕ. Операция отрицания НЕ является унарной (одноместной), а операции И (конъюнкция) и ИЛИ ( дизъюнкция) – бинарные (двуместные). Логические операции определены для операндов, имеющих значение битового типа. Операнды другого типа должны быть преобразованы в строки бит. Логические операции имеют более низкий приоритет, чем операции отношения. Результаты выполнения логических операций над строками, состоящими из одного бита, приведены в таблице 6.2. Таблица 6.2 Правила выполнения логических операций Операция И | | Операция ИЛИ | | Операция НЕ | | | | | | | | | | | x | y | x && y | | x | y | x || y | | x | !x | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Логические операции используется в основном в условном операторе и операторе присваивания. 1.1.3. Логические выражения Логическое выражение (условие) – выражение, которое содержит знаки операций отношения и/или знаки логических операций. Значением логического выражения может быть только 1, если логическое выражение есть ИСТИНА (true), или 0, если логическое выражение ЛОЖЬ (false). Например, логическое выражение a>3 && c<7 при a=5, c=6 будет иметь значение ИСТИНА, а при a=3, c=8 – ЛОЖЬ; логическое выражение a>3 || c<7 при a=5, c=6 будет иметь значение ИСТИНА, при a=2, c=6 – ЛОЖЬ; при a=7 логическое выражение !a>2 будет иметь значение ЛОЖЬ. При составлении логических выражений следует учитывать приоритет выполнения операций (табл. 6.4). Примеры записи логических выражений приведены в табл. 6.3. Таблица 6.3 Примеры записи логических выражений Условие | Логическое выражение | x Î[a, b] | x>=a && x<=b | x Î[a, b] | x<a || x>b | x Î[a, b] или ] x Î[c, d] | x>=a && x<=b || x>=c && x<=d | Хотя бы одно из чисел x, y положительное | x>0 || y>0 | Только одно из чисел x, y положительное | (x>0 && !y>0) || (y>0 && !x>0) | Ни одно из чисел x, y не является четным | x % 2 !=0 && y % 2 !=0 | Точка (x,y) принадлежит заштрихованной области  | x>=0 && x<=a && y>=0 && y<=b/a*x | 1.2. Приоритет операций В лабораторной работе № 4 отмечалось, что требуемый порядок выполнения операций программист может задать с помощью круглых скобок. Если же круглые скобки не определяют полностью порядок выполнения операций, то операции выполняются в соответствии с их приоритетами (старшинством, рангом). С учетом рассмотренных в данной лабораторной работе операций сравнения и логических операций, а такие арифметических операций, рассмотренных ранее в лабораторной работе № 3, приведем окончательный список всех операций языка С++, упорядоченных согласно их приоритетам (табл. 6.4). Таблица 6.4 Ранг | Порядок | Операция (оператор) | Действие | Применение | | Л | : : | Глобальная область видимости | : : имя | | Л | : : | Область видимости класса | класс::имя | | Л | : : | Область видимости пространства имен | пространствоимен::имя | | Л | . | Обращение к члену класса | объект.член | | Л | - > | Обращение к члену класса | указатель->член | | Л | [] | Индексирование | переменная [выражение] | | Л | () | Вызов функции | имя(список_выражений) | | Л | () | Создание типа | тип(список_выражений) | | П | ++ | Постфиксный инкремент | 1 -значение++ | | П | -- | Постфиксный декремент | 1-значение-- | | П | typeid | Идентификатор типа | typeid(тип) | | П | typeid | Идентификатор типа времени выполнения | typeid(выражение) | | П | Явное приведение | Преобразование типов | имя_приведения<тип>(выражение) | | П | sizeof | Размер объекта | sizeofвыражение | | П | sizeof | Размер типа | sizeof(тип) | | П | ++ | Префиксный инкремент | ++1-значение | | П | -- | Префиксный декремент | - -1 -значение | | П | ~ | Побитовый NOT | ~выражение | | П | ! | Логический NOT | !выражение | | П | - | Унарный минус | -выражение | | П | + | Унарный плюс | +выражение | | П | * | Обращение к значению | *выражение | | П | & | Обращение к адресу | &выражение | | П | () | Преобразование типов | (тип) выражение | | П | new | Создание объекта | newтип | | П | delete | Освобождение объекта | deleteвыражение | | П | delete [] | Освобождение массива | delete []выражение | | Л | ->* | Указатель на член класса | указатель ->* указатель_на_ член | | Л | . * | Указатель на член класса | объект .* указатель_на_ член | | Л | * | Умножение | выражение * выражение | | Л | / | Деление | выражение / выражение | | Л | % | Деление по модулю (остаток) | выражение % выражение | | Л | + | Сумма | выражение + выражение | | Л | - | Разница | выражение - выражение | | Л | << | Побитовый сдвиг влево | выражение << выражение | | Л | >> | Побитовый сдвиг вправо | выражение >> выражение | | Л | < | Меньше | выражение < выражение | | Л | < = | Меньше или равно | выражение <= выражение | | Л | > | Больше | выражение > выражение | | Л | > = | Больше или равно | выражение >= выражение | | Л | == | Равенство | выражение == выражение | | Л | != | Неравенство | выражение != выражение | | Л | & | Побитовый AND | выражение & выражение | | Л | ^ | Побитовый XOR | выражение ^ выражение | | Л | | | Побитовый OR | выражение | выражение | | Л | && | Логический AND (конъюнкция «И») | выражение && выражение | | Л | || | Логический OR (дизъюнкция «ИЛИ») | выражение || выражение | | П | ?: | Условная операция | выражение ? выражение : выражение | | П | = | Присвоение | 1-значение = выражение | | П | *=, /=, %=, | Составные операторы присвоения | 1-значение += выражение и т.д. | | П | +=, -= | | П | <<=, >>= | | П | &=, |=, ^= | | П | throw | Передача исключения | throwвыражение | | Л | , | Запятая | выражение , выражение | Напомним, что наивысший приоритет имеют операции под номером 1, затем операции под номером 2 и так далее. 1.3. Разветвляющийся вычислительный процесс Как вы уже знаете из предыдущих работ, программа представляет собой последовательность инструкций (операторов), выполняемых компьютером для реализации определенных задач. Все созданные вами до сих пор простые программы на C++ выполняли операторы по порядку, начиная с первого до конца программы. Обычно операторы в программе на С++ выполняются в порядке их следования в программе (см. лабораторную работу № 5), то есть слева направо и сверху вниз. Такой порядок выполнения операторов принято называть линейным, или естественным. Однако в практике вычислений мало встречается процессов, которые задаются только линейной последовательностью выполнения операторов (операций, блоков, этапов и т.п.). Как правило, направление вычислительного процесса при решении многих задач зависит от исходных данных или промежуточных результатов. При программировании требуется прерывать естественный порядок выполнения операторов, проводить различные проверки отношений между элементами обрабатываемых данных и в зависимости от их исхода выполнять те или иные действия. При выполнении некоторых операций могут возникать исключительные операции, то есть такие операции, в которых результат операции либо ошибочен, либо не определен. В этих случаях также требуется в зависимости от исхода операции выполнять ту или иную последовательность действий. По мере усложнения программ вам потребуется, чтобы выполнялся один набор операторов, если определенное условие соблюдается, и другой набор, если условие не соблюдается. Другими словами, вам потребуется, чтобы ваши программы приняли решение и соответственно отреагировали. Вычислительный процесс называется разветвляющимся (РВП), если в зависимости от исходных данных (условий) или промежуточных результатов он реализуется по одному из нескольких, заранее предусмотренных (возможных) направлений. Каждое отдельное направление, по которым может следовать вычислительный процесс, называют его ветвями. В каждом конкретном случае вычислительный процесс реализуется по одной ветви, остальные остаются не задействованными. Выбор направления вычислений осуществляется проверкой выполнения некоторого логического условия. Обычно это логическое условие выражает определенные свойства величин, входящих в расчетные формулы. Выполнение данного логического условия однозначно определяет выбор одной из ветвей вычислительного процесса. Простейшим примером разветвления вычислений может служить формула определения значения абсолютной температуры воздуха на различных высотах: |  | 288,16 - 0,0065, | если 0 £ h < 11000 м, | | T = | 216,16, | если 11000 £ h< 25000 м, | | | 216,16 + 0,00276098 (h- 25000), | если 25000 £h < 46000 м. | | | | | | | Здесь Т- абсолютная температура воздуха; h - высота над уровнем моря. В приведенном выше примере вычислительный процесс имеет три направления (ветви). Проверка логического условия для выбора одной из его ветвей состоит в определении диапазона высот, которому соответствует текущее значение переменной h. 1.4. Реализация РВП средствами языка С++ Для реализации РВП все языки программирования предоставляют определенные средства. Эти средства состоят из операторов сравнения, логических операторов и собственно операторов управления ходом вычислительного процесса. Операторы управления обеспечивают необходимую последовательность выполнения операторов программы, возможно, отличную от последовательности записи операторов в программе. В этом разделе кратко рассматривается некоторые из подобных средств управления языка С++. Операторы сравнения Оператор !=. Не равно. Проверяет неравенство левого и правого операндов. Оператор ==. Равно. Проверяет, равен ли левый операнд правому. Оператор <. Меньше чем. Проверяет, меньше ли левый операнд, чем правый. Оператор >. Больше чем. Проверяет, больше ли левый операнд, чем правый. Оператор <=. Меньше или равно. Проверяет, меньше или равен левый операнд правому. Оператор >=. Больше или равно. Проверяет, больше или равен левый операнд правому. Логические операторы Оператор AND. Логическое И. Результатом оператора AND (&&) будет значение true только в том случае, если оба его операнда возвращают значение true. Оператор OR. Логическое ИЛИ. Логический оператор OR ( | | ) возвращает значение true, если любой из его операндов расценивается как значение true. Оператор NOT. Логическое НЕ.Логический оператор NOT (!) рассматривают свой операнд как условие. Он возвращает результат, который имеет логическое значение, противоположное его операнду. Побитовые операторы Оператор ~. Побитовый оператор NOT (НЕ). Инвертирует биты своего операнда. Оператор &. Побитовый оператор AND (И). Создает новое целочисленное значение, в котором каждая битовая позиция имеет значение 1, если оба операнда в этой позиции имеют значение 1. В противном случае бит получает значение 0. Оператор |. Побитовый оператор OR ИЛИ). Создает новое целочисленное значение, в котором каждая битовая позиция имеет значение 1, если любой из операндов содержит значение 1 в этой битовой позиции. В противном случае бит получает значение 0. Оператор ^. Побитовый оператор XOR (исключающее ИЛИ).Создает новое целочисленное значение, в котором каждая битовая позиция имеет значение 1,если любой (но не оба) из операндов содержит значение 1 в этой битовой позиции. В противном случае бит получает значение 0. Оператор<<. Побитовый оператор сдвига влево. Сдвигает биты левого операнда влево. Оператор>>. Побитовый оператор сдвига вправо. Сдвигает биты левого операнда вправо. Операторы управления Оператор break. Завершает ближайший вложенный цикл или оператор switch. Передает управление первому оператору после завершенного цикла или оператора switch. Осуществляет принудительный выход из цикла оператора switch. Оператор continue. Завершает текущую итерацию ближайшего вложенного цикла. Передает управление условию цикла while, оператору do или выражению в заголовке цикла for. Оператор for. Управляющий оператор, который обеспечивает итерационное выполнение кода тела цикла. Зачастую используется для перебора структур данных, а также для повторения вычислений определенное количество раз. Оператор goto. Оператор, который осуществляет безусловную передачу управления помеченному оператору в другом месте программы (внутри той же функции). Операторы goto нарушают последовательность выполнения операций программы, поэтому их следует избегать. Оператор if. Условное выполнение кода на основании значения в условии. Если условие истинно (значение true), тело оператора if выполняется, а в противном случае управление переходит к оператору, следующему после него. Оператор if . . .else. Условное выполнение кода в разделе if или else, в зависимости от истинности значения условия. Если условие истинно (значение true), выполняется тело оператора if. В противном случае (значение false) управление переходит к оператору else. Оператор?:. Условный оператор. Сокращенная форма конструкции if. . .else. Синтаксис условного оператора имеет следующий вид. условие ? выражение1 : выражение2;Если условие истинно (значение true) выполняется выражение!, а в противном случае выражение!. Оператор while. Управляющий оператор, обеспечивающий итерационное выполнение кода тела цикла, пока его условие остается истинным (значение true). В зависимости от истинности значения условия, оператор выполняется любое количество раз. Оператор return завершает выполнение функции и возвращает управление той функции, которая вызвала текущую функцию. Завершает выполнение программы и передает управление операционной системе. Оператор throw. Оператор, прерывает текущий поток выполнения. Каждый оператор throw передает объект, который переводит управление на ближайший раздел catch, способный обработать исключение данного класса. Оператор switch. Оператор множественного выбора. Оператор сначала вычисляет результат выражения, следующего за ключевым словом switch, а затем передает управление разделу case, метка которого совпадает с результатом выражения. Когда соответствующей метки нет, выполнение переходит к разделу default (если он есть) или к оператору, следующему за оператором switch, если раздела default нет. Блок catch. Часть программы, которая обрабатывает исключение. Блок обработчика состоит из ключевого слова catch, за которым следует спецификатор исключения и блок операторов. Код внутри блока catch предназначен для обработки исключений класса, указанного в его спецификаторе. Блок try. Блок операторов, начинающийся ключевым словом try и содержащий один или несколько блоков catch. Если код внутри блока try передает исключение и один из блоков catch соответствует типу переданного исключения, переданное исключение будет обработано этим обработчиком. В противном случае исключение будет передано из блока try другомуобработчику. далее по цепи обращений. При реализации РВП в С++ используется ряд сопутствующих понятий. Приведем их. Метка case. Целочисленное постоянное значение, которое следует за ключевым словом case в операторе switch. Метки case в одном операторе switch не могут иметь одинаковых значений. Если значение в условии оператора switch совпадает с одной из меток case, управление передается первому оператору после соответствующей метки. Выполнение продолжается до конца оператора switch, если не встретится оператор break. Метка default. Метка оператора switch, которая соответствует любому значению условия оператора switch, не указанному в метках case явно. Обработчик исключения. Код обработчика предназначен для реакции на исключение определенного типа, переданное из другой части программы. Синоним термина раздел catch. Помеченный оператор. Оператор, которому предшествует метка. Метка оператора – это идентификатор, сопровождаемый двоеточием. Потерянный операторelse (dangling else). Разговорный термин, используемый для описания проблемы, когда во вложенной конструкции операторов if больше, чем операторов else. В языке С++ оператор else всегда принадлежит ближайшему расположенному выше оператору if. Чтобы указать явно, какому из операторов if принадлежит конкретный оператор else, применяются фигурные скобки. Пустой оператор(null statement). Пустой оператор представляет собой отдельный символ точки с запятой. Составной оператор. Последовательность операторов, заключенная в фигурные скобки. Составной оператор может быть использован везде, где ожидается один оператор. Синоним блока. Блок.Последовательность операторов, заключенная в фигурные скобки. Блок операторов может быть использован везде, где ожидается один оператор. Синоним составного оператора. Условие. Выражение, результатом которого является логическое значение true (истина) или false (ложь). Нулевой результат арифметического выражения соответствует значению false, а любой другой — значению true. 1.5. Оператор перехода Любой оператор программы на С++ может быть снабжен меткой или несколькими метками. С помощью метки данный оператор выделяется (находится) среди других операторов. В качестве меток могут использоваться любые идентификаторы, примеры меток: M, M1, АА, М11, FINISH, START. Метка ставится перед оператором и отделяется от него двоеточием. Пусть, например, требуется меткой М2 пометить оператор присваивания X = X + 1; Это следует записать в виде М2: X = X + 1; Операторы снабжаются метками обычно для того, чтобы на них можно было передать управление с помощью оператора перехода. В С++ установлено, что операторы программы выполняются в естественной последовательности, то есть в порядке их написания слева направо и сверху вниз. Однако очень часто возникает необходимость нарушить естественный порядок выполнения операторов программы, например, пропустить группу операторов или некоторые из них выполнить повторно. Для этойцели в С++предусмотрен специальный оператор, называемый оператором перехода (его называют также оператором безусловной передачи управления). Синтаксис оператор перехода в С++: [метка:] goто константа типа метки; Ключевое слово goто пишется слитно. Управление разрешается передавать на метки только внутри данной функции. Оператор перехода обеспечивает безусловную передачу управления на оператор с указанной меткой, начиная с которого выполняется новая последовательность операторов. Пример 6.1. Требуется составить программу суммирования выражения где x = 0,534. Программа может иметь вид у = 0; i = 1; SUM: у = у + pow(x, i); i = i + 1; if i <= 10 goto SUM; Данный пример иллюстрирует применение оператора перехода для программирования циклических процессов, являющихся разновидностью разветвляющихся вычислительных процессов. Следует отметить, что обычно (чаще всего) оператор перехода используется совместно с условным оператором if для организации разветвляющихся и циклических вычислительных процессов. Пример 6.2. Описать алгоритм, представленный на рис. 6.1  Рис. 6.1. Блок-схема алгоритма примера 6.2 Фрагмент программы на языке С++, реализующий алгоритм, представлений на рис. 6.1, имеет вид: if n >= 0 goto M1; else goto M2; M1: p = n + b; s = a*a +l; x = sqrt(p + s); goto M3; M2: x = n*n – b; M3: z = x – r*r; Данный оператор – очень мощное и небезопасное средство управления поведением программы. Использовать его нужно крайне осторожно, так как, например, "прыжок" внутрь цикла (обход кодов инициализации) может привести к трудно локализуемым ошибкам. Метки локализуются в сфере действия функции. Описания и определения, после которых помещен символ "точка с запятой", считаются операторами. Перед пустым оператором также имеет право стоять метка. Метки можно размещать во всех точках программы, где синтаксис разрешает использовать операторы. Внимание: Использование оператора gotoне было одобрено разработчиками алгоритмических языков еще в 1960-х годах. Он существенно затрудняет контроль последовательности выполнения операторов программы, а также является источником ошибок при последующих модификациях. Любая программа, в которой был использован оператор goto,может быть переписана без него. Правило: Для оператора goto существует только одно правило – никогда не используйте оператор goto в своих программах! 1.6. Пустой оператор Пустым оператором называется оператор, который не вызывает никаких действий и никакими символами не обозначается. Как и любой другой оператор, пустой оператор может быть помечен. Следовательно, пустой оператор имеет вид: М: ; где М –список меток, который может отсутствовать. Пустой оператор используется для того, чтобы поместить метку в определенное место программы или зарезервировать место в программе для предполагаемых впоследствии операторов. Обычно (чаще всего) помеченный пустой оператор ставится в конце программы, чтобы в зависимости от выполнения некоторых условий можно было прервать вычисления и выйти на конец программы, блока или составного оператора, пропуская какие-то другие операторы. Пример 6.3. Составить программу для вычисления по заданные сторонам А, В, С площади треугольника S, радиусов описанной Rи вписанной r окружностей. Предусмотреть проверку существования треугольника. Решение. Алгоритм решения задачи: если треугольник существует, то есть если р > а, р > в, р > с, то  Здесь р = (а + в + с)/2 – полупериметр. Блок-схема алгоритма последовательности вычислений примера 6.3 приведена на рис. 6.2.  Рис 6.2. Блок-схема, алгоритма примера 6.3 В качестве идентификаторов сохраним обозначения, принятые при записи алгоритма за исключением R (обозначим R через RO) и r (обозначим r через RB). Программа решения задачи примера 6.3 может иметь вид */Пример 6.3*/ #include <iostream.h> #include<conio.h> #include<math.h> int main() { unsigned znak = 11111; float a, b, c, s, p, RO, RB; cout "Введите через пробел значения для a, b, c и нажмите Enter \n"; cin a >> b >> c >>$ р = (а + в + с)/2; if (p <= a || p< = b || p< = c) goto PRIZNAK; s = sqrt(p*(p-a)*(p-b)*(p-c)); RO= a+b+c; RB = s/p; cout << "Площадь треугольника s = " << s << endl; cout << "Радиус описанной окружности R = " << RO << endl; cout << " Радиус вписанной окружности r = " << RB << endl; goto FIN; PRIZNAK: cout << " Треугольник не существует znak = " << znak << endl; FIN: ; getch(); return 0; } 1.7. Условный оператор и его формы в С++ Одним из наиболее часто применяющихся операторов, которые изменяют естественный порядок следования операторов программы, является условный оператор. Условный оператор (его также называют оператором условной передачи управления) предусмотрен для описания разветвляющегося алгоритма. С помощью этого оператора можно обеспечить выполнение одного или другого оператора в зависимости от заданных условий. В С++ условный оператор имеет три формы: короткую и полную и вложенную. 1. Короткая форма – [метка:] if (E) оператор S1; Например, if (a>b) y=2*x; Если логическое выражение Е истинно, то выполняется оператор S1. 2. Полная форма – [метка:] if (E) оператор S1; else оператор S2; Например, if (x>0 && x!=10) y=2*x; else y=x*x; Если логическое выражение Е истинно, то выполняется оператор S1, иначе – оператор S1. Оператор if в полной форме часто называется оператором if-else. 3. Вложенная форма: [метка:] if (E1) оператор S1; else if (E2)оператор S2;elseоператор S3; Если логическое выражение Е1 истинно, то выполняется оператор S1, иначе, если логическое выражение Е2 истинно, то выполняется оператор S2, иначе выполняется оператор S3. Здесь Е, Е1, Е2 – условие (выражение типа сравнения или скалярное выражение); S1, S2, S3 – либо отдельный, оператор, либо группа операторов (рассмотрим далее в данной работе), либо блок (рассмотрим в последующих работах). Каждая из конструкций оператор S1 и оператор S2 должна заканчиваться точкой с запятой. Выражение Е принято называть логическим. Условие Е необходимо заключать в круглые скобки. Выражение в записи формата условного оператора – это некоторое условие, содержащее операции отношения и логические операции. В числе операторов S1 и S2 может быть и другой условный оператор. Если условие, стоящее за ключевым словом if, выполняется (истинно) то управление будет передано на оператор S1. Если же условие не выполняется (ложно), то при использовании короткой формы оператора if управление передается оператору, непосредственно следующему за условным оператором, а при использовании полной формы оператору S2 (см. рис. 6.3). | | | | | | | | | | | | | | | | | | | | | |  | | Нет | | | Нет | Оператор S2 Выполнение ветви "Нет" | Условие Е (выражение) | (Ложь) | | Условие Е (выражение) | | (Ложь) | | | | | | | | | | | | | | | | | | | | | | | | | | | Да | | | | | | Да | | | | (Истина) | | | | | | (Истина) | | | | | | | | | | | | | | Оператор S1 Выполнение ветви "Да" | | | | | | Оператор S1 Выполнение ветви "Да" | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Выполнение операторов в естественном порядке | | | | | | Выполнение операторов в естественном порядке | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | а) | | | | б) | | | | | | | | | | | Рис. 6.3. Блок-схема участка алгоритма, реализующего условный оператор: а) короткий формат; б) полный формат | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Скалярное выражение Е (условие) в операторе if задает правило вычисления логического условия, для получения которого значение Е преобразуется в строку битов. Если значение выражения равно true (истина), то выполняется оператор S1 (говорят также, что выполняется ветвь "Да"). После выполнения оператора S1 (если это не повлияет на порядок выполнения операторов) управление передается оператору, следующему за условным оператором (см. рис. 6.3). Если значение скалярного выражения Е равно false (ложь), то выполняется оператор S2 (говорят также, что выполняется ветвь "Нет"). В случае отсутствия конструкции else и в операторе if выполняется оператор, стоящий непосредственно за условным оператором (см. рис 6.3,а). После выполнения оператора S2 управление передается следующему за ним оператору, если S2 не влияет на порядок выполнения операторов. Варианты графического изображения команд ветвления представлены на рисунке 6.4.  Рис. 6.4. Команды ветвления: а) – полная форма; б) и в) – сокращенная форма. 1.7.1. Короткая форма условного оператора Условный оператор if в языке C++ позволяет вашим программам осуществлять проверку и затем на основании этой проверки выполнять операторы. Сокращенная форма записи оператора if имеет вид: if (выражение) оператор1; Например, if (a>b) y=2*x; Здесь выражение – выражение, которое может иметь арифметический тип или тип указателя; оператор1 – простые или составные операторы языка. Простой оператор – это один оператор. Составной оператор (блок операторов) – это последовательность из нескольких любых операторов, в том числе операторов описания, заключенных в фигурные скобки. Например, if (x<=5.6) { float a=2.1; y=a*sin(x); printf("%.4f\n",y) ;} Следует учитывать, что переменная, описанная в блоке, не существует вне блока. При выполнении оператора if сначала вычисляется значение выражения выражение. Если полученное значение не равно нулю (имеет значение true), то выполняется оператор1, иначе управление передаются на оператор, следующий за условным. Ниже на рис. 6.5. приведен пример программирования ветвлений с короткой формой. В примере на рис. 6.5 оператор y=a+x; является простым оператором. Обычно оператор if выполняет проверку, используя операцию сравнения C++. Если результат проверки является истиной, if выполняет оператор, который следует за ним. Следующая программа в примере 6.4 использует оператор if для сравнения значения переменной test_score со значением 90. Если набранные тестовые очки больше или равны 90, программа выведет сообщение пользователю, что он прошел тест А. В противном случае, если значение меньше 90, программа просто завершается: Пример 6.4 #include <iostream.h> int main() { int test_score = 95; if (test_score >= 90) cout << "Поздравляем, вы прошли тест! " << endl; }  | | | | | | | Да | | Нет | | | | | a > 3 | | | | y = a + x | | | | | | | | | | | | | | | | | | | | | | | | | | if (a > 3) y = a + x; | | | | | | Рис. 6.5. Короткая форма ветвления. Простой оператор | | | | | | | | | | | | | | | | Как видите, для выполнения проверки программа использует операцию сравнения C++ "больше или равно" (>=). Если результат сравнения значений является истиной, программа выполняет оператор, который следует за if, в данном случае вывод сообщения с использованием cout. Если результат сравнения не является истинным, программа не выводит сообщение. Экспериментируйте с этой программой, изменяя проверочные очки (в том числе и меньше 90), и обратите внимание на работу оператора if. 1.7.2. Полная форма условного оператора Оператор if в полной форме называется оператором if-else и имеет следующую форму записи: if (выражение ) оператор1; else опертор2; Например, if (x>0 && x!=10) y=2*x; else y=x*x; Здесь выражение – выражение, которое может иметь арифметический тип или тип указателя; оператор1, оператор2 – простые или составные операторы языка. Простой оператор – это один оператор. Составной оператор (блок операторов) – это последовательность из нескольких любых операторов, в том числе операторов описания, заключенных в фигурные скобки. Например, if (x<=5.6) { float a=2.1; y=a*sin(x); cout << "y = " << y << endl;} Следует учитывать, что переменная a, описанная в блоке, не существует вне блока. При выполнении оператора if-else сначала вычисляется значение выражения выражение. Если полученное значение не равно нулю (имеет значение true), то выполняется оператор1, иначе выполняется оператор2,а затем управление передаются на оператор, следующий за условным. Ниже на рис. 6.6 и 6.7 приведены примеры программирования ветвлений с полной и короткой формой с использованием понятий пустого, составного и простого операторов. |  | | | | | | Да | | Нет | | | | | a <= 3 | | | | | | | | y = a + x | | | | | | | | | | | | | | | | | | | | if (a <= 3) {;} else y = a + x; | | | | | | Рис. 6.6. Полная форма ветвления. Простой, пустой и составной операторы | | | | | | | | | | | | | | | В примере на рис. 6.6 оператор y= a+x;является простым оператором, а оператор {;} одновременно является пустым и составным.  | | | | | | | Да | | Нет | | | | | a <= 3 | | | | | | | | | | | | z=2+3*x; | | | | | | | | | | | | | | | | | | | | | y=sin(z); | | | | | | | | | | | | | | | | | | | | | | | | | | if (a > 2) { z=2+3*x; y=sin(z);} | | | | | | Рис. 6.7. Короткая форма ветвления. Составной оператор | | | | | | В примере на рис. 6.7 оператор {z=2+3*x; y=sin(z);}является составным. Внимание: Кроме всего прочего, примеры на рис. 6.5 и 6.6 показывают, что неполное ветвление, в котором отсутствуют команды на ветви "Да", может быть приведено к другой форме неполного ветвления путем изменения условия на противоположное (условие, противоположное условию a>3 есть условие a<=3, и наоборот). Из примера на рис. 6.6 видно, что отсутствующие команды ветви "Да" программируются с помощью пустого оператора {;}. Поясним работу полной формы оператора IF на примерах. Пример 6.5. Пусть задана такая последовательность операторов: if (а > в) а = а – 1; else а = а + 1; с = a*a; Здесь использована полная форма условного оператора, в которой в качестве оператора S1 используется оператор а = а - 1; а в качестве S2 – оператор а = а + 1; При выполнении условного оператора if сначала проверяется условие (а > в) (то есть вычисляется значение выражения а > в ). Если а > в (то есть значение выражения равно (истинно), то выполняется ветвь "Да", то есть выполняется оператор a = a -1; а else-ветвь пропускается, то есть оператор а = а + 1; не выполняется. Другими словами, в случае истинности выражения а > в для заданного фрагмента программы будет выполнена последовательность операторов а = а - 1; с = а*a; . В противном случае (то есть значение выражения а> b ложно) пропускается ветвь "Да" (то есть оператор а = а - 1; не выполняется) и сразу выполняется else-ветвь, то есть будет выполнен оператор а = а + 1;. Таким образом, в случае ложности выражения а > в для заданного фрагмента программы будет выполнена последовательность операторов а = а + 1; с = а *a; . Пример 6.6 Пусть задана последовательность операторов: x = 1; s = 0; start: s = s + x*x; x = x + 2; if x < 1000 goto START ; В приведенном примере использована короткая форма условного оператора, то есть конструкция else опущена. Здесь в условном операторе в качестве оператора S1 используется оператор goto. Он будет выполняться (заставлять при этом программу возвращаться к оператору с меткой START ) только тогда, когда значение переменной x не превосходит 1000. Таким образом, этот фрагмент программы обеспечит подсчет суммы квадратов последовательности нечетных чисел от 1 до 999. Отметим, что в качестве операторов S1 или S2 в условном операторе могут быть, в частности, пустые операторы (выполнение их не вызывает никаких действия, а запись состоит только из разделителя ; goto). То есть возможны конструкции оператора if if (E) ; else S2; if и (Е) S1; else ; Например, if (a = b) ; else x = x +2; if и (Е) S1; else ; Любой оператор, входящий в состав условного оператора (S1 и S2), может быть помечен, - и к нему возможен переход из другого места функции. Независимо от способа передачи управления на операторы S1 и S2 порядок выполнения условного оператора сохраняется. Пример 6.7. Задана последовательность операторов: if (x = у) M1: a = 1; else M2: a = 0; В данном примере в качестве оператора S1в конструкции if использован оператор а = 1; помеченный меткой Ml, а в качестве оператора S2 - оператор а = 0;, помеченный меткой М2. Как на оператор а = 1;, так и на оператор а = 0; можно передать управление из другого места программы, например, с помощью оператора goто. Но независимо, на какой из операторов, а = 1; или а =0; передано управление, вначале проверяется условие x = у, и затем в случае истинности условия выполняется ветвь "Да", а в случае ложности условия - ветвь "Нет". Например, передали управление на оператор с меткой Ml и при этом в процессе вычислений оказалось, что x = у, то переменной а будет присвоено значение ноль (а = 0;), хотя мы и передали управление на оператор, присваивающий переменной а значение 1 (а = 1;). Пример 6.8. Следующая программа использует оператор if, чтобы проверить, больше тестовые очки или равны 90. Если условие истинно, программа выводит поздравление. Если условие ложно, программа сообщает, что студент должен работать усерднее: #include <iostream.h> int main() { int test_score =95; if (test_score >= 90) cout << "Поздравляю, вы прошли тест" << endl; else cout << "В следующий раз вы должны" << " работать усерднее!" << endl; } 1.8. Программирование простых РВП средствами языка С++ Программирование простых разветвляющихся вычислительных процессов, содержащих в зависимости от условия одну или две ветви вычислений, осуществляется с использованием полной формы условного оператора ifили совместным использованием короткой формы условного оператора ifи оператора перехода goто. Программирование простых разветвляющихся вычислительных процессов рассмотрим на конкретных примерах. Пример 6.9. Вычислить значение р, исходя из следующих условий:  Фрагмент программы на C++ реализующий вычисление значения р с использованием полной формы условного оператора if, будет иметь вид if (x >= 0) p = (x + у)/cos(z); else p = 1/(sin(z) + y); Пример 6.10. Вычислить значение функции  Вычисление функции может быть реализовано с помесью операторов if (x >= 0 && x<=2) gx = 0; else gx = x*x – 2*x; Пример 6.11. Вычислить значение функции, график которой изображен на рис. 6.4.  Рис. 6.4. График функции y = f(x) Функции, заданные графически, целесообразно описать аналитически, так как это во многом облегчит описание поведения функции средствами языка С++. Для нашего примера поведение функции аналитически описывается следующим образом  Вычисление рассматриваемой функции может быть реализовано с помощью операторов if (x <= 0) y = 0; else y = x; или if (x > 0) y = x; else y = 0; Вычисление этой функции можно осуществить с использованием и короткой формы условного оператора y = 0; if (x > 0) y = x; Примеры на совместное использование короткой формы условного оператора if и оператора перехода goto были рассмотрев ранее (см. примеры 6.1, 6.5, 6.7 ). 1.9. Понятие составного оператора (группы операторов) Как уже отмечалось в лабораторной работе № 5 операторы в алгоритмических языках делятся на простые и составные. Простой оператор не содержит каких-либо других операторов. Составной оператор – это группа операторов, в которую включаются простые и другие составные операторы. Когда программа выполняет только один оператор, следующий за if, такой оператор называется простым оператором: // Простой оператор if (test_score >= 90) cout << "Поздравляем, вы прошли тест!" << endl; Если программе необходимо выполнить несколько инструкций, когда результат сравнения – истина, операторы должны быть сгруппированы внутри левой и правой фигурных скобок {}. Операторы, которые находятся внутри фигурных скобок, образуют составной оператор, как показано ниже: //Составной оператор if (test_score >= 90) { cout << "Поздравляем, вы прошли тест!" << endl; cout << "Вы набрали " << test_Score << " баллов" << endl; } Составной оператор служит для объединения группы операторов, которую по смыслу алгоритма следует рассматривать в программе как единый оператор. Для объединения группы операторов в составной оператор их необходимо заключить в фигурные скобки { }. Его формат { S1; S2; ……. Sn; } Здесь Si; – произвольный оператор, в том числе и составной. Выполнение составного оператора заключается в последовательном выполнении составляющих его операторов. Операторы S1, S2, …, Sn, входящие в составной, могут быть по- мечены. Эти метки, естественно, могут содержаться в имеющихся в про- грамме операторах перехода. Таким образом; извне группы разрешена передача на любой внутренний оператор группы. Если осуществляется пере- дача управления на помеченный оператор, входящий в составной, то выполнение последнего уже начинается не с первого оператора группы (то есть S1). ас оператора, на который было передано управление. Заканчивается выполнение составного оператора обычно последним простым оператором Sn. Однако, если среди операторов S1, S2, …, Sn есть операторы передачи управления, то выход из составного оператора будет осуществляться по соответствующему оператору перехода. Например, в составной оператор { x = 2; M1: y = 3; goto M2; M3: z = 5; } если ему предшествует оператор goto M1; вход осуществляется через метку M1,а выход на метку M2, без выполнения оператора с меткой M3. Для передачи управления на конец группы необход |