Программирование на Objective-C 2.0
Шрифт:
Вывод программы 6.2 1/4 0.25 0/0 = 0
После присваивания aFraction значения 1/4 используется метод convertToNum, чтобы преобразовать эту дробь в десятичное значение. Затем это значение выводится как 0.25.
Во втором случае значение bFraction не задано явным образом, поэтому его числителю и знаменателю присваивается значение 0, что происходит по умолчанию для переменных экземпляра. Это объясняет результат метода print, а оператор if в методе convertToNum возвращает значение 0. Конструкция if-else
Если нужно сказать, является ли число четным или нечетным, вы, скорее всего, определите это по последней цифре числа. Если эта цифра равна 0, 2,4,6 или 8, значит, число является четным.
На компьютере это можно сделать проще: достаточно проверить, делится ли это число на 2 без остатка. Если да, то число является четным, иначе оно является нечетным.
Вы уже видели, как использовать оператор взятия по модулю (%) для вычисления остатка отделения одного целого числа на другое. Его удобно использовать, чтобы определить, делится ли число на 2 без остатка. Если остаток от деления на 2 равен 0, значит, это четное число, если нет — нечетное.
Напишем программу, которая
Вывод программы 6.3 Enter your number to be tested: (Введите ваше число для проверки) 2455 The number is odd. (Число является нечетным)
Вывод программы 6.3 (повторный запуск) Enter your number to be tested: 1210 The number is even. (Число является четным)
После ввода числа вычисляется остаток отделения на 2. Первый оператор if проверяет, равно ли нулю значение этого остатка. Если да, то выводится сообщение «The number is even.» (Число является четным).
Второй оператор if проверяет значение этого остатка на неравенство нулю. Если да, то выводится сообщение, что число является нечетным.
Если выполняется первый оператор if, то второй оператор не должен выполняться, и наоборот. При написании программ концепция «иначе» («else») требуется настолько часто, что почти во всех современных языках программирования введена специальная конструкция для этой ситуации. В Objective-C это конструкция if-else, которая имеет следующий формат. if (выражение) программный оператор 1 else программный оператор 2
На самом деле if-else является просто расширением общего формата оператора if. Если результатом оценки выражения является значение TRUE, то выполняется программный оператор /; иначе выполняется программный оператор 2. Во всех случаях выполняется программный оператор 1 или программный оператор 2, но не оба оператора.
Оператор if-else можно вставить в предыдущую программу, заменив два оператора if на один оператор if-else. Эта новая конструкция в некоторой степени упрощает программу и делает ее более удобной для чтения. // Программа, определяющая, является ли число четным или нечетным (Версия 2) #import <Foundation/Foundation.h> int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int number_to_test, remainder; NSLog (@"Enter your number to be tested:"); scanf ("%i", &number_to_test); remainder = number_to_test % 2; if ( remainder == 0 ) NSLog (@"The number is even."); else NSLog (@"The number is odd."); [pool drain]; return 0; }
Вывод программы 6.4 Enter your number to be tested: (Введите ваше число для проверки) 1234 The number is even. (Число является нечетным)
Вывод программы 6.4 (повторный запуск) Enter your number to be tested: 6551 The number is odd. (Число является четным)
He забывайте, что двойной знак равенства (==) - это проверка на равенство, а одинарный знак равенства — это оператор присваивания. Если случайно использовать оператор присваивания внутри оператора if, то может возникнуть множество проблем. Составные операции сравнения
До сих пор в операторах if использовались простые операции сравнения между двумя числами. В программе 6.1 сравнивалось значение числа с нулем, а в программе 6.2 выполнялось сравнение с нулем знаменателя дроби. Иногда необходимы более сложные проверки. Предположим, что нужно вычислить количество экзаменационных оценок в диапазоне от 70 по 79. В данном случае нужно сравнить значение оценки не с одним пределом, а с двумя (70 и 79), чтобы проверить, попадает ли она в указанный диапазон. В Objective-C имеется механизм для составных операторов сравнения этого типа. Составная операция сравнения (compound relational test) — это несколько операций сравнения, объединенных логическим оператором AND или 0R. Эти операторы представлены парой символов && или || (два вертикальных штриха). Н апример, следующий оператор увеличивает значение переменной grades_70_to_79 (оценки от 70 по 79), только если значение grade (оценка) больше или равно 70 и меньше или равно 79). if ( grade >= 70 && grade <= 79 ) ++grades_70_to_79; А следующий оператор вызывает выполнение оператора NSLog, если index меньше 0 или больше 99. if ( index < 0 || index > 99 ) NSLog (@"Error - index out of range"); (Ошибка - индекс вне диапазона) Составные операторы можно использовать в Objective-C для формирования очень сложных выражений. Не злоупотребляйте этим. Более простые выражения всегда проще читать и отлаживать.При формировании составных выражений сравнения можно неограниченно использовать круглые скобки, чтобы повысить удобство чтения выражений и избежать осложнений из-за ошибочных предположений о старшинстве операторов в выражении. (Оператор && имеет более низкий приоритет, чем любой арифметический оператор или оператор отношения, но более высокий приоритет, чем оператор ||.) Пробелы также повышают удобочитаемость выражения. Дополнительные пробелы вокруг операторов && и || визуально отделяют эти операторы от выражений, которые они связывают. Чтобы показать использование составных операций сравнения на конкретном примере, мы напишем программу, которая проверяет, является ли определенный год високосным, если он делится на 4 без остатка. Год, который делится на 100, не является високосным годом, если он не делится также на 400. Необходимо продумать, как проверять эти условия. Во-первых, можно сосчитать остатки (remainder) отделения года на 4, 100 и 400 и присвоить эти значения соответствующим переменным, например, rem_4, remJOO и rem_400. Затем можно проверить эти переменные, чтобы выяснить, отвечают ли эти остатки критериям високосного
int main (int argc, char argv[]) { NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init]; int year, rem_4, remJOO, remJOO; NSLog (@"Enter the year to be tested:"); scant ("%i", &year); rem J = year % 4; remJOO = year % 100; remJOO = year % 400; if ( (rem 4 == 0 && remJOO != 0) || remJOO == 0 ) NSLog ((ant’s a leap year."); else NSLog (@"Nope, it’s not a leap year."); [pool drain]; return 0; } Вывод программы 6.5 Enter the year to be tested: (Введите год для проверки) 1955 Nope, it’s not a leap year. (Нет, это не високосный год) Вывод программы 6.5 (повторный запуск) Enter the year to be tested: 2000 It’s a leap year. (Это високосный год) Вывод программы 6.5 (повторный запуск) Enter the year to be tested: 1800 Nope, it’s not a leap year. (Нет, это не високосный год) В приведенных примерах вводится 1955-й год, который не является високосным, поскольку он не делится нацело на 4, 2000-й год, который является високосным, поскольку он делится нацело на 400, и 1800-й год, который не является високосным, поскольку он делится нацело на 100, но не на 400. В качестве последнего варианта следует проверить год, который делится нацело на 4, но не на 100. Выполните эту проверку самостоятельно. Objective-C дает программисту очень высокий уровень гибкости при формировании выражений. Например, в приведенной выше программе вместо вычисления промежуточных результатов rem_4, remJOO и rem_400 можно было бы сделать все непосредственно в операторе if: if (( year % 4 == 0 && year % 100 != О ) || year % 400 == 0 ) Использование пробелов для разделения отдельных операторов делает это выражение более удобным для чтения. Если игнорировать эти возможности и удалить необязательный набор круглых скобок, то получится следующее выражение: if(year%4==0&&year%100!=0)||year%400==0) Это выражение действует точно так же, как предыдущее выражение, однако дополнительные пробелы очень упрощают восприятие составных выражений. Вложенные операторы if
При рассмотрении общего формата оператора if мы указывали, что если результатом оценки выражения в круглых скобках является значение TRUE, то выполняется следующий оператор. Этим программным оператором может быть еще один оператор if, как в следующих строках. if ( [chessGame isOver] == NO ) ([игра в шахматы окончена] == НЕТ) if ( [chessGame whoseTurn] == YOU )([... чей ход] == ВАШ) [chessGame yourMove]; ([... ваш ход]) Если значение, возвращаемое после отправки сообщения isOver объекту chessGame, равно N0, то выполняется следующий оператор; в свою очередь, этот оператор является еще одним оператором if. Этот оператор if сравнивает значение, возвращаемое методом whoseTurn, со значением YOU. Если эти два значения равны, то объекту chessGame отправляется сообщение yourMove. Таким образом, сообщение yourMove отправляется только в том случае, если игра не окончена, и это ваш ход. Эти операторы можно было бы записать с помощью составной операции сравнения: if ( [chessGame isOver] == N0 && [chessGame whoseTurn] == YOU ) [chessGame yourMove]; Обычно с вложенными операторами if используют предложение else, как показано ниже. if ( [chessGame isOver] == N0 ) ([игра в шахматы окончена] == НЕТ) if ( [chessGame whoseTurn] == YOU )([... чей ход] == ВАШ) [chessGame yourMove]; ([... ваш ход]) else [chessGame my Move]; ([... мой ход]) Сначала все выполняется, как и раньше, но если игра не окончена и ход не ваш, то выполняется предложение else. В результате сообщение myMove отправляется объекту chessGame. Если игра окончена, то пропускается весь следующий оператор if вместе с присоединенным к нему предложением else. Предложение else связано с оператором if, который проверяет значение, возвращаемое методом whoseTurn, а не с оператором if, который проверяет, окончена ли игра (chessGame isOver). Общее правило состоит в том, что предложение else всегда связывается с последним оператором if, не содержащим else. Можно продвинуться еще на один шаг и добавить предложение else к внешнему оператору if. Это предложение else выполняется, если игра окончена. if ( [chessGame isOver] == NO ) ([игра в шахматы окончена] == НЕТ) if ( [chessGame whoseTurn] == YOU )([... чей ход] == ВАШ) [chessGame yourMove]; ([... ваш ход]) else [chessGame myMove]; ([...мой ход]) else [chessGame finish]; (... конец) Конечно, система может интерпретировать этот оператор и по-другому. Например, если в предыдущем примере удалить первое предложение else, то оператор не будет интерпретироваться в соответствии с показанными отступами. if ( [chessGame isOver] == NO ) if ( [chessGame whoseTurn] == YOU ) [chessGame yourMove]; else [chessGame finish]; Вместо этого оператор будет интерпретироваться следующим образом: if ( [chessGame isOver] == NO ) if ( [chessGame whoseTurn] == YOU ) [chessGame yourMove]; else [chessGame finish]; Предложение else связывается с последним оператором if, не включающим else. Можно использовать фигурные скобки, чтобы связать else с внешним if, а не с внутренним. Фигурные скобки замыкают оператор if, который находится внутри них. Нужная последовательность задается с помощью следующего оператора. if ( [chessGame isOver] == NO ) { if ( [chessGame whoseTurn] == YOU ) [chessGame yourMove]; } else [chessGame finish]; Конструкция else if