Штерн В. - Основы C++. Методы программной инженерии - 2003
.pdf90 |
Hacih I «^ Вве, |
охэгрс^;^л^ирово |
|
|
|
short int X = 1, у = 3; |
|
||
|
cout « |
"Сумма равна " « x + у «", a ее размер равен |
// выводит 4 и 4 |
|
|
" « |
sizeof(x+y)«endl; |
||
|
Вычисления выполняются не со значениями типа short, а с соответствующими |
|||
|
целочисленными значениями. Преобразование достаточно простое. На 16-разряд |
|||
|
ной машине оно тривиально, поскольку типы short и int имеют один размер. На |
|||
|
32-разрядной машине к значению short добавляется еиде два байта, заполняемых |
|||
|
значением бита знака (О для положительного числа, 1 для отрицательного). При |
|||
|
таком приведении размера значение сохраняется. |
|
||
|
Аналогично unsigned char и unsigned short int приводятся к int. На 32-раз |
|||
|
рядной машине это не вызывает проблемы, так как диапазон целых здесь больше, |
|||
|
чем диапазон значений short, даже unsigned. На 16-разрядных машинах ситуация |
|||
|
иная. Максимальное значение unsigned short здесь равно 65 535, что больше |
|||
|
максимального значения int (32 767). Но причин для беспокойства нет. Если |
|||
|
значение не помендается в диапазон целого, то компилятор расширяет его до |
|||
|
unsigned int. Опять же приведение размера происходит прозрачно для про |
|||
|
граммиста. |
|
|
|
|
Для типов с плаваюидей точкой все происходит подобным же образом. Значения |
|||
|
float приводятся к размеру double. Со значениями float |
вычисления не выполня |
ются. Когда такое значение считывается из памяти, оно преобразуется к double. Приведение размеров целых типов и типов с плаваюш,ей точкой — нудная
техническая задача, но нужно знать о ней, поскольку такие преобразования влияют на время выполнения и могут сказываться в критичных по времени приложениях. Например, при обработке большого количества символов в коммуникационном приложении программист может хранить символы как целые, что позволит избе жать приведения их размера при каждом извлечении символа из памяти.
Это типичный для программирования случай выбора между временем выпол нения и экономией памяти. Хорошая новость в том, что приведение размера цело го не нанесет уш,ерба с точки зрения корректности программы, чего нельзя сказать о других преобразованиях.
Компилятор выполняет неявные преобразования:
•В выражениях с операндами разных типов
•В присваиваниях (согласно типу целевой переменной)
Когда выражения содержат операнды числовых типов разного размера, к "ко ротким" операндам применяется "расширяюш,ее" преобразование размера — они приводятся к типу значений большего размера, после чего операция выполняется над операндами одного, большого размера. Если выражение состоит из несколь ких операций, то оно вычисляется по правилам ассоциирования операций (обычно слева направо), и на каждом шаге, если это необходимо, преобразуются размеры. Вот иерархия размеров для преобразования в выражениях:
i nt -> unsigned int -> long -> unsigned long -> float -> double -> long double
При таком неявном преобразовании сохраняется значение преобразуемого операнда, однако программист должен убедиться, что необходимое преобразова ние имеет место. В противном случае возможна потеря точности результата (см. листинги 3.6 и 3.7).
Преобразования присваивания изменяют тип правой части присваивания — она преобразуется к типу данных цели присваивания (левой части). Сама операция присваивания всегда выполняется с операндами одного типа. В случае усечения возможна потеря точности, но это не синтаксическая ошибка. Многие компилято ры по доброте дают предупреждение о потере точности, но в C + + такая операция вполне законна. Если программист этого хочет, то он это и получит. Другими сло вами, работаюш,ий с C + + программист имеет все права на подобные действия.
Глава 3 * Работа с данными и выражениями C^-t- |
91 |
Кроме потери точности, неявное преобразо вание может давать еще два осложнения: влиять на скорость выполнения и корректность резуль татов.
Рассмотрим исходный код в листинге 3.6, преобразующий температуру из градусов по Цельсию в градусы по Фаренгейту. Пример вывода этой программы показан на рис. 3.5.
Введите, пожалуйста, значения в градусах Цельсия: 20 Значение в градусах поФаренгейту: 68
Рис. 3.5- Программа из листинга 3.6 дает корректные результат^ы при неявном преобразовании к double
Листинг 3.6. Демонстрация неявного преобразования типа
#inclucle |
<iostream> |
|
|
using namespace std; |
|
||
int mainO |
|
||
{ |
|
|
|
float |
fahr, celsius; |
|
|
cout |
« |
" Введите, пожалуйста, значения в градусах Цельсия: "; |
|
cin |
» |
Celsius; |
|
fahr = 1.8 * Celsius + 32; |
/ / преобразование? |
||
cout « |
"Значение в градусах поФаренгейту: " « |
fahr « endl; |
|
return |
0; |
|
|
} |
|
|
|
Литерал 1.8 имеет тип double. Переменная celsius типа float перед умноже нием преобразуется к типу double. Литерал 32 имеет тип int и преобразуется перед сложением к double. В итоге складываются операнды одного типа. Резуль тат вычисления будет иметь тип double. Так как переменная fahr имеет тип float, то результат вычислений перед присваиванием снова преобразуется. Конечно, эти
. преобразования выполняются очень быстро, но если объем вычислений велик и они многократно повторяются, то быстродействие программы может снизиться. Программист, использующий C+-t-, не должен забывать о производительности или, по крайней мере, быть готовым к обсуждению связанных с нею вопросов.
От подобной проблемы можно избавиться с помоилью явных суффиксов типов или вычислений с типами double.
Вот пример использования явных суффиксов типов:
float |
fahr,,celsius; ... |
|
fahr |
= 1.8f * Celsius + 32f; |
/ / float приводится к double |
A вот пример вычислений с типами double:
|
|
float fahr, |
celsius; ... |
|
|
|
|
fahr |
= 1.8 |
* Celsius + 32.0; |
/ / преобразований нет |
|
|
Даже если производительность — не первоочередная проблема (нередко так оно |
|||
|
|
и есть), программу необходимо писать с учетом удобства ее чтения. Для этого |
|||
|
|
нужно помнить о вопросах, связанных с неявными преобразованиями. Например, |
|||
|
|
при |
стандартном преобразовании |
значения температуры из градусов Цельсия |
|
|
|
в шкалу Фаренгейта используется коэффициент 9/5. Здесь он для простоты пре |
|||
|
|
вращен в 1,8. Обычно предпочтительнее не считать ничего вручную и реализо |
|||
Введите, |
пожалуйста, |
значения в градусах Цельсия: 20 |
вать программу, как показано в листинге 3.7. |
||
Кроме того, это интерактивная программа и в |
|||||
Значение |
в градусах |
по Фаренгейту: 52 |
ней тратится время на ожидание ввода от поль |
||
|
|
|
|
|
зователя и отображения результата. В таком |
Рис. 3 . 6 . Б результат,е |
*'опплоэюенного" |
случае несколько преобразований ничего не |
|||
|
преобразования |
к double |
меняют. Тот же результат программы пред |
||
|
программа из лист,инга 3.7 дает |
ставлен на рис. 3.6. |
|||
|
некорректные |
результаты |
|||
|
|
92 |
Часть I # Введение в програ1У1мирование но С^^ |
Листинг 3.7. Пример потери точности при целочисленных вычислениях
#inclucle |
<iostream> |
|
using namespace std; |
|
|
int mainO |
|
|
{ |
|
|
double fahr, Celsius; |
|
|
cout « |
" Введите, пожалуйста, значения в градусах Цельсия: "; |
|
Gin » |
Celsius; |
// точность? |
fahr = 9 / 5 * Celsius + 32; |
||
cout « |
"Значение в градусах поФаренгейту: " « |
fahr << endl; |
return 0; |
|
|
} |
|
|
Причина некорректности вывода в том, что, вопреки ожиданиям, преобразо вание из целого в double здесь не выполняется. Поскольку двоичные операции ассоциируются слева направо, целое 9 делится на целое 5 и результатом станет единица. Если же записать строку так:
fahr = Celsius * 9 / 5 + 32; / / точность?
то все будет иначе. Здесь переменная Celsius имеет тип double и все вычисления выполняются с типом double.
Как можно видеть, программисту требуется инструментальное средство, обес печивающее необходимые преобразования. В C++ для этого предлагается приве дение типа (cast) — унарная операция высокого приоритета. Она позволяет явно управлять преобразованиями числовых типов. Операция приведения типа состоит из имени типа в скобках перед преобразуемым значением. Например, (double) 9 преобразует целое 9 к double 9.0, а (int) 1.8 преобразует double 1.8 в целое 1. Теперь небольшое пояснение. Все сказанное соответствует тому, как описывают приведение типа программисты. На самом деле 9 ни во что не преобразуется, оно так и остается целым. В программе создается новое значение типа double, числен но эквивалентное целому 9.
Внимание говорят, что приведение типа преобразует значение.
На самом деле оно создает значение целевого типа и инициализирует его с помощью числового содержимого операции приведения типа.
Проблемную строку в листинге 3.7 можно переписать, используя явное приве дение типа:
fahr = (double)9 / (double)5 * Celsius + (double)32;
Ha самом деле, чтобы избежать проблемы усечения, можно написать:
fahr = (double)9 / 5 * Celsius + 32;
При этом целое 9 преобразуется в double 9.0 и , следовательно, целое значение 5 будет неявно преобразовано в double 5.0.
Такая форма приведения типа унаследована C++ из языка С. Язык C++ под держивает еще одну форму приведения типа, аналогичную по синтаксису вызову функции. В ней имя типа указывается без скобок, а операнд заключается в скобки. Если использовать приведение типа C+ + , то вычисления из листинга 3.7 будут выглядеть так:
fahr = double(9) / 5 * Celsius + 32;
Глава 3 • Работа с данньши и выраженияг^и С+4- |
93 |
Кроме того, C++ поддерживает еще четыре дополнительных вида приведения типа: dynamic_cast, static_cast, reinterpret_cast и const_cast. О них будет рассказано позднее. Чтобы показать свои намерения сопровождающему ПО программисту, некоторые применяют явные преобразования к типу, который соответствует выражению. Другие считают, что это только отягощает код и за трудняет задачу сопровождения программы. Третьи вовсе не применяют приведе ния типа, чтобы не набирать лишнего на клавиатуре.
И еще замечание по вычислению выражений. Уже упоминалось, что операнды обрабатываются слева направо. Это может создать впечатление, что компоненты выражения также вычисляются слева направо, что неверно. C++ не берет на себя никаких обязательств относительно порядка вычисления компонентов выра жения. Соблюдается лишь порядок выполнения операций в выражении.
Данное обстоятельство иногда ускользает от внимания программистов. Часто это не важно. Например, в выражении, преобразующем температуру по Цельсию в градусы по Фаренгейту, операции выполняются слева направо. Неважно, в ка ком порядке вычисляются значения 9, 5, Celsius и 32. Они не зависят друг от друга. Важно, когда операции с побочными эффектами используются в другом выражении. Каким, например, будет результат в этом случае?
i nt |
num = 5, t o t a l ; |
|
|
t o t a l |
= num + num++; |
/ / 10 или 11? |
|
cout |
« |
"Сумма равна " « total « |
endl; |
Поскольку здесь применяется постфиксная операция, значение num использу ется в выражении перед инкрементом, поэтому total будет равно 10. Но это предполагает, что компоненты выражения вычисляются слева направо. При вы числении справа налево num++ подсчитывается первым. Тогда значение 5 сохраня ется для использования в вычислениях, а num становится равным 6. Затем вычисляется левый операнд num, но его значение уже равно 6, поэтому total ста новится равным 11, а не 10.
На моей машине результат равен 10. Возможно, на вашей он будет таким же. Это не означает, что C++ делает "незаконной" любую программу, вычисляющую компоненты выражения слева направо. Как преодолеть проблему? Как сделать так, чтобы на всех машинах получалось 10? Вот как:
int num = 5, t o t a l ; |
|
// 10, a не 11num++; |
||
total = num + num; |
total « |
|||
cout « |
"Сумма равна " « |
endl; |
||
Нужно получить на всех машинах 11 ? Легко: |
||||
int num = 5, total; |
|
|
||
int olcl_num = num; num++; |
|
|
||
t o t a l |
= num + old_num; |
|
/ / 11, a не 10 |
|
cout |
« |
"Сумма равна " « |
total « |
endl; |
Всегда можно явно указать, что именно требуется. Так и нужно делать.
Итоги
Итак, в C++ достаточно типов и вычислений выражений. Как можно видеть, всегда полезно подумать о диапазоне используемых типов. Это важно как с точки зрения переносимости программы, так и для корректности результатов. Если нет веских причин делать обратное (например, таково желание вашего начальника), то используйте типы int и double, но убедитесь, что они работают корректно.
94 Часть ! # Введение в програ^г^ироеоние на C++
Эта глава охватывала большой объем тем, для усваивания данного материала потребуется некоторое время. Поэкспериментируйте с примерами, вернитесь к главе 2 — используйте ее как основу для работы с С+4-. Не торопитесь при менять слишком много продвинутых средств.
Попробуйте комбинировать в выражениях разные типы, но не забывайте о преобразованиях, их влиянии на корректность результатов и производительность программы. Умеренно применяйте явное приведение типа, не используйте выра жения с побочными эффектами как часть другого выражения. Избегайте излиш ней сложности. Вы запутаете компилятор, да и программист, сопрово>едаюш,ий программу, тоже в ней не разберется.
Убедитесь, что вы знаете, что делаете.
^ ^ / ^ |
# |
• - ^ правление ходом выполнения программы С+ +
Темы данной главы
•^ Операторы и выражения •^ Условные операторы »<^ Итерация
ь^ Операторы перехода в С++
^Итоги
) ^ \ ^ |
предыдуш,ей главе обсуждались основы программирования на C+ + : |
ш ^5fc-'^^"bi данных и операции, позволяющие комбинировать значения раз-
^^^^^^^^ личных типов в выражения. В данной главе рассматривается следую щий уровень программирования — реализация алгоритмов для принятия решений и выполнения различных сегментов кода в зависимости от внешних обстоятельств.
Правильное использование управляющих конструкций — один из наиболее важных факторов, определяющих качество программного кода. Когда операторы выполняются последовательно, поочередно, программисту, сопровождающему ПО, достаточно легко в нем разобраться. В каждом сегменте программы есть только один набор начальных условий и, следовательно, один результат вычислений. Однако такие последовательные программы примитивны и мало на что способны. В реальной ситуации нужно выполнять те или иные сегменты кода в зависимости от каких-то условий. Чем более гибок язык программирования с точки зрения управляющих структур, тем больше возможностей в руках программиста.
Когда один сегмент программы выполняется после того или иного сегмента, то наборов начальных условий несколько и возможных результатов вычислений тоже несколько. Запоминать все эти альтернативы становится трудно. Програм мисты делают ошибки при разработке программы, а те, кто занимается ее сопро вождением, ошибаются при чтении исходного кода и внесении изменений. Вот почему современные языки программирования ограничивают возможности про граммиста при передаче управления от одного сегмента программы к другому. Такой подход называется структурным программированием. Программист использует лишь небольшой набор строго заданных конструкций (циклов и опе раторов условия), и каждый сегмент программного кода имеет только один вход (или два) и один выход (или два).
96ль I« ВшвА^име в програ1У1^ирование на C++
ВC + + реализован компромиссный подход. Он предлагает богатый набор конструкций, позволяющий управлять выполнением программы. Эти конструк ции обладают достаточной гибкостью и мощностью для реализации сложных вариантов принятия решений в программе. В то же время они достаточно строгие
ине способствуют чрезмерной изощренности программы, затрудняющей ее пони мание и сопровождение.
Операторы и выражения
в отличие от других языков в C + + разница между выражением и выполняе мым оператором мала: любое выражение можно превратить в оператор, добавив точку с запятой. Вот некоторые примеры допустимых выражений и допустимых в C + + выполняемых операторов:
X * у |
/ / |
выражение, |
которое можно использовать в других выражениях |
|
X * у; |
/ / |
оператор (достаточно бесполезный) |
||
а = X * у |
/ / |
выражение, |
которое можно использовать в других выражениях |
|
а = X * у; |
/ / |
оператор, |
полезный и распространенный |
|
X++ |
/ / |
выражение, |
которое можно использовать в других |
|
|
/ / |
выражениях |
(только аккуратно) |
|
Х++; |
/ / |
оператор, |
полезный и распространенный |
|
foo() |
/ / |
вызов функции, |
возвращающей значение (допустимое выражение) |
|
foo();? |
/ / |
вызов функции, возвращающей неиспользуемое значение |
||
|
/ / |
(допустимый оператор) |
||
; |
/ / |
пустой оператор, допустимый, но только запутывающий |
||
Как и в других языках, в C + + |
операторы выполняются последовательно, |
в том порядке, как они записаны в исходном коде. Логически каждый оператор представляет собой целую, непрерываемую единицу выполнения.
Выполняемые операторы группируются в блоки (составные операторы). Блоки должны ограничиваться фигурными скобками. Синтаксически блок операторов интерпретируется как один оператор и может использоваться там, где предпола гается один оператор. Каждый оператор — это блок, завершаемый точкой с за пятой, но за закрывающей фигурной скобкой блока операторов точка с запятой не ставится.
Объединение операторов в блок дает два важных преимущества. Во-первых, можно использовать блок с несколькими операторами в том месте, где допускает ся только один оператор. Во-вторых, можно определять в блоке локальные пере менные. Имена таких переменных не будут конфликтовать с именами переменных, определенных в другом месте программы. Первое свойство критически важно для написания управляющих операторов. Без этого невозможно было бы создать ни какой реальной программы. Второе свойство имеет важное значение при написа нии функций. Без него также не написать реальной программы. Вот обобщенная синтаксическая форма составного оператора:
{ локальные определения и объявления (если они имеются); |
|
|
операторы завершаются точкой с запятой; } |
/ / |
в конце нет |
|
/ / |
точки с запятой |
Составной оператор можно использовать как тело функции, как вложенный блок внутри функций или как тело управляющего оператора. Если поставить после завершающей фигурной скобки точку с запятой, то в большинстве случаев это не повредит. Появится лишь пустой оператор, не генерирующий объектный код. Но иногда такая точка с запятой может изменить смысл операторов, так что лучше не использовать ее после закрывающей фигурной скобки (нужно запомнить исключения, когда такая точка с запятой необходима, как, например, в определе нии класса и в некоторых других случаях).
Глава4 • Управление ходом выполнения программы C+-f |
97 |
Составные операторы вычисляются как один оператор — после предыдущего оператора и перед следующим. Внутри блока выполнение также происходит по следовательно, в лексическом порядке операторов.
С-(-+ предусматривает стандартный набор операторов управления, которые могут менять ход выполнения программы. Они включают в себя:
условные операторы: if, if-else циклы: while, do-while, for
переходы: операторы goto, break, continue, return
код с несколькими точками входа: оператор switch с ветвями case
В конструкции с условиями, в зависимости от булева выражения в условии, оператор может выполняться один раз или пропускаться. В цикле оператор вы полняется один или несколько раз, в зависимости от булева выражения цикла. Булево выражение — это выражение, возвращающее true или false. Его часто называют логическим выражением, выражением условия или просто выражением. В C-f-f любое выражение можно использовать как булево, что значительно уве личивает гибкость операторов условия и циклов. В других языках применение небулева выражения там, где предполагается булево выражение, даст синтаксиче скую ошибку.
В операторе switch в зависимости от результата вычисления целочисленного выражения выбираются соответствующие ветви case. Операторы перехода меня ют ход выполнения программы без всякого условия. Часто они используются в сочетании с некоторыми другими управляющими конструкциями (условным оператором, оператором цикла или переключателем switch).
Таким образом, для всех управляющих конструкций область действия состав ляет лии1ь один оператор. Если логика алгоритма требует выполнения нескольких операторов после проверки логического выражения, то можно использовать со ставной оператор в фигурных скобках. После закрывающей фигурной скобки точки с запятой не требуется, но каждый оператор в блоке (включая последний) должен завершаться точкой с запятой.
В остальной части данной главы рассмотрены отдельные типы операторов управления выполнением программы С+Н-, даны конкретные рекомендации, что делать и что не следует делать при применении этих управляющих операторов в коде C+-f.
Условные операторы
Условные операторы являются, вероятно, наиболее распространенными управ ляющими конструкциями в программах С++ . На самом деле, можно написать лишь незначительную часть программного кода, не прибегая к условным опера торам. Всегда возникает необходимость выполнить то или иное действие в зави симости от какого-то условия.
Существует несколько форм условных операторов, которые можно использо вать в программе С+4-. Сложные виды условных операторов требуют тщательно го тестирования, но их применение часто дает возможность сделать программный код более осмысленным и элегантным.
Стандартные формы условных операторов
Условные операторы в СН-+ в своей наиболее общей форме имеют две ветви: ветвь true и ветвь false. При выполнении условного оператора отрабатывается только одна ветвь.
Вот несколько примеров условных операторов в контексте с предшествующим и последующим операторами:
г |
98 |
1 4 - I W I O I |
|
'гшлтроваиив не
^^^^^^^^^
предыдущии_оператор; |
/ / |
ключевого слова then в C++ нет |
|
|
i f (выражение) |
|
|||
onepaTop_true; |
/ / |
обратите |
внимание на точку с запятой |
перед else |
else |
/ / |
обратите |
внимание на необязательный |
отступ |
onepaTop_false; |
следующий_оператор;
Ключевые слова if и else должны записываться в нижнем регистре. Ключевое слово then в C++ отсутствует. Выражение должно заключаться в круглые скобки.
После выполнения предыдущего_оператора (им может быть все, что угодно, включая одну из управляющих конструкций) вычисляется выражение в скобках. Логически это булево выражение: нужно знать, принимает условие значение true или false. Еслиусловие дает true, то выполняется onepaTop_true, а onepaTop_falseпропускается. Если условие равно false, то выполняется onepaTOp_false, а операTOp_true пропускается. Поскольку мы изучаем C + + , а не Паскаль, Бейсик, Java или PL/I, ТО выражение в условии не обязано быть булевым. Это может быть любое выражение любой сложности. Вычисляется его значение, и любое ненулевое значение (не обязательно целое) интерпретируется как true, а нулевое — false.
После выполнения одного из операторов (onepaTop_false или onepaTop_true) независимо от условия выполняется следующий_оператор. Опять же этим операто ром может быть все, что угодно, включая одну из конструкций управления.
В листинге 4.1 показана программа, запрашивающая у пользователя темпера туру в градусах Цельсия, а затем сообщающая, действительно ли это значение (выше абсолютного нуля, т. е. -273 градуса по Цельсию).
Листинг 4 . 1 . Оператор условия
#inclucle <iostream> using namespace std;
int main |
() |
|
|
|
|
|
|
||
{ |
|
|
|
|
|
|
|
|
|
int |
eels; |
|
|
|
|
|
|
||
cout |
« |
"\пВведите температуру в градусах Цельсия: "; |
|
|
|||||
cin |
» |
eels; |
|
eels « endl; |
|
|
|||
cout « |
"\пВы ввели значение " « |
|
|
||||||
if (eels < -273) |
|
"недопустимо\п" |
|
|
|||||
cout «"\пЗначение " «eels « |
/ / |
нет ; |
|||||||
else |
« |
"Оно меньше абсолютного нуля\п"; |
/ / |
один оператор |
|||||
|
cels«" - допустимая температура\п"; |
|
|
||||||
cout « |
|
|
|||||||
cout « |
"Спасибо, чтовоспользовались программой" «endl; |
|
|
||||||
return 0; |
|
|
|
|
|
|
|||
|
|
|
Обратите внимание на использование ESC-последовательности перевода на |
||||||
|
|
|
новую строку в начале и в конце строк в двойных кавычках, выводимых объектом |
||||||
|
|
|
cout, а также на применение манипулятора endl в конце программы. Если опера |
||||||
Введите температуру в градусах Цельсия: 20 |
|
ционная система не использует буферизацию вывода, |
|||||||
|
то ме>кду ESC-символом новой строки ' /п' и манипу |
||||||||
Вы ввели значение 20 |
|
|
лятором endl разницы нет. При буферизации endl |
||||||
20 -допустимая температура |
программой |
|
посылает вывод в буфер и "сбрасывает" его, когда |
||||||
Спасибо, что |
воспользовались |
|
он заполняется. Иногда это повышает производитель |
||||||
|
|
|
|
|
|
ность программы, но многие программисты не беспо |
|||
Рис. 4.1. Вывод |
программЫу |
|
коятся об этой разнице. |
|
|
||||
|
Вывод программы представлен на рис. 4.1. |
||||||||
представленной |
в листинге |
4.1 |
|||||||
|
|
|
Глава 4 • Управление ходогм! вьтоАнеиия программы C++ |
99 |
|
Обратите внимание на отступы в обобщенном примере условного |
оператора |
|
и в листинге 4.1. Обычно ключевые слова if и else |
выравниваются |
на тот же |
уровень, что и предыдущий оператор. OnepaTop_true и onepaTOp_false |
часто вы |
|
равнивают на несколько позиций вправо. Это делает программу более понятной |
||
для сопровождающего ее программиста (и для самого разработчика во время от |
||
ладки). Глубина выравнивания — дело вкуса. По идее, двух пробелов достаточно. |
||
При более глубоком отступе уменьшится размер строки, особенно, если исполь |
||
зуются вложенные управляющие конструкции, либо сами операторы |
t r u e / f a l s e |
|
представляют собой условные операторы, циклы или переключатели. |
|
|
Заметим, что когда вводится недопустимое значение температуры, |
программа |
|
выводит две строки. Для этого выполняются операторы: |
|
|
cout «'ЛпЗначение " «eels « " недопустимо\п"; |
/ / ; в конце |
|
cout « |
"Оно меньше абсолютного нуля\п"; |
|
|
|
|
/ / |
2 оператора |
|||
|
Если |
операторы |
записываются |
таким |
образом, то они должны |
заключаться |
|||||
|
в фигурные скобки, т. е. оформляться как составной оператор. Причина в том, что |
||||||||||
|
когда программный код используется как часть условного оператора, в каждой |
||||||||||
|
ветви есть место только для одного оператора, а не для двух. |
|
|
||||||||
|
А в листинге 4.1 используется |
другая техника. Оператор cout может быть |
|||||||||
|
сколь угодно длинным и занимать несколько строк (важно лишь, чтобы разрыв |
||||||||||
|
строки попадал между компонентами оператора, а не оказывался в середине |
||||||||||
|
лексемы). Это означает, что некорректно разбивать строку посередине. Но если |
||||||||||
|
нужно выводить две строки, то с этим все в порядке. |
|
|
|
|||||||
|
OnepaTop_false не обязателен. Если некоторые действия должны |
выполняться |
|||||||||
|
только тогда, когда булево выражения равно true, его можно опустить. Вот обоб |
||||||||||
|
щенная форма условного оператора без onepaTopa_f alse: |
|
|
||||||||
|
предыдущий_оператор; |
|
|
|
|
|
|
|
|||
|
i f (выражение) |
|
|
|
|
|
|
|
|
||
|
onepaTop_true; |
|
|
|
|
|
|
|
|
||
|
следующий_оператор; |
|
|
|
|
|
|
|
|
||
Этот условный оператор не содержит ключевых слов |
Введите температуру |
в градусах |
Цельсия: 20 |
||||||||
then или else . |
Листинг 4.2 |
показывает |
урезанную |
||||||||
|
|
|
|
|
|
|
|||||
версию программы из листинга 4.1. Пользователь по |
Вы ввели значение 20 |
|
|
|
|||||||
лучает предупреждение о неверном вводе (т. е. тем |
Спасибо, что |
воспользовались программой |
|||||||||
пература ниже абсолютного нуля), но программа |
|
|
|
|
|
|
|
||||
выполняет свою |
задачу. (Для простоты здесь ото- |
п.,^ |
>i о |
г, |
г» |
|
|
|
|||
^ |
|
1 |
ч тл |
гИС. A.Z. |
Вывод |
программы, |
|
||||
бражается только заключительная фраза.) Результат |
|
|
|
представленной |
в листинге 4.2 |
||||||
выполнения показан на рис. 4.2. |
|
|
|
|
|
|
|
|
|||
Листинг 4.2. |
Условный оператор без части else |
|
|
|
|
|
|
|
#inclucle <iostream> using namespace std;
#define ABSOLUTE_ZERO -273 int main ()
{
int eels;
cout « |
"\пВведите температуру в градусах Цельсия: "; |
|
|
cin » |
eels; |
eels « endl; |
|
cout « |
"\пВы ввели значение " « |
|
|
if (eels < ABSOLUTE.ZERO) |
" недопустимо\п" |
|
|
cout «"\пЗначение " «eels « |
// 1 оператор |
||
cout « |
« "Оно меньше абсолютного нуля\п"; |
||
"Спасибо, чтовоспользовались программой" «endl; |
|
||
return 0; |
|
|