Условный оператор реализует структуру выбора. Он имеет такой вид:
if (условие) оператор1[ else оператор 2]
Если условие оценивается как истинное (ненулевое), выполняется onepaтop1, если как ложное (нулевое), выполняется onepaтop2. Простейший пример:
if (а > b) max_ab = a; else max_ab = b;
Как было сказано чуть выше, вместо одиночного оператора всегда можно подставить блок из нескольких операторов, заключенный в фигурные скобки. Другими словами, возможна следующая синтаксическая форма:
if (условие) {операторы_блока_if} else {операторы_блока_еlsе}
В случае, когда при ложности условия не нужно выполнять никаких действий, а требуется только пропустить операторы блока if, ключевое слово else и соответствующий ему оператор (блок) могут отсутствовать, как в следующем примере:
if (а > b) { temp = а; а = b; b = temp; } //...Продолжение программы...
В этом фрагменте программы, если а > b, то значения a и b меняются местами, в противном случае блок не выполняется и все остаётся, как есть. В соответствии с правилом суперпозиции можно строить вложенные структуры if...else, например:
if (a > b) if (a > с) max_abc = а; else max abc = с; else if (b > с) max_abc = b; else max_abc = с ;
Эта конструкция всего-навсего определяет наибольшее из трех чисел, но разобраться в ее логике не так-то просто. Кроме того, следует помнить, что если во вложенных условных структурах используются как полные, так и неполные операторы if (без else), то могут возникать неоднозначности. Попробуем, например, переписать предыдущий фрагмент чуть более экономно, заранее присвоив максимуму значение с:
max_abc = с; if (a > b) if (a > c) max_abc = = a; else if (b > c) max_abc = b;
К которому из двух первых if относится это else? По задуманной нами логике – к первому, однако компилятор считает по-другому; он разрешает подобные неоднозначности, ставя спорное else в соответствие ближайшему if, т. е. в данном случае второму. В результате все работает неправильно. Чтобы устранить неоднозначность, нужно применить операторные скобки:
max_abc = с; if (а > b) { if (а > с) max_abc = а; } else if (b > с) max abc = b;
Об условиях в операторе if
Условие оператора if может быть сколь угодно сложным выражением. Можно было бы сказать, что это выражение должно быть "логическим”, но в языке С (не в С++, а в С) нет логического типа данных, поэтому условие для большей общности сделали целого типа. Как уже говорилось, выражение считается ложным (false), если его значением является нуль, и истинным (true), если значение ненулевое. В С++ введен логический тип данных bool. Но переменные логического типа конвертируются к целому типу true (равно 1) или false (равно 0), если они используются в условии. Вот несколько примеров условий оператора if:
if (x) DoSomething(); //Если х не равно нулю, то выполняется функция DoSomething().
if (!x) DoAnotherThing(); //Если х равно нулю, то выполняется функция DoAnotherThing().
if (b = = с) DoAnotherThing(); /*Если b равно с (логическое сравнение), то выполняется функция DoA-notherThing().*/
if (b != с) DoSomething(); //Если b не равно с, то выполняется функция DoSomething().
if ((key = getch()) = = 'q') DoQuit(); /*Сохранить код клавиши в key и,если он равен ' q ' , выполнить функцию DoQuit().*/
if (a >= b && a <= c) DoSomething(); //Если а лежит между b и с, выполнить функцию DoSomething().
При записи условия используются логические операции (записаны в порядке убывания приоритета):
! – логическое НЕ (инверсия); < – меньше; <= – меньше или равно; > – больше; >= – больше или равно; = = – равно; != – логическое И; && – логическое И; || – логическое ИЛИ.
! – логическое НЕ (инверсия, отрицание), дает в результате false (0), если операнд true(≠ 0 ) или 1 если операнд false (0). Операнды в этой операции могут иметь тип bool, int, вещественный. Пример:
bool x,y; y=true; x=!y;
В результате: х будет присвоено значение false (0). Операции отношения (<, <=, >, > , = =. ! =) сравнивают первый операнд со вторым. Операнды могут быть арифметического типа ( int, float, double ) или указателями. Результатом операции является значение true или false (любое значение, не равное нулю, интерпретируется как true). Операции сравнения на равенство и неравенство имеют меньший приоритет, чем остальные операции сравнения. ПРИМЕЧАНИЕ: обратите внимание на разницу между операцией проверки на равенство (==) и операцией присваивания (=), результатом которой является значение, присвоенное левому операнду. Пример:
a= =0; логическое значение этого выражения true, если а равно 0, иначе false. a=0; логическое значение этого выражения всегда false.
Логические операции && (И) и || (ИЛИ). Операнды логических операций И (&&) и ИЛИ ( || ) могут иметь арифметический тип или быть указателями, при этом операнды в каждой операции могут быть различных типов. Преобразования типов не производятся, каждый операнд оценивается с точки зрения его эквивалентности нулю (операнд, равный нулю, рассматривается как false, не равный нулю – как true). Результатом логической операции является true или false. Результат операции логическое И имеет значение true только если оба операнда имеют значение true. Результат операции логическое ИЛИ имеет значение true, если хотя бы один из операндов имеет значение true. Логические операции выполняются слева направо. Если значения первого операнда достаточно, чтобы определить результат операции, второй операнд не вычисляется. Примеры:
a>b && c<d если одновременно а больше b и с меньше d, то выражение равно true, иначе false. a>b || c<d если а больше b или с меньше d, то выражение равно true, иначе false. Можно было бы записать (a>b)&&(c<d), но в этом нет необходимости, поскольку приоритет операций > и < выше чем && и ||.
Оператор выбора switch
Часто возникают ситуации, когда некоторая переменная может принимать несколько возможных значений-вариантов, и для каждого варианта требуется выполнить какие-то свои действия. Например, пользователю может быть предложено меню, когда нажатие различных клавиш инициирует соответствующие команды. Управляющая конструкция, реализующая такую логику, может использовать "последовательно вложенные” операторы if...else if...:
int key; printf(RUS("\nВыберите команду (F, M or Q): ")); // Вывести подсказку. key = getch(); // Прочитать символ. key = toupper(key); // Преобразовать в верхний регистр. // блок определения команды... if (key == 'F') printf(RUS("\nВыбрана команда \"F\" – означает Файл.\n")); else if (key == 'M') printf(RUS("\nВыбрана команда \"M\" – означает сообщение.\n")); else if (key == 'Q') printf(RUS("\nВыбрана команда \"Q\" – означает Выход.\n")); else printf(RUS("\nНеправиьная клавиша!"));
Условия операторов if содержат проверку кода нажатой клавиши на равенство одному из допустимых символов. Если код клавиши не соответствует никакой команде, выводится сообщение об ошибке. Для подобных случаев в С существует специальная, более удобная, конструкция выбора switch. Выглядит она так:
switch (выражение) { case константное_выражение: группа_операторов case константное_выражение: группа_операторов [default: группа операторов] } Сначала производится оценка выражения в операторе switch. Полученное значение последовательно сравнивается с каждым из константных_выражений, и при совпадении значений управление передается на соответствующую группу_операторов. Если значение выражения не подходит ни под один из вариантов, управление передается на группу операторов с меткой default или на следующий после блока switch оператор, если группа default отсутствует. Под группой _операторов подразумевается просто один или несколько произвольных операторов. Группа здесь вовсе не обязана быть блоком, т. е. заключать ее в операторные скобки не требуется. И еще одна особенность, о которой следует помнить при написании структур switch. Если найдена метка case, совпадающая со значением проверяемого выражения, то выполняется группа_операторов данного case. Однако дело на этом не заканчивается, поскольку, если не принять никаких дополнительных мер, управление "провалится” ниже, на следующую по порядку метку case и т. д., и в результате будут выполнены все операторы до самого конца блока switch. Если это нежелательно (как чаще всего и бывает), в конце группы_операторов case нужно поставить оператор break. Он прерывает выполнение блока c совпавшей меткой и передает управление оператору, непосредственно следующему за блоком switch. Для иллюстрации мы перепишем предыдущий пример "меню”, оформив его в виде законченной программы, и продемонстрируем попутно еще один управляющий оператор С. Демонстрация структуры switch:
int key; loop: //здесь можно добавить программу, выполняемую каждый раз //после выбора команд F, M or Q printf(RUS("\nВыберите команду (F, M or Q): ")); key = getche(); // Прочитать клавишу. // Определение команды... switch (key) { case 'f': case 'F': printf(RUS("\nВыбрана команда \"Файл\".\n"));break; case 'm': case 'M': printf (RUS("\nВыбрана команда \"Message\".\n"));break; case 'q': case 'Q': printf(RUS("\nВыбрана команда \"Quit\".\n")); printf(RUS("Нажмите любую клавишу для завершения программы ...\n")); getch() ; return 0; // Возврат в Windows. default: printf(RUS("\nНеправиьная клавиша!")); } goto loop; // переход в начало программы на метку loop
Мы организовали в программе простейший "бесконечный” цикл, который все время просит пользователя ввести команду – до тех пор, пока не будет нажата клавиша "Q”. В этом случае происходит возврат в операционную систему. Чтение команды производится функцией getche(). Она, как и getch(), возвращает код нажатой клавиши, однако в отличие от getch() отображает введенный символ на экране. Для реализации цикла мы использовали оператор goto, исполнение которого приводит к передаче управления на метку, указанную в операторе. В примере метка с именем loop стоит в самом начале программы. Таким образом, дойдя до конца функции main (), управление возвращается к ее началу и все повторяется снова.