Урок 3. Операторы ветвления

Особенности языка С. Учебное пособие

if-else

В языке программирования C синтаксис оператора ветвления if-else выглядит так:

if (логич_выражение) 
	выражение1;
else 
	выражение2;

Как и в других языках ветка else не является обязательной.

В языке С в простых логических выражениях используются следующие знаки операторов: >, <, >=, <=, ==, !=.

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

if (логич_выражение)  {
	выражение1;
	выражение2;}
else {
	выражениеN;}

Задание
Напишите любую программу на языке C, в которой бы использовалась конструкция if-else.

В C можно использовать вложенные конструкции if-else. При этом рекомендуют вкладывать во внешнюю ветку else, а не if, т.к. это позволяет избегать неоднозначности толкования инструкции. Посмотрите на такую конструкцию:

if ()
	if ();
	else;
else
	if ();
	else;

Для более легкого восприятия человеком отступами подчеркнуто, что куда вложено. Однако для компилятора с языка C отступы никакой роли не играют, и принадлежность первой ветки else не очевидна. Ее можно было бы ошибочно отнести к первому if, в результате чего второе else было бы вообще неуместным, т.к. не относилось бы ни к какому if. В данном случае такой ошибки не будет, т.к. компилятор руководствуется правилом: ветка else относится к ближайшему к ней сверху if, у которого еще нет ветки else. Именно поэтому здесь первое else относится ко второму if (т.к. оно к нему ближе), а второе else к первому if, т.к. второе if уже "покрыто" предыдущим else. Теперь посмотрите вот на такую конструкцию:

if ()
	if ()
		….;
else
	if ()
		….;
	else
		….;
<c>
Программист отступами показал, что он хочет, чтобы первое <c>else
относилось к внешнему if. Однако компилятор, руководствуясь правилом отнесения веток else, расценит программу вот так (если перевести на удобство чтения ее программистом):
if ()
	if ()
		….;
	else
		if ()
			….;
		else
			….;

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

if () {
	if ()
		….;
}
else
	if ()
		….;
	else
		….;

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

Задание
Придумайте и напишите программу, в которой бы использовалась вложенная конструкция if-else.

Условное выражение

В языке программирования C существует сокращенная запись инструкции if-else в виде условного выражения, результат которого может быть присвоен переменной:
(логич_выражение) ? выражение1 : выражение2

Переводится это так. Если логич_выражение вернуло истину, то все выражение возвращает выражение1; если логич_выражение вернуло ложь, то все выражение возвращает выражение2. Например:

x = 12;
y = 16;
z = (x > y) ? x - 1 : y - 1; 

Здесь z получит значение 15. Такое условное выражение бывает очень удобно, однако область его применения ограничена простейшими случаями ветвления, т.к. невозможно создавать сложные "тела" в такой конструкции.

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

Операторы И (&&) и ИЛИ (||)

Как известно логическое выражение может быть сложным. Логические операторы И и ИЛИ в языке программирования C обозначаются соответственно парными знаками амперсанда (&&) и вертикальной черты (||). Их приоритет меньше, чем у простых логических операторов, поэтому простые логические операции при их объединении в сложные логические выражения можно не заключать в скобки. Пример сложного логического выражения на языке C:
a > 100 && b != 0

Задания

  1. Напишите программу, в которой при if использовалось бы сложное логическое выражение.
  2. Проверьте и объясните, что выводит функция printf(), если ей передать простые или сложные логические выражения. Например:

printf("%d\n", a == b && c < d);
printf("%d\n", c < d);

Оператор switch

При организации множественного выбора бывает удобно использовать не вложенные if-else, а оператор switch. Его синтаксис можно описать так:

switch (целая_переменная) {
	case константа1:
		операции;
	case константа2:
		операции;
	….
	default: 
		опрации;
}

Это приблизительное, а не точное описание. В скобках после слова switch может стоять не только переменная, но и выражение, результат выполнения которого возвращает целое значение (может быть символ). Константы при case также могут быть результатом выполнения выражений. Константы можно группировать в одном case (например, case 12, 13, 18). Ветка default не обязательна.

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

  int a=1;
 
  switch (a) {
    case 0: 
      printf("%d ", 0);
    case 1: 
      printf("%d ", 1);
    case 2: 
      printf("%d ", 2);
    default: 
      printf("%d ", -1);
  }
 
  printf("\n");

на экране будет выведено:

1 2 -1

, т.к. как только совпадение было обнаружено, все нижеследующие инструкции были выполнены.

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

  int a=1;
 
  switch (a) {
    case 0: 
      printf("%d\n", 0);
      break;
    case 1: 
      printf("%d\n", 1);
      break;
    case 2: 
      printf("%d\n", 2);
      break;
    default: 
      printf("%d\n", -1);
  }

выведет только единицу, т.к. выполнение всей инструкции switch прервется после выполнения инструкции break при case 1.

Задание
Придумайте свою программу с использованием оператора switch.