Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Программирование в Visual С++ 2005 11 страница



Вложенные операторы if-else

Как вы уже видели, можно вкладывать операторы if в другие операторы if.
Точно так же можно вкладывать операторы if-else внутрь операторов if, а опера-
торы if — внутрь if-else. Здесь существует некоторая возможность путаницы, поэ-
тому рассмотрим несколько примеров. Ниже представлен пример вложения if-else
внутрь if.

 

 


Проверка donuts выполняется только в случае, когда проверка coffee возвраща-
ет true, поэтому сообщения корректно отражают ситуацию в каждом случае. Однако
здесь легко запутаться. Если вы напишете то же самое с неправильными отступами,
то, глядя на код, можете прийти к неверным заключениям.

 


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

 

else всегда относится к ближайшему предшествующему if, у которого нет другого else.

 

В любом случае, когда код выглядит сложным, вы можете применить это правило,
чтобы разобраться. А когда пишете собственную программу, всегда применяйте фигур-
ные скобки, чтобы сделать ситуацию яснее. Без них можно обойтись в таком простом
случае, но, тем не менее, вы могли бы записать последний пример следующим образом:

 

И в этом случае не остается места для неправильного толкования. Теперь, когда
вы знаете правила, понять случай с вложением if внутрь if-else будет нетрудно

 

 

.


Решения и циклы 147

 

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

Если в данном примере удалить фигурные скобки, то вы получите корректный ре-
зультат только тогда, когда и coffee, и donuts равны * у', то есть тогда, когда про-
верка не выполняется.

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

 

 


Логика этого примера выглядит не столь очевидной, даже несмотря на правиль-
ные отступы. Необходимости в фигурных скобках нет, потому что правило, упомяну-
тое выше, выполняется, но код будет яснее, если скобки все-таки вставить.

 


Однако существует гораздо лучший способ программирования логики такого рода.
Если вы собираете достаточно много if в одну конструкцию, то почти наверняка
рано или поздно допустите ошибку. В следующем разделе я покажу, как упростить си-
туацию.



Логические операции и выражения

Как видите, использование if может выглядеть несколько неуклюже, когда нужно
проверить два или более взаимосвязанных условия. В предыдущем примере мы по-
пробовали применить if для выяснения ситуации с кофе и пончиками, но на прак-
тике может понадобиться проверять намного более сложные условия. Вы можете ис-
кать в файле персонала кого-нибудь старше 21, но младше 35 лет, женского пола, с
дипломом колледжа, не замужем и разговаривающую на хинди или урду. Определение


148 Глава 3

 

такого проверочного условия может породить монстроподобную конструкцию опе-
раторов if.

Простое и четкое решение обеспечивают логические операции. Применяя ло-
гические операции, вы можете комбинировать серии сравнений в одно логическое
выражение, так что в конечном итоге понадобится всего один оператор if — почти
независимо от сложности набора условий, до тех пор, пока он сводится в конечном
итоге к выбору из двух альтернатив (true или false).

Существуют всего три логических операции.

Логическое И

Операция логического И (&&) применяется тогда, когда есть два условия, и оба
должны вернуть результат true, чтобы общий результат был равен true. Вы хотите
быть богатым и здоровым. Например, вы можете использовать операцию && при про-
верке принадлежности символа к буквам верхнего регистра; проверяемое значение
должно быть больше или равно ' А' И меньше или равно ' Z '. Оба условия должны
вернуть true, чтобы значение относилось к заглавным буквам.

Как и ранее, условия, комбинируемые логическими операциями, могут возвращать числовые
значения. Помните, что ненулевые значения приводятся к true, а нулевые— к false.

Если вернуться к примеру, в котором проверяется значение типа char, сохранен-
ное в переменной letter, то можно было бы заменить проверку с двумя оператора-
ми i f на одну, использующую операцию :

 

 


Скобки внутри проверочного выражения условия i f гарантируют, что операции
сравнения, вне всяких сомнений, будут выполнены первыми, и это делает весь опера-
тор яснее. Здесь вывод сообщения произойдет только в том случае, если оба условия,
объединенные операцией &&, окажутся истинными.

