Операторы ветвления

if-else

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

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

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

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

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

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

В 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
		….;

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

if (…)
	if (…)
		….;
	else
		if (…)
			….;
		else
			….;

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

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

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

Чаще всего на практике используется подобная конструкция множественного ветвления:

if (…) {
    …
} else if (…) {
    …
} else if (…) {
    …
} else {
    … 
}

Здесь с точки зрения компилятора каждое else относится к предыдущему if, но выравнивание делается таким, как будто в Си есть условный оператор множественного ветвления. Результат работы конструкции таков, что выполняется хотя бы одна ветка. И как только она выполняется, вся конструкция завершает работу.

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

В языке программирования 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

Задание

Проверьте и объясните, что выводит функция 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 операции начинают выполняться. Другими словами, выполняется не только кейс, где произошло совпадение, но и все нижележащие ветки case (и default тоже), константы которых не совпадают со значением при 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.

Создано

Обновлено