Условные выражения
Условия выражения if должны быть записаны в круглых скобках. Если они истинны, выражение, непосредственно следующее за if, выполняется:
// #5
If (usr_rsp == "N" II usr_rsp == V) go_for_.it = false;
Если должно выполниться несколько выражений, они должны быть заключены в фигурные скобки, следующие за if (это называется блоком выражений):
//#3
If (usr_guess == next_elem) {
// начало блока выражений num_right++;
Got_.it = true;} // окончание блока выражений
Общая ошибка начинающих - забыть отметить блок:
// р-раз: пропущена отметка блока
// только num_cor++ относится к if,
// а got_.it = true; выполняется вне условия
If (usr_guess == next_elem)
Num_cor++;
Got_it = true;
Выполнение got_it отражает намерения программиста. К сожалению, оно не отражает поведение программы. Наращивание num_cor относится к условному оператору і f и выполняется только тогда, когда попытка пользователя эквивалентна значению next_elem. got_it, однако, не относится к условному оператору, поскольку мы забыли обозначить два выражения как блок. В этом примере got__it всегда устанавливается в значение true независимо от того, что делает пользователь.
Условный оператор if так же поддерживает расширение else. Else представляет одно выражение или блок выражений, которые будут выполняться, если условие принимает значение false. Например,
If (usr_guess == next__elem) {
// пользователь угадал }
Else {
// пользователь не угадал }
Другое использование оператора else - объединить два условных выражения. Например, если попытка пользователя неудачна, мы хотим варьировать ответ в зависимости от числа попыток. Мы должны написать три проверки как независимые условные выражения:
If (num_tries == l)cout « "У-ух! Хорошая попытка, но не совсем.п";
If (num_tries == 2)cout « "М-да. Извини. Опять неправильно.п";
If (num_tries == 3)cout « "A-a, это труднее, чем могло показаться, не так ли?п";
Однако ТОЛЬКО одно из трех условий может быть истинным одновременно. Если одно из условий верно, остальные должны быть ложны. Мы можем отобразить зависимость между выражениями if, объединив их вместе с помощью выражений if-else:
If (num_tries == 1) cout « "У-ухї Хорошая попытка, но
Не совсемп";
Else
If (num_tries == 2) cout « "М-да. Извини. Опять неправильно. п"; else
If (num_tries == 3)cout « "А-а, это труднее, чем могло показаться, не так ли?п";
Else cout « "Похоже, дальше бесполезно!п";
Первое условное выражение выполняется. Если оно истинно, выражение, следующее за ним, выполняется, а последовательность else-if - нет. Если же первое условное выражение ложно, выполняется следующее, затем следующее, пока одно из условий не становится истинным или num_tries не становится больше 3, - все условия ложны, и последнее else выполняется.
Один из неприятных аспектов использования вложенных if-else - трудности с правильной их логической организацией. Например, мы хотели бы использовать if-else для разделения логики программы на два случая: когда пользователь угадывает и когда он не угадывает. Первая попытка не работает совсем, как мы и планировали:
If (usr_guess == next__elem) {
// пользователь угадывает }
Else if (num_tries == 1)
Else II ___ выводим вопрос
If (num__tries == 2) else 11 ... выводим вопрос if (num__tries == 3) else // ... выводим вопрос // ... выводим вопрос
// теперь спросим у пользователя, хочет ли он еще раз угадать
// но только, если он не угадал // р-раз! и куда же мы воткнем это?
Каждая пара else-if непреднамеренно была сделана альтернативой удачной попытки. В результате нам некуда поместить вторую часть кода для поддержки неудачных попыток. Вот правильная организация:
If (usr_guess == next__elem) {
// пользователь угадал} else { // пользователь не угадал if (num_tries == 1) else // ...
If (num_tries == 2) else // ... if (num__tries == 3) // ... else // ...
Cout « "Желаете попробовать еще? (Y/N) "; char usr_rsp; с in » usr_rsp;
If (usr__rsp == "N" II usr_rsp == "n") go_for__it = false;}
Если значение проверяемого условия имеет интегральный тип, мы можем заменить набор if-else-if выражением switch:
// равноценно if-else-if выше
Switch (num_tries) {
Case 1:
Cout « "У-ух! Хорошая попытка, но не совсемп"
Break;
Case 2:
Cout « "М-да. Извини. Опять неправильно.п"; break;
Case 3:
Cout « "А-а, это труднее, чем могло показаться, не так
Ли?п";
Break;
Default:
Cout « "Похоже, дальше бесполезно!п";
Break; }
Ключевое слово switch с последующим выражением в круглых скобках (да, имя объекта работает, как выражение). Выражение должно вычисляться как целое значение. Серия меток case, следующая за ключевым словом switch, определяет постоянное выражение. Результат выражения сравнивается с каждой из меток case по очереди. Если есть совпадение, выражение, следующее за case, выполняется. Если совпадений нет, и метка default присутствует, выполняется выражение, следующее за ней. Если же нет ни совпадений, ни метки default, не делается ничего.
Почему я поместил выражение break в конце каждой метки case? Каждая метка case проверяется по очереди на совпадение со значением выражения. Каждая несовпадающая метка case пропускается по очереди. Когда обнаруживается совпадение, выражение, следующее за меткой, выполняется. Увы, выполнение продолжается со следующими метками, пока не будет достигнут конец меток. Если значение num_tries, например, равно 2, и если нет выражений break, вывод будет выглядеть так:
// output if num_.tries == 2 and
// we had forgotten the break statements
М-да. Извини. Опять неправильно.
А-а, это труднее, чем могло показаться, не так ли? Похоже, дальше бесполезно!
Вторая метка case совпадает, все метки case, следующие за совпадающей, также выполняются, пока не завершается оператор. Этот алгоритм дает выражение break. Вы можете спросить: почему выражение switch так устроено? Вот пример этого провала, который придется в самый раз:
Switch |
(next. |
_char) |
|
{ case |
-a": |
Case |
"A1 |
Case |
Иe" • |
Case |
"E1 |
Case |
"i": |
Case |
-Iі |
Case |
"o": |
Case |
-0' |
Case |
"u" : |
Case |
"U' |
++vowel. |
_cnt; |
Break;// ...} |