Как и в случае с бинарными операциями, о которых мы говорили в предыдущей
главе, эффект применения каждой логической операции можно представить табли-
цей истинности. Упомянутая таблица для && представлена в табл. 3.1.

Заголовки строк слева и заголовки столбцов сверху представляют значения ло-
гических выражений, комбинируемых операцией &&. Таким образом, чтобы опреде-
лить результат комбинации условия true с условием false, выберите строку с true
слева, и столбец с false сверху, а на пересечении строки и столбца ищите результат
(false). В действительности вам даже не нужна таблица истинности, поскольку все
достаточно просто: операция && возвращает true, только если оба операнда равны
true.


Решения и циклы 149

 

Логическое ИЛИ

Операция логического ИЛИ (| |) применяется тогда, когда имеются два условия и
нужно получить результат true, если любое из них или оба возвращают true. Напри-
мер, банк может положительно оценить вашу кредитоспособность для получения за-
йма, если ваш доход составляет не менее $100 ООО в год или же у вас есть $1 ООО ООО
наличными. Это может быть проверено с помощью следующего оператора if:

 

 


Банковский клерк проявит любезность, когда любое из двух условий выполнено
либо оба сразу. (Более подходящим вопросом был бы: "Почему вы хотите занять де-
нег?". Вообще-то странно, что банки готовы одалживать деньги только тогда, когда
вы в них совершенно не нуждаетесь.)

Таблица истинности для операции | | представлена в табл. 3.2.

Здесь также результат может быть выражен очень просто: результат false получа-
ется только тогда, когда оба операнда операции | | равны false.

Логическое НЕ

Третья логическая операция — НЕ (!) — принимает один операнд типа bool и ин-
вертирует его значение. Поэтому если значением переменной test является true,
то! test получит значение false. Если же test равно false, то 'test будет равно
true. В качестве примера простого выражения, если х имеет значение 10, то выра-
жение:

будет false, поскольку х > 5 соответствует true.

Можно применить операцию! к любимому выражению Чарльза Диккенса:

 

 


Если это выражение возвращает true, то в результате вы получите нищету, по
крайней мере, как только банк перестанет оплачивать подписанные вами чеки.

И, наконец, вы можете применять операцию! к другим базовым типам данных.
Предположим, что имеется переменная rate типа float, содержащая значение 3,2.
По некоторой причине вы можете пожелать убедиться, что значение rate отличает-
ся от нуля, в этом случае можно использовать следующее выражение:

Значение 3,2 отличается от нуля, а потому преобразуется в значение true типа
bool, и результат всего выражения будет false.



Вы можете комбинировать условные выражения и логические операции так, как
вам будет удобно. Например, вы можете сконструировать тест, определяющий, отно-
сится ли символ к буквам, применив единственный оператор if. Давайте рассмотрим
рабочий пример.

Описание полученных результатов

Пример начинается так же, как ЕхЗ_01. срр — с чтения символа, введенного поль-
зователем в ответ на приглашение. Что здесь интересно, так это условие оператора
if — оно состоит из двух логических выражений, скомбинированных операцией | |
(ИЛИ), так что если любое из них равно true, то все условие возвращает true, и на
экран выдается сообщение:

 


Если же оба выражения возвращают false, то выполняется оператор else, кото-
рый выдает сообщение:

Каждое из логических выражений, объединенных | |, само состоит из комбина-
ций пары выражений, объединенных операцией && (И), поэтому каждое выражение,
участвующее в этих парах, должно возвращать true, чтобы данная пара вернула true.
Первое логическое выражение возвращает true, если введена буква верхнего реги-
стра, а второе — если это буква нижнего регистра.

Условная операция

Условную операцию иногда называют тернарной операцией, потому что она ра-
ботает с тремя операндами. Лучше всего объяснить ее на примере. Предположим,


Решения и циклы 151

 

что имеется две переменных — а и b — и вы хотите присвоить максимальное из этих
двух значений третьей переменной с. Это можно сделать с помощью следующего опе-
ратора:

 


Первый операнд условной операции должен быть выражением, которое возвра-
щает значение типа bool — true или false, как в случае с а > Ь. Если это выражение
возвращает true, то в качестве результирующего значения возвращается значение
второго операнда — а. Если же первый аргумент равен false, то возвращается зна-
чение третьего операнда — то есть Ь. Таким образом, результатом условного выраже-
ния а > b? а: b будет а, если а больше Ь, и b — в противном случае. Это значение
записывается в переменную с операцией присваивания. Такое применение условной
операции в операторе присваивания эквивалентно следующей конструкции if:

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

 

 

