
- •«Технология программирования» методические указания
- •Самара 2007
- •Лабораторная работа разветвляющиеся программы. Циклы
- •1. Сведения из теории
- •1.1 Базовые конструкции структурного программирования
- •1.1.2 Оператор «выражение»
- •1.1.3 Операторы ветвления
- •1.1.4 Оператор switch
- •2. Программа выполнения работы
- •2.1 Разветвляющиеся программы
- •2.1.1 Задача 1. Вычисление значения функции, заданной графически
- •2.2 Циклы
- •Контрольные вопросы
1.1.4 Оператор switch
Оператор switch (переключатель) предназначен для разветвления процесса вычислений на несколько направлений. Структурная схема оператора приведена на рис. 1.7. Формат оператора:
switch ( выражение )
{
case константное_выражение_1: [список_операторов_1]
case константное_выражение_2: [список_операторов_2]
…
case константное_выражение_n: [список_операторов_n]
[default: операторы ]
}
Рис. 1.7- Структурная схема оператора switch
Выполнение оператора начинается с вычисления выражения (оно должно быть целочисленным), а затем управление передается первому оператору из списка, помеченного константным выражением, значение которого совпало с вычисленным. После этого, если выход из переключателя явно не указан, последовательно выполняются все остальные ветви.
Выход из переключателя обычно выполняется с помощью операторов break или return. Оператор break выполняет выход из самого внутреннего из объемлющих его операторов switch, for, while и do. Оператор return выполняет выход из функции, в теле которой он записан.
Все константные выражения должны иметь разные значения, но быть одного и того же целочисленного типа. Несколько меток могут следовать подряд. Если совпадения не произошло, выполняются операторы, расположенные после слова default (а при его отсутствии управление передается следующему за switch оператору).
Пример (программа реализует простейший калькулятор на 4 действия):
#include <iostream.h>
int main()
{
int a, b, res;
char op;
cout << "\nВведите 1й операнд : "; cin >> а;
cout << "\nВведите знак операции : ": cin >> op;
cout << "\nВведите 2й операнд : "; cin >> b;
bool f = true;
switch (op)
{
case '+': res = a + b; break;
case '-': res = a - b; break;
case '*': res = a * b; break;
case '/': res = a / b; break;
default : cout <<"\nНеизвестная операция": f = false;
}
if (f) cout << "\nРезультат : " << res;
return 0;
}
ПРИМЕЧАНИЕ: В случае синтаксической ошибки в слове default сообщение об ошибке не выдается, поскольку компилятор воспримет это слово как допустимую метку оператора.
Другие примеры программ, содержащих проверки условий, приведены в практикуме [11] на с. 30.
2. Программа выполнения работы
2.1 Разветвляющиеся программы
В линейной программе все операторы выполняются последовательно, один за другим. Для того чтобы в зависимости от исходных данных обеспечить выполнение разных последовательностей операторов, применяются операторы ветвления if и switch. Оператор if обеспечивает передачу управления на одну из двух ветвей вычислений, а оператор switch - на одну из произвольного числа ветвей. Рассмотрим сначала задачи с применением оператора if.
2.1.1 Задача 1. Вычисление значения функции, заданной графически
Написать программу, которая по введенному значению аргумента вычисляет значение функции, заданной в виде графика (рис. 1).
Рис. 1-Функция для задачи 1
Начинать решение даже простейшей задачи необходимо с четкого описания того, что является ее исходными данными и результатами. В данном случае это очевидно: исходными данными является вещественное значение аргумента х, который определен на всей числовой оси, а результатом — вещественное значение функции у.
Перед написанием программы следует составить алгоритм ее решения — сначала в общем виде, а затем постепенно детализируя каждый шаг. Такой способ, называемый «нисходящая разработка», позволяет создавать простые по структуре программы. По мере приобретения опыта вы убедитесь, насколько это важно. Как известно, алгоритм решения задачи можно описать в различном виде, например, в словесном или в виде блок-схемы. А нам удобнее будет для начала записать функцию в виде формул:
Ниже приведено описание алгоритма в неформальной словесной форме. Этот способ мы всячески рекомендуем, потому что только после того, как задача четко описана на естественном языке, ее можно успешно записать на языке программирования. Для такой простой задачи, как рассматриваемая, это, быть может, и не имеет смысла, но вы ведь не собираетесь всю жизнь писать только элементарные программы!
Ввести значение аргумента х.
Определить, какому интервалу из области определения функции оно принадлежит.
Вычислить значение функции у по соответствующей формуле.
Вывести значение у.
Детализировать этот алгоритм уже практически некуда, поэтому сразу же смело напишем первый вариант программы:
#include <iostream.h>
int main()
{
float x, y;
cout <<" Введите значение аргумента" << endl;
cin >> 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;
cout << " Для x = " << x << " значение функции у = " << у << endl;
return 0;
}
Тестовые примеры для этой программы должны включать по крайней мере по одному значению аргумента из каждого интервала, а для проверки граничных условий — еще и все точки перегиба (если это кажется вам излишним, попробуйте в последнем условии «забыть» знак =, а затем ввести значение х, равное 2).
Как видно из программы, с помощью последовательности условных операторов практически «один в один» записана математическая форма описания функции, приведенная выше. Обратите внимание на запись условий, содержащих два сравнения.
Операции отношения (<, >, = =, ≤ ≥, !=) являются бинарными, то есть имеют два операнда, и формируют результат типа bool, равный true или false1. Поскольку необходимо, чтобы эти условия выполнялись одновременно, они объединены с помощью операции логического И (&&) — не путать с поразрядным И! Приоритет у операции И ниже, чем у операций отношения, поэтому заключать их в скобки не требуется.
Весьма распространенная ошибка начинающих — запись подобных условий в виде кальки с математической формулы, то есть как а<b<с. Синтаксической ошибки в этом выражении нет, поэтому компилятор не выдает каких-либо сообщений. Давайте посмотрим, что же происходит при вычислении. Операции отношения одного приоритета выполняются слева направо, поэтому сначала будет выполнена операция а<b и сформирован результат в виде true или false. Следующая операция будет выглядеть как true<c или false<c. Для ее выполнения значения true и false преобразуются соответственно в единицу и ноль того же типа, что и с, и формируется результат, смысл которого вряд ли соответствует ожиданиям.
При работе приведенной выше программы всегда выполняются один за другим все пять условных операторов, при этом истинным оказывается только одно условное выражение и, соответственно, присваивание значения переменной у выполняется один раз. Запишем условные операторы так, чтобы уменьшить количество проверок:
If ( х <= -2 ) y = 0;
else If ( х < -1 ) у = -х - 2;
else if ( х < 1 ) у = х;
else If ( х < 2 ) у = -х + 2;
else у = 0;
Проверка на принадлежность аргумента очередному интервалу выполняется только в том случае, если х не входит в предыдущий интервал. Программа получилась более компактной, более эффективной, но, возможно, менее наглядной. В отличие от предыдущей версии, порядок следования условных операторов имеет здесь важное значение. Рассмотрим еще один вариант:
y = 0;
if ( х > -2 ) у = -х – 2;
If ( х > -1 ) у = х;
if ( х > 1 ) у = -х + 2;
if ( х > 2 ) у = 0;
Запись фрагмента стала еще короче, но появились два недостатка: значение функции вычисляется многократно (от двух до пяти раз в зависимости от интервала, которому принадлежит х), значит, увеличилось время выполнения, а главное — программа потеряла универсальность, то есть таким способом можно вычислить не всякую функцию. Для того чтобы в этом убедиться, попробуйте заменить у=х на, к примеру, фрагмент окружности y=sqrt(l-x*x) и ввести значение х, большее 1 — это приведет к ошибке в программе, связанной с вычислением квадратного корня из отрицательной величины.
Какой же вариант лучше? Для решения данной задачи разница между ними несущественна, но наша цель состоит в том, чтобы на простых примерах продемонстрировать общие принципы, следование которым позволит вам впоследствии создавать надежные и красивые программы.
СОВЕТ: В современной иерархии критериев качества программы на первом месте стоят ее надежность, простота поддержки и модификации, а эффективность и компактность отходят на второй план. Поэтому в общем случае, если нет специальных требований к быстродействию, наиболее наглядный вариант предпочтительнее.
Нам кажется, что наиболее наглядным является самый первый вариант программы, поскольку по нему проще проследить логику ее работы.
В заключение приведем вариант с использованием функций ввода-вывода в стиле С:
#include <stdio.h>
int main(){
float х, у;
printf(“ Введите значение аргумента:\n");
scanf(“%f", &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 ) y = 0;
printf(“ Для x = %5.2f значение функции у = %5.2f\n", x, у);
return 0;
}