Новости
Главная / Студентам / ОАиП / Лекция 5. Программирование ветвлений

Лекция 5. Программирование ветвлений

Операторы ветвления позволяют изменить порядок выполнения операторов в программе. К операторам ветвления относятся условный оператор if и оператор выбора switch.

1. Условный оператор if

Условный оператор if используется для разветвления процесса обработки данных на два направления. Он может иметь одну из форм: сокращенную или полную.

1.1 Форма сокращенного оператора if:

if (B)  S;

где В — логическое или арифметическое выражение, истинность которого проверяется; S — оператор: простой или составной.

При выполнении сокращенной формы оператора if сначала вычисляется выражение B, затем проводится анализ его результата: если B истинно, то выполняется оператор S; если B ложно, то оператор S пропускается. Таким образом, с помощью сокращенной формы оператора if можно либо выполнить оператор S, либо пропустить его.

1.2 Форма полного оператора if:

if (B) S1; else S2;

где B — логическое или арифметическое выражение, истинность которого проверяется; S1, S2- оператор: простой или составной.

При выполнении полной формы оператора if сначала вычисляется выражение B, затем анализируется его результат: если B истинно, то выполняется оператор S1, а оператор S2 пропускается; если B ложно, то выполняется оператор S2, а S1 — пропускается. Таким образом, с помощью полной формы оператора if можно выбрать одно из двух альтернативных действий процесса обработки данных.

Рассмотрим несколько примеров записи условного оператора if:

if (a > 0) x=y;               // Сокращенная форма c простым оператором
if (++i) {x=y; y=2*z;}               // Сокращенная форма c составным оператором
if (a > 0 || b<0) x=y; else  x=z;   // Полная форма с простым оператором
if (i+j-1) { x= 0; y= 1;} else {x=1; y:=0;}           // Полная форма с составными операторами

Рассмотрим пример использования условного оператора.

static void Main()
{
  Console.Write("x= ");
  float x = float.Parse(Console.ReadLine());
            Console.Write("y=");
  float y = float.Parse(Console.ReadLine());
  if (x < y ) Console.WriteLine("min= "+x);
  else Console.WriteLine("min= "+y);
}

Результат работы программы:

x          y          min
0          0          0
1          -1         -1
-2         2          -2

Задание. Измените программу так, чтобы вычислялось наибольшее значение из х и у.

Операторы S1 и S2 могут также являться операторами if. Такие операторы называют вложенными. При этом ключевое слово else связывается с ближайшим предыдущим словом if, которое еще не связано ни с одним else. Рассмотрим пример программы, использующей вложенные условные операторы.

Пример: Дана мишень.

Подсчитать количество очков после выстрела по данной мишени.

static void Main()
{
  int Ball=0;
  Console.Write("x= ");
  float x = float.Parse(Console.ReadLine());
  Console.Write("y= ");
  float y = float.Parse(Console.ReadLine());
  if (x * x + y * y <=1) Ball = 10;           //окружность с радиусом 1
  else  if (x * x + y * y <= 4) Ball = 5;     //окружность с радиусом 2
  Console.WriteLine("Ball= "+ Ball);
}

Результат работы программы:

x          y          Ball
0          0          10
1          -1         5
-2         2          0

Задание. Измените программу так, чтобы подсчитывалось количество очков для мишени вида

2. Оператор выбора switch

Оператор выбора switch предназначен для разветвления процесса вычислений по нескольким направлениям. Формат оператора:

switch ( <выражение> )
{
  case <константное_выражение_1>: 
   [<оператор 1>];  <оператор перехода>;
  case <константное_выражение_2>: 
   [<оператор 2>]; <оператор перехода>; 
  ...
  case <константное_выражение_n>: 
   [<оператор n>]; <оператор перехода>;
   [default: <оператор>; ] 
}

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

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

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

Пример. По заданному виду арифметической операции (сложение, вычитание, умножение и деление) и двум операндам, вывести на экран результат применения данной операции к операндам.

static void Main()
{
  Console.Write("OPER= ");
  char oper=char.Parse(Console.ReadLine());
  bool ok=true;
  Console.Write("A= ");
  int a=int.Parse(Console.ReadLine());
  Console.Write("B= ");            
  int b=int.Parse(Console.ReadLine());
  float res=0;
  switch (oper)
  {
    case '+': res = a + b; break;     //1
    case '-': res = a - b; break;
    case '*': res = a * b; break;
    case ':': if (b != 0)
    { 
      res = (float)a / b; break;
    }
    else goto default;
    default: ok = false; break;    
  }
  if (ok) Console.WriteLine("{0} {1} {2} = {3}", a, oper, b, res);
  else Console.WriteLine("error");
}

Результат выполнения программы:

oper     x          y          rez
+        4          5          9
:        4          0          error
%        4          3          error

Задания.

  1. Замените в строке 1 оператор break, на оператор goto case ‘-‘ и посмотрите, что произойдет, если в качестве операции ввести +.
  2. В условном операторе if уберите ветку else и посмотрите, что произойдет.

Если необходимо, чтобы для разных меток выполнялось одно и тоже действие, то метки перечисляются через двоеточие. Например:

switch (oper)
{
  case '+': res = a + b; break;  
  case '-': res = a - b; break;
  case '*': res = a * b; break;
  case '/': case ':': if (b != 0)  // перечисление меток
  {
    res = (float)a / b; break;
  }
  else goto default;
  default: ok = false; break;
}

Цикл for

Цикл for используется для организации циклов — повторения каких-либо однородных действий. Например, если вам нужно посчитать сумму чисел от 1 до 10, то вы должны сложить 1 и 2, полученную сумму сложить с 3, полученную сумму сложить с 4 и так далее, пока не получим сумму предыдущих чисел с 10. В итоге получили последовательность повторяющихся действий: к сумме предыдущих чисел прибавляем следующее число. Вот для организации таких действий и используются циклы, в частности цикл for.

Вот общий вид цикла for:

            for (начальная_инструкция; условие; выражение)
            {
                        инструкции;
            }

Семантика (смысл) цикла for такова, что сначала выполняется начальная_инструкция; она инициализует переменную, используемую в цикле. Затем проверяется условие. Если оно истинно, то выполняются инструкции, вычисляется выражение, и управление передается обратно в начало цикла for с той разницей, что начальная_инструкция уже не выполняется. Это продолжается до тех пор, пока условие не станет ложно, после чего управление передается следующей_инструкции. Каждый проход цикла называется итерацией цикла.

Начальной_инструкцией может быть инструкция-выражение или просто объявление.

Цикл for является итерационной инструкцией, используемой обычно с увеличивающейся или уменьшающейся переменной. Например, в следующем коде инструкция for используется для сложения целых чисел от 1 до 10.

sum = 0;
for (i = 1; i <= 10; ++i)
sum += i;

Когда инструкция for начинает выполняться, управляющей переменной i задается начальное значение 1. Затем проверяется условие продолжения цикла i <= 10. Поскольку начальное значение i равно 1, это условие удовлетворяется, так что оператор тела инструкции суммирует к значению переменной sum, равному 0, значение счетчика i, равное 1. Затем управляющая переменная i увеличивается на единицу в выражении ++i и цикл опять начинается с проверки условия его продолжения. Поскольку значение i теперь 2, предельная величина не превышена, так что программа снова выполняет тело цикла. Этот процесс продолжается, пока управляющая переменная i не увеличится до 11 — это приведет к тому, что условие продолжения цикла нарушится и повторение прекратится. Выполнение программы продолжится с первого оператора, расположенного после цикла for.

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

for (sum = 0,i = 1; i <= 10; ++i)
            sum += i;

Основное назначение использования оператора запятая — помочь программисту использовать несколько выражений задания начальных значений и (или) несколько выражений приращения переменных. Например, в одной структуре for может быть несколько управляющих переменных, которым надо задавать начальное значение и которые надо изменять. Например:

for(i=0,j=0;i<3,j<`4;i++,j+=2)
cout<<i*j;

Данный цикл проведет две итерации, после которых значение счетчика i станет равным 2, а значение счетчика j = 4. При этом условие для второго счетчик не выполняется (т.к. j строго должен быть меньше 4) и цикл будет прерван. На экране будет выведено 02.

В цикле for может присутствовать локальное объявление переменной управления циклом, как в следующем примере.

for (int i = 0; i < N; ++i)
            sum += i*i;

Целая переменная i теперь является объявленной в программе. Это может вносить путаницу, поэтому лучше объявлять все программные переменные в начале блока.

В большинстве случаев инструкцию for можно представить при помощи инструкции while:

начальная_инструкция;
while (условие) {
            инструкция;
            выражение;
            }
следующая_инструкция;

Любое или все выражения в инструкции for могут отсутствовать, но две точки с запятой должны быть обязательно. Если пропущена начальная_инструкция, то никакая инициализация в цикле for не выполняется. Если пропущено выражение, то не производится приращение, а в случае отсутствия условия не производится проверка. Есть специальное правило для тех случаев, когда пропущено условие; в такой ситуации компилятор будет считать условие выполненным всегда. Так, цикл for в следующем фрагменте бесконечен.

for (i = 1, sum = 0 ; ; sum += i++ )
            cout << sum << endl;

Размещение точки с запятой сразу после правой закрывающей скобки заголовка for делает тело структуры пустым оператором. Обычно это логическая ошибка.

“Приращение” инструкции for может быть отрицательным (в этом случае в действительности происходит не приращение, а уменьшение переменной, управляющей циклом).

Если условие продолжения цикла с самого начала не удовлетворяется, то операторы тела инструкции for не выполняются и управление передается оператору, следующему за for.

Управляющая переменная иногда печатается или используется в вычислениях в теле инструкции for, но обычно это делается без изменений ее величины. Чаще управляющая переменная используется только для контроля числа повторений и никогда не упоминается в теле инструкции.

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

Давайте рассмотрим несколько вариантов применения цикла for:

а) Изменение управляющей переменной от 1 до 100 с шагом 1.

for (int i = 1; i <= 100; i++)

b) Изменение управляющей переменной от 100 до 1 с шагом -1 (с уменьшением на 1).

for (int i = 100; i >= 1; i—)

Распространенная ошибка при программировании, это использование несоответствующей операции отношения в условии продолжения цикла при счете циклов сверху вниз (например, использование i <= 1 при счете циклов сверху до 1 не включая).

c) Изменение управляющей переменной от 7 до 77 с шагом 7.

for (int i = 0; i <= 77; i += 7)

d) Изменение управляющей переменной от 20 до 2 с шагом -2.

for (int i = 20; i >= 2; i -= 2)

e) Изменение управляющей переменной в следующей последовательности:

2, 5, 8, 11, 14.
for (int j = 2;j <= 14; j += 3)

f) Изменение управляющей переменной в следующей последовательности:

99, 88, 77, 66, 55, 44, 33, 22, 11, 0.
for (int j = 99; j >= 0; j -= 11)

Цикл while.

Обобщенная форма цикла while:

while ( выражение ) оператор;

Вначале вычисляется выражение. Если результат отличен от нуля (true), тогда выполняется оператор и управление переходит обратно к началу цикла while. Это приводит к выполнению тела цикла while, а именно оператора, который будет выполняться до тех пор, пока выражение не станет равным нулю (false). Затем управление передается следующему оператору. Таким образом, цикл может выполняться ноль или более раз. Например:

/* Пример выводит на экрон 5 строк типа «Строка» + «индекс» + «выводится в цикле», где «индекс» меняется от 0 до 4 */ 

#include < iostream.h >
void main()
{
int i = 0; /*Объявление и инициализация переменной i*/ 
cout << «\n Начало цикла»; 
while (i != 5) /*Проверяется выражение (i != 5),
если результат — истина, выполняется операторы тела цикла,
в противном случае управление передается оператору, следующему за циклом. */
{
cout << «Строка » << i << «выводится в цикле \n»;
i++;
}
cout << «\n Оператор, следующий за циклом»;

Чтобы материал стал более понятным рассмотрим еще такой пример:

/*Программа выводит на экран данные таблицы умножения на 2*/
#include < iostream.h >
void main()
{
int i = 0;
cout << «Таблица умножения на 2 \n»;
while ( i ++ < 10)
cout << i << » * 2 = » << i * 2 << ‘\n’;
cout << «\n Все»;

Давайте остановимся на операторе while в данном примере и по шагам посмотрим, как он работает.

while ( i ++ < 10)
cout << i << » * 2 = » << i * 2 << ‘\n’;

Цикл состоит из двух частей: условие цикла и тело цикла. Обратите внимание на условие цикла — это выражение i++ < 10 . Условие гласит, что тело цикла будет выполняться пока выполняется условие i < 10 . ПОСЛЕ проверки этого условия значение переменной i увеличивается на 1 (об этом говорит оператор i++). Тело цикла состоит всего из одного оператора, а именно:

cout << i << » * 2 = » << i * 2 << ‘\n’;

Итак, 1-й шаг цикла

1.1 Значение переменной i равно 0 (так она была проинициализирована).
1.2 Проверка условия i < 10 дает истина (т.к. 0 < 10)
1.3 Значение переменной i увеличивается на 1, теперь i = 1.
1.4 Так как проверка условия цикла дала значение истина управление передается оператору тела цикла, т.е. на экран выводится строка 1 * 2 = 2
1.5 Далее управление передается циклу while

2-й шаг цикла

2.1 Значение переменной i равно 1.
2.2 Результат проверки условия цикла — истина (1 < 10)
2.3 Значение переменной i увеличивается на 1, теперь i = 2.
2.4 Так как проверка условия цикла дала значение истина управление передается оператору тела цикла, т.е. на экран выводится строка 2 * 2 = 4
2.5 Далее управление передается циклу while

9-й шаг цикла

9.1 Значение переменной i равно 8.
9.2 Результат проверки условия цикла — истина (8 < 10)
9.3 Значение переменной i увеличивается на 1, теперь i = 9.
9.4 Так проверка условия цикла дала значение истина управление передается оператору тела цикла, т.е. на экран выводится строка 9 * 2 = 18
9.5 Далее управление передается циклу while

10-й шаг цикла

10.1 Значение переменной i равно 9.
10.2 Результат проверки условия цикла — истина ( 9 < 10)
10.3 Значение переменной i увеличивается на 1, теперь i = 10.
10.4 Так проверка условия цикла дала значение истина управление передается оператору тела цикла, т.е. на экран выводится строка 10 * 2 = 20
10.5 Далее управление передается циклу while

11-й шаг цикла

11.1 Значение переменной i равно 10.
11.2 Результат проверки условия цикла — ложь ( 10 равно 10, а не меньше!)
11.3 Значение переменной i увеличивается на 1, теперь i = 11.
11.4 Так проверка условия цикла дала значение ложь, управление НЕ передается в тело цикла, т.е. выполнение цикла заканчивается, и управление переходит к оператору, следующему за while, т.е. к cout << «\n Все»;

В данном примере, мы рассмотрели случай с заранее определенным числом повторений, однако характеру оператора while наиболее соотвествуют ситуации, когда заранее неизвестно, количество повторений цикла.