|
|
| Строка 1: |
Строка 1: |
| − | В этой главе будут рассмотрены основные синтаксические конструкции, которые так или иначе присутствуют в любом современном языке программирования, будь то функциональный или объектно-ориентированный язык. Это констркции условного перехода и циклы. Без подобных конструкций (или их аналогов) невозможно написать программу, сколько-нибудь сложнее чем "Hello world".
| + | A few years ago I'd have to pay soomene for this information. |
| − | | + | |
| − | __TOC__
| + | |
| − | | + | |
| − | == Условный оператор ==
| + | |
| − | | + | |
| − | Условный оператор — это основа основ любого языка программирования. На основании условия, то есть значения некоторого выражения, принимается решение, куда следует двигаться программе. В основе всех условных операторов лежит булева логика, при которой любое утверждение сводится к двум понятиям: истина и ложь. Если условие истинно, то управление программы движется в одну сторону. Если условие ложно — в другую. Таким образом, в каждый момент времени делается выбор всего из двух направлений. Более сложные условия строятся путем последовательного прохождения элементарных, двоичных условий.
| + | |
| − | | + | |
| − | === Оператор if ===
| + | |
| − | | + | |
| − | В языке K++, для проверки условия служит оператор <tt>'''if'''</tt>, так же называемый условным оператором. Синтаксис этого оператора знаком наверное любому человеку, который имеет хоть какое-то представление о языках программирования:
| + | |
| − | <source lang="kpp">
| + | |
| − | if (/* выражение условия */) {
| + | |
| − | /* тело оператора */
| + | |
| − | }
| + | |
| − | </source>
| + | |
| − | | + | |
| − | Если в коде программы встречается условный оператор, то первым делом происходит вычисление значения его условия — выражения, заключенного в круглые скобки. В качестве такого выражения, может быть указано любое выражение, которое возвращает значение. Если значение условного выражения можно трактовать как истину, то управление передается телу оператора, заключенному в фигурные скобки (в случае единственного выражения в теле оператора, фигурные скобки можно опустить). Если же значение условия ложно — управление передается следующему выражению, стоящему после условного оператора (то есть, тело оператора просто пропускается).
| + | |
| − | | + | |
| − | Истинным, считается любой существующий объект, а так же логические [[Типы операторов#Операторы сравнения|операторы сравнения и отношения]] (такие как <tt>==</tt>, <tt>!=</tt>, <tt><</tt> и т. д), если их значение истинно (то есть, объекты соответствуют указанному отношению), а так же специальное ключевое слово <tt>'''true'''</tt>, которое считается истинным всегда. Исключением является объект типа bool, имеющий в данный момент значение <tt>'''false'''</tt>.
| + | |
| − | | + | |
| − | Ложными, соответственно, считаются несозданные объекты (пустые указатели), а так же операторы отношения, если их значение ложно (объекты не соответствуют отношению). Ложными так же считаются объекты, соответствующие ключевым словам <tt>'''false'''</tt> и <tt>'''null'''</tt>. Опять же, исключением является объект типа bool, если он имеет значение <tt>'''true'''</tt>.
| + | |
| − | | + | |
| − | Для ясности приведем несколько выражений, а так же укажем соответствующие им логические значения:
| + | |
| − | <source lang="kpp">
| + | |
| − | //Выражение булево значение
| + | |
| − | true true
| + | |
| − | false false
| + | |
| − | null false
| + | |
| − | var x; x false
| + | |
| − | var y; y = 1; true
| + | |
| − | var int z; z true
| + | |
| − | var bool x; false
| + | |
| − | var bool x; x = true; true
| + | |
| − | 0 true
| + | |
| − | 1 true
| + | |
| − | "hello world" true
| + | |
| − | 0 == 1 false
| + | |
| − | 5 < 6 true
| + | |
| − | 2 > 3 false
| + | |
| − | 5 >= 5 true
| + | |
| − | 'a' != 'b' true
| + | |
| − | </source>
| + | |
| − | | + | |
| − | Обратите внимание на следующие моменты:
| + | |
| − | * Неинициализированная динамическая переменная ''x'' считается ложной (равна <tt>'''null'''</tt>)
| + | |
| − | * Инициализированная динамическая переменная ''y'' считается истинной (объект создан)
| + | |
| − | * Неинициализированная статическая переменная ''z'' считается истинной (объект создан)
| + | |
| − | * Переменная типа <tt>bool</tt> имеет значение по умолчанию <tt>'''false'''</tt> (хотя объект создан)
| + | |
| − | * 0, так же как любой другой созданный объект считается '''истиной''', в отличие от C++.
| + | |
| − | * условие 5 >= 5 считается истиной, так как формулируется как "5 больше 5 '''или''' равно 5"
| + | |
| − | | + | |
| − | По поводу нуля следует поговорить отдельно. C++ не является в полной мере объектно-ориентированным языком, фактически, в нем ОО система является абстракцией, позволяющей оперировать все теми же понятиями стандартных типов данных и памяти, но на более высоком уровне. Все что мы имеем на этапе выполнения программы, это кусочки памяти, которые мы считаем объектами. Поскольку числа в нем являются совершенно определенной сущностью, подобные вольности возможны.
| + | |
| − | | + | |
| − | В языке К++ все наоборот. Все с чем он оперирует — это объекты. Провести грань между стандартными типами данных и пользовательскими невозможно. Числа, что фигурируют в программе так же являются объектами. Даже числовые константы которые записываются в выражениях — это тоже объекты (это уже было показано в [[Введение, или краткий обзор#Расширение классов|кратком обзоре]]). За основу логики языка принимается факт существования объекта. Если объекта не существует — значение ложно, если существует — истинно (кроме описанных выше исключений). Оператор <tt>'''if'''</tt> помимо чистой логики, служит для определения существования объекта. Получается, что при таком подходе, делать для нуля исключение нерационально, и более того — это может привести к ошибкам. Возьмем к примеру код:
| + | |
| − | | + | |
| − | <source lang="kpp">
| + | |
| − | if (x) {
| + | |
| − | /* код, соответствущий существованию переменной x */
| + | |
| − | }
| + | |
| − | </source>
| + | |
| − | | + | |
| − | Подразумевается, что тело оператора будет выполнено в случае, если передаваемый объект (вероятнее всего [[Переменные#Нетипированные (динамические) переменные|динамическая переменная]]) инициализирован и существует. Но что будет, если мы передадим в качестве объекта динамическую переменную, содержащую объект типа <tt>int</tt>, равный нулю? Если бы реализация языка обрабатывала значение 0 как ложь, то логика оператора <tt>'''if'''</tt> в частости и всей программы в целом, зависела бы от фактического значения переменной, а соответственно была бы неопределенной и даже непредсказуемой. Получалось бы, что для одних переменных, оператор работает одним образом, а для других — другим. Отладка подобной программы может занять многие часы. А все из-за одной условности.
| + | |
| − | | + | |
| − | Таким образом, можно заключить, что оператор <tt>'''if'''</tt> следует применять для проверки логического выражения, либо для проверки существования переменной. Если мы хотим проверить равенство переменной нулю, то это необходимо делать явно:
| + | |
| − | <source lang="kpp">
| + | |
| − | if (x == 0) {
| + | |
| − | /* что нужно делать, если x равен 0 */
| + | |
| − | }
| + | |
| − | </source>
| + | |
| − | | + | |
| − | And I thought I was the seinsble one. Thanks for setting me straight.
| + | |
| − | | + | |
| − | === Оператор if-elsif-else ===
| + | |
| − | | + | |
| − | Существует так же третья форма условного оператора, которая позволяет проверять несколько условий в единой, более эффективной форме. Это конструкция <tt>'''if-elsif-else'''</tt>:
| + | |
| − | <source lang="kpp">
| + | |
| − | if (/* условие 1 */) {
| + | |
| − | /* код, соответствущий истине условия 1*/
| + | |
| − | } elsif (/*условие 2*/) {
| + | |
| − | /* код, соответствущий истине условия 2*/
| + | |
| − | ...
| + | |
| − | } else {
| + | |
| − | /* код, соответствущий лжи */
| + | |
| − | }
| + | |
| − | </source>
| + | |
| − | Она работает так: сначала проверяется условие 1. Если оно истинно, то выполняется код в первом блоке, а затем управление выходит за рамки всей связки. Если условие 1 ложно, то проверяется условие 2, и т. д. Таким образом, вышеописанная конструкция функционально эквивалентна следующей конструкции, однако более компактна.
| + | |
| − | | + | |
| − | <source lang="kpp">
| + | |
| − | if (/* условие 1 */) {
| + | |
| − | /* если условие 1 истинно */
| + | |
| − | } else {
| + | |
| − | if (/* условие 2 */) {
| + | |
| − | /* если условие 2 истинно */
| + | |
| − | } else {
| + | |
| − | if (/* условие 3 */) {
| + | |
| − | /* если условие 3 истинно */
| + | |
| − | } else {
| + | |
| − | ...
| + | |
| − | }
| + | |
| − | }
| + | |
| − | }
| + | |
| − | </source>
| + | |
| − | | + | |
| − | === Постфиксные операторы ===
| + | |
| − | | + | |
| − | Существует так же более лаконичная форма оператора <tt>'''if'''</tt>, удобная для записи коротких, однострочных условий. При этом, само условие записывается после выражения, которое оно должно проверить:
| + | |
| − | | + | |
| − | <source lang="kpp">
| + | |
| − | /* выражение */ if /* условие */;
| + | |
| − | </source>
| + | |
| − | | + | |
| − | При такой записи, окружать условие скобками не требуется. Проверяемое выражение должно быть единственным, то есть не содержать оператора точка с запятой (<tt>;</tt>). Такие условия занимают меньше места в программе и помогут сделать ваш код более чистым:
| + | |
| − | | + | |
| − | <source lang="kpp">
| + | |
| − | var even_sum = 0;
| + | |
| − | for (var i = 1; i < 100; i++) | + | |
| − | even_sum += i if i % 2 == 0; //сумма всех четных чисел
| + | |
| − | </source>
| + | |
| − | | + | |
| − | Для проверки "невыполнения" условия есть специальная форма постфиксного оператора — <tt>'''unless'''</tt>. Выражение при таком операторе будет выполняться только если условие ложно. Таким образом, смысл оператора прямо противоположен оператору <tt>'''if'''</tt>. Конечно, эти два оператора взаимозаменяемы. Конструкция <tt>do_smth '''if''' x;</tt> делает то же самое что <tt>do_smth '''unless''' !x;</tt>.
| + | |
| − | | + | |
| − | Перепишем предыдущий код с использованием оператора <tt>'''unless'''</tt>:
| + | |
| − | | + | |
| − | <source lang="kpp">
| + | |
| − | var even_sum = 0;
| + | |
| − | for (var i = 1; i < 100; i++)
| + | |
| − | even_sum += i unless i % 2 != 0; //сумма всех четных чисел
| + | |
| − | </source>
| + | |
| − | | + | |
| − | If my problem was a Death Star, this article is a pthoon torpedo.
| + | |
| − | | + | |
| − | FVPIQh <a href="http://qgxpytrzaaps.com/">qgxpytrzaaps</a>
| + | |
A few years ago I'd have to pay soomene for this information.