Управление потоком достаточно простое и обычно включает условие в круглых скобках и блок выполняемого кода в фигурных скобках.

Эти фигурные скобки составляют новую область видимости, в которой можно вводить новые переменные, например:

it (Х == 7) {
inti = О;
i += l;
}

После закрывающей фигурной скобки в четвертой строке переменная i, объявленная во второй строке, прекращает свое существование, так как ее область видимости располагается в этих фигурных скобках. Если содержимое фигурных скобок состоит из одной инструкции, то скобки можно опустить, но я не советую новичкам это делать, так как при этом очень легко запутаться. Распространенная ошибка новичков (которую, к счастью, отлавливает компилятор) - отсутствие круглых скобок вокруг условия. Полный набор инструкций управления потоком приводится в главе 3 KO-R, и 11 просто подытожу их здесь в примере 1.1.

 

Пример 1.1. Конструкции управления потоком языка программирования C

if (условие) {
инструкции;
if (условие) {
инструкции;
} else {

инструхции; if (условие) { инструкции; else if (условие) инструкции; else { инструкции; while (условие) инструкции; } do { инструкции; ) while (условие); for (перед циклом; условие; после каждой интеграции) { инструкции;

Структура i f ... е 1 s е i f ... еlse может иметь любое необходимое количество блоков е 1 s е i f, и блок е 1 s е является необязательным. Вместо расширенной структуры if ... else if ... else if ... else, в случае, когда условия представляют собой сравнение единственной переменной с разными значениями, можно использовать конструкцию switch; однако при ее применении будьте осторожны, так как она достаточно запутанная и в ней легко ошибиться (за подробностями обратитесь к K&R 3.4). Главное - не забывать заканчивать каждый блок case инструкцией break, если только вы не хотите "провалиться" в следующий блок case (пример 1.2).

 

 

Пример 1 .2. Инструкция swltch

NSStrinq* key;
switch (taq) {
case 1: { // т.е. еспи taq равно 1
key • @"lesson";
break;
case 2: { // т.е. если taq равно 2
key • @"lessonsection";
break1
case 3: 1 11 т.е. если taq равно З
key • @"lessonSectionPartFirstWord";
break;

Цикл fоr в языке программирования С для новичков требует некоторой работы для понимания (см. пример 1.1). Инструкция перед циклом выполняется однократно, когда программа встречается с циклом, и обычно используется для инициализации счетчика. Затем проверяется условие, и если оно истинно, выполняется блок кода; обычно в условии проверяется, не достиг ли счетчик определённого граничного значения. После этого выполняется инструкция после каждой итерации, которая обычно применяется для увеличения или уменьшения счетчика; непосредственно за этим вновь проверяется условие. Таким образом, для выполнения блока, в котором переменная i принимает целые значения 1, 2, 3, 4 и 5, i используется следующий код:

int i;

for (i = 1; i < 6; i++) { // ... Инструкции ... }

Потребность в счетчике, существование которого ограничено только рамками цикла, столь распространено, что стандарт С99 допускает объявление счетчика как часть инструкции перед циклом; область видимости объявленной переменной ограничена только кодом в фигурных скобках и инструкциями в круглых скобках заголовка цикла:

for (int i • 1; i < 6; i++)
// ... Инструкции ...
}

Цикл for является одной из немногих областей, в которых Objective-C расширяет синтаксис управления потоком языка программирования С. Некоторые объекты Objective-C, такие как NSArray, представляют перечислимые коллекции других объектов; "перечислимый" в данном случае означает, что можно выполнить цикл по элементам коллекции, и выполнение такого цикла и есть перечисление элементов коллекции. (Основные типы перечислимых коллекций рассматриваются в главе 10. Для упрощения перечисления Objective-C предоставляет конструкцию for…in, которая работает аналогично циклу:

SomeType* oneitem;
for (oneitem in myCollection) {
// ... Инструкции ....
}

При каждой итерации цикла переменная oneitem (или как вы ее назовете) получает очередное значение из коллекции. Как и в цикле for стандарта С99, переменную oneitem можно объявить в заголовке цикла for, ограничивая тем самым ее область видимости фигурными скобками цикла:

for (SomeType* oneitem in myCollection)
// ... Инструкции ...<
}

Для досрочного прекращения работы цикла используется инструкция break. Для досрочного прекращения работы текущей итерации в фигурных скобках и перехода к следующей итерации цикла используется инструкция continue. В случае циклов while и do инструкция continue означает немедленное выполнение проверки условия цикла; в цикла for инструкция continue означает немедленное выполнение инструкции после каждой итерации, а затем проверку условия цикла.

В языке программирования С имеется также инструкция goto, которая позволяет перейти к именованной (с помощью метки) строке вашего кода (K&R 3.8); несмотря на то, что goto заведомо "рассматривается ш вредная возможность~ бывают ситуации, в которых она необходима, в основном из-за примитивности управления потоком в С.

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

Вернемся теперь к вопросу о том, что собой представляет условие. В языке программирования С нет отдельного логического (булева) типа; вычисление условия либо дает значение О, рассматриваемое ш ложь, либо ненулевое значение, рассматриваемое как истина. Сравнения выполняются с помощью операторов эквивалентности и отношений (K&R 2.6); например, оператор == выполняет проверку на равенство, а оператор < выполняет проверку того, что первый операнд меньше второго. Логические выражения можно комбинировать с помощью операторов логического "И"(&&) и логического "ИЛИ"; применяя эти операторы вместе со скобками и оператором логического отрицания (!), можно формировать сложные условия. Вычисление выражений логического "И" и логического "ИЛИ" сокращенное, т.е. если левое условие однозначно определяет все выражение (ложное в случае "И" или истинное в случае "ИЛИ"), то правое условие не вычисляется.

Не перепутайте операторы логического "И" (&&) и логического "ИЛИ" (1 1) с операторами побитового "И"(&) и побитового "ИЛИ" (1), которые рассматривались ранее. Если вы напишете&, подразумевая && (или наоборот). то можете получить результаты, которые вас немало удивят. Оператор проверки равенства == отличается от обычного одинарного знака равенства; забыть об этом различии - одна из распространенных ошибок начинающих. Основная проблема в том, что код при этом остается корректным: простое присваивание, которое подразумевает одинарный знак равенства, имеет значение, и это значение вполне можно использовать в качестве условия. Рассмотрим следующий (бессмысленный) фрагмент кода:

int i = О;
while (i = 1) {
i = О;
}

На первый взгляд начинающий программист может решить, что условие в цикле while проверяет, не равно ли значение i единице. Затем он может рассуждать так: значение i при входе в цикл равно нулю, так что ЦИIСЛ не будет выполнен ни разу. Верно? Нет. Условие в цикле while не проверяет, равно ли значение i единице, а присваивает i это единичное значение. Значение всего выражения присваивания также равно единице, так что условие цикла равно единице, что означает истину. Таким образом, тело цикла будет выполнено, и переменная i станет равной нулю. Но это ничего не значит, так как очередное вычисление условия снова присвоит переменной i единичное значение, условие будет истинно, и будет выполнена очередная итерация цикла. И так до бесконечности, так что программа просто зависает.

Программисты на С наслаждаются тем, что проверка на равенство нулю, и проверка на ложность представляют собой одно и то же, и используют этот факт для создания компактных условных выражений, которые считаются элегантными и идиоматичными. Такие идиомы могут запутывать неискушенного программиста, но одна из них очень часто используется в Objective-C, а именно для проверки ссылки на объект, не является ли она пустой, имеющей значение nil. Поскольку значение пустой ссылки нулевое (см. главу 3), проверить, является ли ссылка s равной nil, можно следующим образом:

if ( !s) {
// ...
}

В языке Objective-C введен тип 8001, который вы должны использовать, если нужно сохранить значение условия как переменную, и константы YES и NO (представляющие значения 1 и 0), используемые при установке значения логического типа. Не сравнивайте никакие значения со значениями типа 8001, даже YES и NO, поскольку значение наподобие 2 представляет собой истину, но при этом не равно ни YES, ни NO. (Выполнение этих действий - распространенная ошибка начинающего программиста, которая может привести к нежелательным результатам, причину которых будет очень трудно найти.) Используйте переменную типа 8001 непосредственно в качестве условия или как часть сложного условия, и все будет хорошо. Например:

BOOL isnil = (nil == s);
if (isnil) {
// не так: if (isnil == YES)
// ...
}

 

 

 

Добавить комментарий