Если условие оценивается как true, результатом будет значение выражение1, если

же оно равно false, то результатом будет значение выражение2.



Вывод этой программы:



Часто условная операция применяется для управления выводом, в зависимости от
результата выражения или з


 



а 3

 

Описание полученных результатов

Сначала вы инициализируете переменную nCakes значением 1; затем идет выра-
жение, выводящее на экран сообщение о количестве пирожных. Часть, использую-
щая условную операцию, просто проверяет значение переменной, чтобы определить,
сколько есть пирожных — одно или больше:

Выражение оценивается как "ых. ", если nCakes больше 1, или "ое. " — в против-
ном случае. Это позволяет использовать один оператор вывода для любого количе-
ства пирожных, получая грамматически корректное сообщение. Это доказывает по-
вторный вывод сообщения после увеличения значения переменной nCakes.
' Существует много аналогичных ситуаций, в которых вы можете применить этот
механизм; например, выбирая между "является" и "являются".

Оператор switch

Оператор switch дает возможность выбирать из множества вариантов, основыва-
ясь на наборе фиксированных значений заданного выражения. Он действует подобно
вращающемуся переключателю, который можно установить в одно из фиксирован-
ного числа положений. Некоторые стиральные машины снабжены подобным пере-
ключателем, которым выбирается режим стирки. Есть заданное число возможных
позиций, в которые его можно установить — хлопок, шерсть, синтетическое волокно
и тому подобное, и вы можете выбрать любой из них, установив переключатель в со-
ответствующее положение.

В операторе switch выбор определяется значением указанного выражения. Вы
устанавливаете возможные позиции switch одним или более case-значений, одно из
которых выбирается, если значение выражения совпадает с ним. Каждому возможно-
му значению выражения оператора switch соответствует одно case-значение, при-
чем эти case-значения должны отличаться друг от друга.

Если значение выражения switch не соответствует ни одному из case-значений,
то switch автоматически выбирает ветвь default. При желании вы можете специ-
фицировать код ветви default, как это показано ниже. Если этого не сделать, то ког-
да выражение switch не соответствует ни одному из case-значений, по умолчанию
не делается ничего, а управление просто передается оператору, следующему за завер-
шающей фигурной скобкой switch.

Увидеть на практике работу оператора switch можно, запустив приведенный
ниже пример.

 

 



 
 

Описание полученных результатов

После выдачи в выходной поток списка возможных вариантов выбора и прочте-
ния введенного пользователем значения в переменную choice оператор switch ис-
полняется с условием, специфицированным в скобках просто как (choice), которое
следует за ключевым словом switch. Все возможные варианты switch заключены в
фигурные скобки, и каждый снабжен меткой case. Эта метка состоит из ключевого
слова case, за которым идет значение choice, соответствующее данному выбору, и
завершается двоеточием.

Как видите, выполняемые операторы для конкретного case записываются между
двоеточием данной метки case и завершаются оператором break. Слово break пере-
дает управление оператору, следующему за закрывающей фигурной скобкой switch,
break — необязательная часть конструкции, но если вы ее пропустите, то выполне-
ние продолжится с оператора, идущего за следующим case, а это обычно не совсем
то, что вам нужно. Можете попробовать убрать несколько break в последнем приме-
ре и посмотреть, что получится.

Если значение choice не соответствует ни одному значению case, то выполняют-
ся операторы, которым предшествует метка default. Однако эта метка не обязатель-
на. В случае ее отсутствия, если значение проверочного выражения не соответствует
ни одному значению case, управление передается за пределы switch, и программа
выполняет оператор, следующий за закрывающей скобкой switch.

Каждое из выражений, которые вы специфицируете для идентификации вариан-
тов case, должно быть константой, чтобы его значение могло быть определено во
время компиляции, и должно бать уникальным целым числом. Причина в том, что


154 Глава 3

 

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

 

 


Описание полученных результатов

