Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
http.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.34 Mб
Скачать

Вложенные if

Один из наиболее трудных аспектов использования операторов if в любом языке программирования - это вложенность операторов if. Под вложенным if подразумевается оператор if, имеющий еще один if или else. Причина того, что вложенность операторов if вызывает такие проблемы, заключается в трудностях идентификации: какое else соответствует какому if. Например: if (x)     if (у) printf("1");    else printf("2"); Какому if соответствует какое else?

К счастью, С предоставляет очень простое правило для разрешения такого рода проблем. В С else соответствует ближайшему предшествующему if (на том же уровне видимости), еще не имеющему оператора else. В данном случае else связан с оператором if (у). Для того, чтобы связать else с оператором if (х), следует использовать фигурные скобки, как показано ниже: if (x) {     if (у) printf ("1"); } else printf ("2"); Теперь else связано с if (x), поскольку он не принадлежит больше блоку if (у). Из-за правил видимости С else теперь не знает об операторе if (у), поскольку он находится на другом уровне.

Дальнейшее улучшение программы предоставляет возможность игроку узнать, как близко он был к победе. Это реализуется с помощью вложенных if: #include <stdio.h> /* программа "угадай число 3" */ int main(void) { int magic = 123; /* искомое число */ int guess; printf("Enter your guess: "); scanf("%d", &guess); if(guess == magic) { printf("** Right ** "); printf("%d is the magic number", magic); } else { printf(".. Wrong .. "); if(guess > magic) printf("Too high"); else printf("Too low"); } return 0; }

Лесенка if-else-if

Типичной программистской конструкцией является лесенка if-else-if. Она выглядит следующим образом: if (выражение) оператор; else if (выражение) оператор; else if (выражение) оператор; ... else   оператор;

Условия вычисляются сверху вниз. Когда обнаруживается истинное условие, то выполняется оператор, связанный с этим условием, а остальная часть конструкции игнорируется. Если не найдено ни одного истинного условия, выполняется оператор, соответствующий последнему else. Последний оператор else часто играет роль оператора, выполняемого по умолчанию, то есть, если все условия ложны, то выполняется оператор, соответствующий последнему else. Если последний оператор else отсутствует, то не выполняется никаких действий в случае ложности всех условий. Использование лесенки if-else-if преобразует нашу программу следующим образом: #include <stdio.h> /* программа "угадай число 4" */ int main (void) { int magic = 123; /* искомое число */ int guess; printf ("Enter your guess: "); scanf {"%d", &guess); if(guess == magic) { printf ("** Right ** ") ; printf("%d is the magic number", magic); } else if(guess > magic)    printf (ff. . Wrong . . Too High"); else printf (".. Wrong .. Too low"); return 0; }

Оператор ?

Оператор ? может использоваться для замены стандартной конструкции if/else: if (условие) выражение; else выражение; Ограничением в данном случае является использование единственного выражения как после if, так и после else.

Оператор ? называется триадным оператором, поскольку ему требуется три операнда и он имеет следующий вид: выражение1 ? выражение2 : выражение3 где выражение1, выражение2 и выражение3 - это выражения.

Оператор ? работает следующим образом. Вычисляется выражение1. Если оно истинно, вычисляется выражение2 и вся конструкция получает вычисленное выражение. Если выражение1 ложно, вычисляется выражение3 и вся конструкция получает вычисленное выражение. Например: х = 10; у = х > 9 ? 100 : 200; В данном примере у получает значение 100. Если бы х было меньше, чем 9, то у получило бы значение 200. Ниже приведен фрагмент программы, выполняющий такие же действия, но с использованием операторов if/else: х = 10; if (х > 9) у = 100; else у = 200;

Использование оператора ? для замены if/else не ограничивается присваиванием. Надо помнить, что все функции (кроме объявленных как void) могут возвращать значение. Следовательно, допустимо использование одного или нескольких вызовов функции в выражениях. Когда встречается имя функции, функция соответственно выполняется для определения возвращаемого значения. Поэтому возможно выполнить одну или несколько функций, используя оператор ?, поместив их в выражения, образующие операнды. Например: #include <stdio.h> int f1 (int n) , f2(void); int main(void) { int t; printf(": "); scanf("%d", &t); /* print proper message */ t ? f1(t)+f2 () : printf ("Zero Entered"); return 0; } int f1 (int n) { printf("%d ",n); return 0; } int f2(void) { printf("entered"); return 0; } В данном примере, если ввести 0, вызовется функция printf() и появится сообщение «Zero Entered». Если ввести любое другое число, то выполняются функции f1() и f2(). Следует заметить, что в данном примере значение, возвращаемое оператором ?, отбрасывается. Даже если ни f1(), ни f2() не возвращают информативного значения, они не могут быть определены как возвращающие тип void, поскольку это не позволит применять их в выражении. Поэтому функции просто возвращают 0.

