Для программирования ветвящихся алгоритмов в языке Си имеется несколько различных средств. К ним относятся операция условия ?:, условный оператор if , оператор безусловного перехода goto и оператор выбора switch.
Примечание
Условная операция ?: . В формуле
y = x ? a: b;
y = a, если x не равно нулю (т.е. истинно), и y = b, если х равно нулю (ложно). Следующее выражение
y = (a>b) ? a: b;
позволяет присвоить переменной у значение большей переменной (а или b), т.е. y = max(a, b).
Условный оператор.
Формат условного оператора следующий:
if (выражение) оператор1; else оператор2;
Это полная форма оператора, программирующая структуру полного ветвления. Обычно выражение — это некоторое условие, содержащее операции отношения и логические операции. Значение выражения приводится к целому и интерпретируется в соответствии с правилом: равно нулю - ложь, не равно нулю - истина. Если выражение истинно, выполняется оператор 1, если ложно — оператор2.
Необходимо обратить внимание на следующие особенности синтаксиса условного оператора:
• выражение записывается в круглых скобках;
• точка с запятой после оператора 1 ставится обязательно.
Возможно использование неполной формы условного оператора
if (выражение) оператор;
Вот пример использования полной формы условного оператора для нахождения большего значения из двух переменных а и b:
if(a>b) max=a; elsemax=b;
Та же самая задача может быть решена с использованием неполного ветвления следующим образом:
max=a; if(b>a) max=b;
Напомним, что эту же задачу можно решить с помощью операции «условие».
Пример проверки не одного, а нескольких условий сразу
char ZNAC;
int x,y,z;
if (ZNAC = '-') x = y - z;
else if (ZNAC == '+') x = y + z;
else if (ZNAC == '*') x = y * z;
else if (ZNAC == '/') x = y / z;
else ...
Теперь рассмотрим примеры программирования вложенных ветвящихся структур. Требуется вычислить функцию sign(x) — знак х, которая определена следующим образом:
-1, если х < О,
sign(x) = { 0, если х = О,
1, если х > 0.
Пример 1.Алгоритм с полными вложенными ветвлениями:
if(х<=0)
if(x==0) y=0;
else y=-l; else y=l;
Пример2. Алгоритм с неполным ветвлением:
у=1;
if(x<=0)
if(x==0) y=0;
else y=-l;
Пример3. Упорядочить по возрастанию значения в двух переменных я, Ь:
if(a>b)
{с=а; a=b; b=c;}
cout<<”a=”<<a<<”b=”<<b;
В данном примере использован составной оператор — последовательность операторов, заключенная в фигурные скобки. В Си фигурные скобки выполняют роль операторных скобок по аналогии с Begin, End в Паскале.
Обратите внимание на то, что перед закрывающей фигурной скобкой точку с запятой надо ставить обязательно, а после скобки точка с запятой не ставится.
В следующем примере вернемся к задаче вычисления площади треугольника по длинам трех сторон. Добавим в программу проверку условия правильности исходных данных: а, Ъ, с должны быть положительными, а сумма длин каждой пары сторон треугольника должна быть больше длины третьей стороны (аналогичную программу на Паскале см. в разд. 3.10, пример 1).
Пример 4.
// Площадь треугольника
if include <iostream.h>
#include <math.h>
void main()
{float a,b,c,p,s;
cоut«"\na = "; cin»a;
соut<<"\nb="; сin»b;
соut<<"\11с="; сin»с;
if(a>0 && b>0 && с>0 && a+b>c && a+c>b && b+c>a)
{ p=(a+b+c)/2;
s = sqrt(p*(p-a)*(p-b)*(p-c)} ;
cout<<”\nПолщадь треугольника="<<s;
}
else cout(“\n Неверные сходные данные.”);
}
Оператор выбора (переключатель).
Формат оператора выбора:
switch(целочисленное_выражение)
{ caseконстанта1: список_операторов;
caseконстанта2: список_операторов;
. . . . . . . . . . . . . . . . . . . . .
default:список_операторов;
}
Последняя строка (default) может отсутствовать. Выполнение оператора происходит в следующем порядке:
1. Вычисляется выражение.
2. Полученное значение последовательно сравнивается с константами, помещенными после служебного слова case; при первом совпадении значений выполняются операторы, стоящие после двоеточия.
3. Если ни с одной из констант совпадения не произошло, то выполнятся операторы после слова default.
Для того чтобы «обойти» выполнение операторов на последующих ветвях, нужно принять специальные меры, используя операторы выхода или перехода.
Рассмотрим фрагмент программы, который переводит числовую оценку знаний ученика в ее словесный эквивалент. Согласно вузовской системе: 5 — «отлично», 4 — «хорошо», 3 — «удовлетворительно», 2 — «неудовлетворительно».
Здесь используется еще один новый для нас оператор break -— оператор выхода. Его исполнение завершает работу оператора выбора, т.е. происходит «обход» других ветвей. Вот два варианта результатов выполнения этой программы:
Введите оценку: 3 Это удовлетворительно!
Введите оценку: 7 Нет такой оценки!
Если на всех ветвях убрать оператор break, то результат может выглядеть следующим образом:
Введите оценку: 3 Это удовлетворительно! Это хорошо! Это отлично! Нет такой оценки!
В этом случае выполнились операторы на всех ветвях, начиная с той, которая помечена константой 3.
Возможны задачи, в которых такой порядок выполнения ветвей оператора выбора может оказаться полезным. В следующем фрагменте программы происходит возведение вещественного числа х в целую степень n, где п изменяется в диапазоне от 1 до 5.
у=1.0;
Switch(n)
case 5:y=y*x;
case 4:y=y*x;
case 3:y=y*x;
case 2:y=y*x;
case 1:y=y*x; cout<<”y=<<”y; break;
default: cout<<”стeпeнь больше 5";
Язык Си может использовать следующие безусловные переходы или прерывания: break, continue и goto. Их использование в основном совпадает с использованием в Паскаль, а именно: break прерывает исполнение любого вида циклов, continue - завершает текущую итерацию цикла, goto - осуществляет переход по метке. В отличие от языка Паскаль, break может использоваться в Си для завершения выбора. Использование оператора goto в языке Си считается нежелательным. Метки специально не объявляются.
Пример
switch (ZNAC)
{
case -:
x=y-z;
break;
case +:
x=y+z;
break;
case *:
x=y*z;
break;
case /:
x=y/z;
break;
default:
cout<<А куркулятор у меня только арифметический! Чего это вы тут такое левое нажимаете?;
break;
}
А теперь разбираемся.
Сразу после оператора switch идет в круглых скобках имя переменной, которая проверяется на соответствие определенному значению (в этих скобках может стоять и выражение). Так называемое управляющее выражение. Т.е. условие, которое для оператора if записывается в скобках (например, ZNAC=-) как бы делится на 2 части: первая остается в скобках после оператора switch, вторая (значение) выносится ниже и устанавливается после ключевого слова case. Знак сравнения (не любой, а только конкретно - знак равенства) подразумевается сам по себе, так как он один и других зесь просто быть не может.
Внимание!
В Си в структуре множественного выбора можно использовать (т.е. подразумевать, как мы выяснили выше) ТОЛЬКО оператор сравнения =. Никакие другие операторы сравнения использоваться не могут!
С первой строчкой разобрались. Дальше - case. Расшифровывается так: в случае, если указанные после switch в скобках переменная или выражение принимают такое значение, как указанные case, то начинают выполняться операторы, следующие после этого же case, если нет - мы переходим к другому случаю, к другому case. Если среди всех описанных нами случаев нет ни одного, соответствующего текущему значению проверяемой переменной или выражениия, переходим к служебному слову default. В этом случае начинают выполняться операторы, находящиеся после него. Собственно, этого служебного слова в данной конструкции может и не быть - оно не обязательно, но считается правильным все же описывать ситуации, которые вы не предвидели в case. Кроме того, default не обязательно должен располагаться в самом конце рассматриваемой структуры, но рекомендуется все-таки располагать его именно там - как-то логически более на месте. Но если вам все-таки очень захотелось втиснуть его куда-нибудь посередине, не забудьте после операторов, описывающих действия по умолчанию поставить break.
Зачем – смотрим следующий абзац.
Теперь рассмотрим оператор break. Когда выполняется этот оператор, следущие за ним строки не выполняются, программа выходит из блока структуры и начинает выполняться оператор, следующий сразу после данного блока. Простым языком говоря: если представлять блок структуры, как контейнер (что собственно так и есть), как только встретили break, из контейнера выбрались и пошли дальше по коду.
Оператор break здесь необходим после операторов действия для каждого случая, кроме самого последнего (обычно это действия по умолчанию), т.к. в последнем случае программа по любому выходит из структуры switch. Но если вы и в этом случае поставите, оператор break, ошибкой это являться не будет.