В данном примере вы имеете более использовано более сложное выражение в
switch. Если введенный символ не является буквой в нижнем регистре, то выражение:

 

 


даст в результате false, иначе — true. Поскольку letter умножается на это выра-
жение, значение логического выражения приводится к целому (0, если выражение
ложно, и 1 — если истинно). Таким образом, выражение switch равно 0, если введен-
ный символ не является буквой нижнего регистра, в противоположном случае оно
равно самому введенному символу. То есть оператор, следующий за case 0, выполня-
ется всякий раз, когда код символа, сохраненного в letter, не является прописной
буквой нижнего регистра.

Если же введена прописная буква, то выражение switch в результате вычисления
дает само значение этой буквы, поэтому для того, чтобы выдать сообщение о том,
что введенная буква — гласная, оператор вывода помещается после серии меток case,
каждая из которых сравнивает значение с одной из гласных букв. Один и тот же опе-
ратор выполняется для любой гласной, потому что когда обнаруживается подходящая
метка case, то после этого выполняются все последующие операторы — до тех пор,
пока не встретится break. Вы можете видеть, что одно и то же действие может соот-


Решения и циклы 155


 

ветствовать нескольким последовательным меткам case, размещенным перед опера-
тором, выполняющим это действие. Если же будет введена согласная буква, то выпол-
нится оператор, следующий за меткой default.

Безусловное ветвление

Оператор if предоставляет вам возможность гибко выбирать один или другой на-
бор операторов, в зависимости от указанного условия, то есть последовательность вы-
полнения операторов варьируется в зависимости от данных программы. В отличие от
этого, оператор goto — грубый инструмент. Он позволяет вам перейти к определен-
ному оператору программы безо всяких условий. Оператор, на который выполняет-
ся переход, должен быть идентифицирован меткой — идентификатором, определен-
ным в соответствии с теми же правилами, которым подчиняются имена переменных.
Метка должна быть снабжена двоеточием и помещена перед оператором, к которому
выполняется переход. Ниже представлен пример помеченного оператора.

 


Оператор имеет метку myLabel, и безусловный переход к этому оператору в про-
грамме записывается так:

Где только возможно, вы должны избегать в своих программах применения goto.
Это порождает запутанный код, который чрезвычайно трудно отследить.

Поскольку теоретически goto не является необходимым в программах— применению goto
всегда существует альтернатива— большая часть программистов считает, что использо-
вать его вообще никогда не следует. Я не подпишусь под этой крайней точкой зрения. В кон-
це концов, это — законный оператор языка, и бывают случаи, когда применить его удобно.
Однако я рекомендую, чтобы он использовался только тогда, когда очевидно его преимуще-
ство перед другими возможными вариантами организации кода. В противном случае вы
рискуете получить запутанный, подверженный ошибкам код, который трудно понять и еще
труднее сопровождать.

 

Повторение блока операторов

Возможность повторно выполнять группу операторов — фундаментальна для боль-
шинства приложений. Без этой возможности организации пришлось бы модифици-
ровать программу начисления зарплаты всякий раз, когда нанимается новый сотруд-
ник, и вам пришлось бы перезагружать Halo 2 всякий раз, когда вы хотите сыграть в
другую игру. Поэтому давайте разберемся, как работают циклы.

Что такое цикл?

Цикл выполняет последовательность операторов до тех пор, пока истинно (или
ложно) определенное условие. Вы можете написать цикл, используя лишь те операто-
ры С++, с которыми вы познакомились до сих пор. Вам понадобится для этого только
if и "страшный" goto. Взгляните на следующий пример.

 


В этом примере осуществляется накопление суммы целых чисел от 1 до 10. При
первом выполнении последовательности операторов i, равное 1, добавляется к пере-
менной sum, которая поначалу равна 0. В операторе if переменная i увеличивается
до 2 и, до тех пор, пока она меньше или равна max, выполняется безусловный переход
к метке loop и значение i — на этот раз 2 — прибавляется к sum. Программа продолжа-
ет работать, увеличивая i и прибавляя его к sum до тех пор, пока i не вырастет до 11,
и поскольку условие if станет ложным, очередной возврат к loop выполнен не будет,
и цикл завершится. Если вы запустите этот пример, то получите следующий вывод:

 

 