Используя оператор ?, возможно переписать нашу программу следующим образом: #include <stdio.h> /* программа "угадай число 5" */ int main(void) { int magic = 123; /* искомое число */ int guess; printf("Enter your guess: "); scanf("%d", &guess); if(guess == magic) { printf("** Right ** "); printf("%d is the magic number", magic); } else guess > magic ? printf("High") : printf("Low") ; return 0; }

Здесь оператор ? приводит к выводу сообщения, основываясь на сравнении guess > magic.

SWITCH

Хотя конструкция if-else-if может выполнять многочисленные проверки, она не очень элегантна. Код очень труден для восприятия и в нем может запутаться даже автор через некоторое время. С этой целью С имеет оператор принятия решений switch, выполняющий действия, основываясь на сравнении значения со списком констант символов или целых чисел. При обнаружении совпадения выполняется оператор или операторы, ассоциированные с данным значением. Оператор switch имеет следующий вид: switch (выражение) { case константа1: последовательность операторов break; case константа2: последовательность операторов break; case константа3: последовательность операторов break; ... default: последовательность операторов }

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

Следует знать о трех важных моментах оператора switch:

  1. switch отличается от if тем, что он может выполнять только операции проверки строгого равенства, в то время как if может вычислять логические выражения и отношения.

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

  3. Если в операторе switch используются символьные константы, они автоматически преобразуются к целочисленным значениям.

Оператор switch часто используется для обработки команд клавиатуры типа работа с меню. Как показано ниже, функция menu() отображает меню для программы проверки орфографии и вызывает соответствующие процедуры: void menu(void) { char ch; printf("1. Check Spelling\n"); printf("2. Correct Spelling Errors\n"); printf("3. Display Spelling Errors\n"); printf("Strike Any Other Key to Skip\n"); printf ("    Enter your choice: "); ch = getche(); /* чтение клавиатуры */ switch(ch) { case '1':      check_spelling();    break; case '2':     correct_errors();    break; case '3';     display_errors();    break; default  : printf("No option selected");   } }

С технической точки зрения операторы break являются необязательными в операторе switch. Они используются для окончания работы последовательности операторов, ассоциированных с данной константой. Если оператор break отсутствует, продолжают выполняться операторы следующего раздела, пока не будет достигнут оператор break или конец оператора switch. О константах выбора можно думать как о метках. Выполнение начинается с метки, соответствующей искомому значению, и продолжается, пока не будет достигнут break или конец оператора switch. Например, функция, показанная ниже, использует данную особенность оператора case для упрощения кода обработчика ввода драйвера устройства: void inp_handler(void) { int ch, flag; ch = read_device(); /* чтение какого-то устройства */ flag = -1; switch(ch) { case 1: /* данные случаи имеют общую последовательность */ case 2: /* операторов */ case 3:     flag = 0;     break; case 4:      flag = 1; case 5:     error(flag); break; default: process(ch);   } } Данная подпрограмма иллюстрирует две грани оператора switch. Во-первых, можно иметь пустые условия. В данном случае первые три условия приводят к выполнению одних и тех же операторов: flag = 0; break; Во-вторых, выполнение переходит к следующему case, если отсутствует break. Если ch соответствует 4, то flag устанавливается в 1, и, поскольку отсутствует оператор break, выполнение продолжается и выполняется оператор error(flag). В данном случае flag имеет значение 1. Если ch равно 5, то вызывается error(flag), а значение flag будет равно - 1. Способность запускать несколько операторов, соответствующих нескольким условиям при отсутствии оператора break, позволяет создавать эффективный код, поскольку это избавляет от необходимости дублировать код.

Важно понять, что операторы, ассоциированные с каждой меткой, являются не блоками кода, а скорее последовательностью операторов. (Сам оператор switch определяет блок.) Понимание этого необходимо в некоторых специфических ситуациях. Например, следующий фрагмент кода содержит ошибку и не будет компилироваться, поскольку невозможно объявить переменную в последовательности операторов: /* неверно */ switch(с) { case 1:      int t; ...

Тем не менее переменная может быть добавлена: /* верно */ switch(с) { int t; case 1: ...

Имеется возможность создания блока кода как одного из операторов в последовательности и объявление в нем переменной, как показано ниже: /* Это также корректно */ switch (с) { case 1: { /* create a block */ int t; ... }

ЗАМЕТКА: Все ранее обсуждаемое применимо только к С, но не к С++. В С++ можно объявлять переменную в любой точке, в том числе в последовательности операторов.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]