Последний пример можно переписать, используя то, что называется циклом for.



Этот пример достаточно наглядно демонстрирует работу цикла; однако он исполь-
зует goto и вводит метку, чего обычно следует избегать. Вы можете достичь того же
результата, и даже более того, если применяете следующий оператор, специально
предназначенный для организации циклов.


Решения и циклы 157

Описание полученных результатов

Если вы скомпилируете и запустите это, то получите тот же вывод, что и в пред-
ыдущем примере, но как видите, здесь код заметно меньше. Условия, определяющие
операцию цикла, появляются в скобках после ключевого слова for. В этих скобках
содержится три выражения, разделенные точкой с запятой.

□ Первое выражение выполняется один раз, в начале, и устанавливает начальное
условие цикла. В данном случае переменной i присваивается значение 1.

□ Второе выражение — логическое — определяет, до каких пор должен выпол-
няться оператор цикла (или блок операторов). Если второе выражение истин-
но, цикл продолжает выполняться; когда оно ложно, он завершается и выпол-
нение продолжается с оператора, расположенного за телом цикла. В данном
случае оператор цикла в строке, следующей за for, выполняется до тех пор,
пока значение i меньше или равно max.

□ Третье выражение выполняется после оператора цикла (или блока операто-
ров), и в данном случае оно увеличивает i на 1 на каждой итерации. После
того, как это выражение оценено, еще раз вычисляется второе выражение,
чтобы проверить, должен ли цикл продолжаться.

На самом деле такой цикл — не совсем то же самое, что представлено в версии
ЕхЗ_07. срр. Вы можете убедиться в этом, если установите значение max равным О
в обеих программах и запустите их опять. При этом вы увидите, что значение sum
будет равно 1 в ЕхЗ_07. срр и 0 — в ЕхЗ_08. срр. Конечное значение i также будет
различаться. Причина в том, что первая версия программы (с if и goto) всегда вы-
полняет тело цикла, как минимум, один раз, потому что условие не проверяется до
его конца. Цикл for работает иначе, поскольку его условие на самом деле проверяет-
ся в начале.

Обобщенная форма цикла for выглядит следующим образом.

 

 


Конечно же, оператор_внутри_цикла может быть отдельным оператором или
блоком операторов в фигурных скобках. Последовательность событий при работе
цикла for показана на рис. 3.3.

Как уже упоминалось, оператор_внутри_цикла на рис. 3.3 также может быть бло-
ком операторов. Выражения, управляющие циклом for, очень гибки. Вы даже мо-
жете написать два или более выражений, разделенных запятыми, вместо любого из
трех управляющих операторов цикла for. Это дает вам широчайшие возможности в
его применении.

Вариации цикла for

В большинстве случаев выражения в цикле for используются довольно стандарт-
ным способом: первое из них инициализирует один или более счетчиков цикла, вто-
рое проверяет, должен ли цикл продолжаться, а третье увеличивает или уменьшает
значение одного или более счетчиков. Однако вы не обязаны использовать выраже-
ния именно таким образом — на самом деле, возможны несколько вариаций.


158 Глава 3

Выражение инициализации цикла for может также включать объявление пере-
менной цикла. В предыдущем примере вы могли бы написать цикл так, чтобы в пер-
вом его управляющем выражении содержалось объявление переменной i.

 

 


Естественно, исходное объявление i теперь должна быть исключена из програм-
мы. Если вы внесете это изменение в последний пример, то обнаружите, что про-
грамма не компилируется, потому что переменная цикла i исчезает после заверше-
ния цикла, и вы не можете обращаться к ней в операторе вывода. Цикл имеет область
видимости, распространяющуюся от управляющих выражений for до конца его тела,
которое может быть либо блоком кода в фигурных скобках, либо единственным опе-
ратором. Счетчик i теперь объявлен внутри области видимости цикла, и вы не мо-
жете обращаться к нему в операторе вывода, потому что оно находится за пределами
этой области. По умолчанию компилятор С++ придерживается стандарта ISO/ANSI


Решения и циклы 159


Дата добавления: 2015-11-04; просмотров: 31 | Нарушение авторских прав







mybiblioteka.su - 2015-2024 год. (0.052 сек.)







<== предыдущая лекция | следующая лекция ==>