355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Стивен Кочан » Программирование на Objective-C 2.0 » Текст книги (страница 7)
Программирование на Objective-C 2.0
  • Текст добавлен: 19 сентября 2016, 13:02

Текст книги "Программирование на Objective-C 2.0"


Автор книги: Стивен Кочан



сообщить о нарушении

Текущая страница: 7 (всего у книги 32 страниц)

@interface Calculator: NSObject { double accumulator; } // методы для сумматора (accumulator) -(void) setAccumulator: (double) value; -(void) clear; -(double) accumulator; // арифметические методы -(void) add: (double) value; -(void) subtract: (double) value; -(void) multiply: (double) value; -(void) divide: (double) value; @end @implementation Calculator -(void) setAccumulator: (double) value { accumulator = value; } -(void) clear { accumulator = 0; } -(double) accumulator { return accumulator; } -(void) add: (double) value { accumulator += value; } -(void) subtract: (double) value { accumulator -= value; } -(void) multiply: (double) value { accumulator = value; } -(void) divide: (double) value { accumulator /= value; } @end int main (int argc, char argv[]) { NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init]; double value 1, value2; char operator; Calculator deskCalc = [[Calculator alloc] init]; NSLog (@"Type in your expression."); scant («%lf %c %lf», &value1, &operator, &value2); [deskCalc setAccumulator: valuel]; if ( operator == ) [deskCalc add: value2]; else if ( operator == ) [deskCalc subtract: value2]; else if ( operator =='') [deskCalc multiply: value2]; else if ( operator == '/') [deskCalc divide: value2]; NSLog (@"%.2f", [deskCalc accumulator]); [deskCalc release]; [pool drain]; return 0; } Вывод программы 6.8 Type in your expression. (Введите ваше выражение) 123.5 + 59.3 182.80 Вывод программы 6.8 (повторный запуск) Type in your expression. 198.7/26 7.64 Вывод программы 6.8 (повторный запуск) Type in your expression. 89.3 2.5 223.25 При обращении к scant указывается, что должны быть считаны три значения в переменные valuel, operator и value2. Значение типа double можно прочитать с помощью символов формата %lf. Этот формат считывает значения в переменную valuel, которая является первым операндом выражения. Затем считывается оператор. Поскольку оператор представляется символом или 7 ), а не числом, он читается в символьную переменную operator. Символы формата %с указывают, что нужно прочитать с терминала следующий символ. Пробелы внутри строки формата указывают, что при вводе допускается любое число пробелов. Это позволяет при вводе значений отделять операнды от оператора. После считывания двух значений и оператора программа сохраняет первое значение в сумматоре (accumulator) калькулятора. Затем значение operator сравнивается с четырьмя возможными операторами. Если найдено допустимое со– ответствие, калькулятору передается сообщение для выполнения операции. В последней строке NSLog значение accumulator считывается для вывода. После этого выполнение программы завершается. Здесь необходимо сказать несколько слов о законченности программы. Хотя приведенная программа выполняет поставленную задачу, ее нельзя назвать законченной, поскольку в ней не учитываются ошибки пользователя. Например, что произойдет, если пользователь ошибся и ввел ? в качестве имени оператора? Программа просто пройдет через оператор if, и на терминале не появится никаких ошибок, уведомляющих пользователя, что он ввел недопустимое выражение. Еще один неучтенный случай – это ввод пользователем нулевого значения делителя в операции деления. Программа должна проверять этот случай. Определение ситуаций, при которых возможен отказ программы или получение нежелательных результатов, и принятие предупредительных мер – обязательная часть разработки надежных программ. Программа 6.8А является модифицированной версией программы 6.8. В ней учитываются деление на нуль и ввод неизвестного оператора. Программа 6.8А // Программа вычисления простых выражений в форме // число оператор число import

// Здесь нужно вставить секции interface и implementation // для класса Calculator int main (int argc, char argv[]) NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init]; double value 1, value2; char operator; Calculator deskCalc = [[Calculator alloc] init]; NSLog (@"Type in your expression."); scant («%lf %c %lf», &value1, &operator, &value2); [deskCalc setAccumulator: valuel]; if ( operator =='+') [deskCalc add: value2]; else if ( operator =='-') [deskCalc subtract: value2]; else if ( operator =='’ ) [deskCalc multiply: value2]; else if ( operator == ' / ' ) if ( value2 == 0 ) NSLog (@"Division by zero."); else [deskCalc divide: value2]; else NSLog (@"Unknown operator."); NSLog (@"%.2f", [deskCalc accumulator]); [deskCalc release]; [pool drain]; return 0; } Вывод программы 6.8A Type in your expression. (Введите ваше выражение) 123.5 + 59.3 182.80 Вывод программы 6.8А (повторный запуск) Type in your expression. 198.7/0 Division by zero. (Деление на нуль) 198.7 Вывод программы 6.8А (повторный запуск) Type in your expression. 125 $28 Unknown operator. (Неизвестный оператор) 125 Если введен оператор деления (слэш), то проверяется, не равно ли нулю значения value2. Если равно, выводится соответствующее сообщение; если нет – выполняется операция деления и выводятся результаты. Обратите внимание, как в данном случае вложены оператор if и предложения else. Предложение else в конце программы позволяет «уловить» любые непредусмотренные случаи. Поэтому любое значение переменной operator, которое не совпадает с одним из четырех символов вычислений, приводит к выполнению предложения else, и на терминал выводится сообщение «Unknown operator» (Неизвестный оператор). Более удобный способ обработки ситуации деления на ноль – это выполнение проверки в методе, который работает с операцией деления. Метод divide: можно модифипировать следующим образом. -(void) divide: (double) value { if (value != 0.0) accumulator /= value; else { NSLog ((@"Division by zero."); accumulator = 99999999.; ) } Для ненулевого значения выполняется деление; для нулевого – выводится сообщ ен и е, и переменной accumulator п ри сваи вается значение 99999999. Это произвольно выбранное значение; можно было присвоить значение 0 или задать специальную переменную, указывающую состояние ошибки. Лучше включать обработку особых ситуаций в сам метод, чем полагаться на предусмотрительность программиста при использовании метода. Оператор switch

Цепочки if-else гак часто используются при разработке программ, что в язык Objcctivc-C включен специальный оператор для выполнения именно этой функции. Это оператор switch. Он имеет следующий формат. switch (выражение) { case valuel: программный оператор программный оператор break; case value2. программный оператор программный оператор break; case valuen: программный оператор программный оператор break; default: программный оператор программный оператор break; } Выражение, указанное в круглых скобках, последовательно сравнивается со значениями valuel, value2, ..., valuer), которые могут быть простыми константами или константными выражениями. Если найден вариант (case), при котором значение равно значению выражения, выполняются программные операторы, следующие после этого предложения case. Если включено несколько таких операторов, то их можно не заключать в фигурные скобки. Оператор break вызывает прекращение выполнения оператора switch. Не забывайте включать оператор break в конце каждого предложения case, иначе выполнение программы продолжится в следующем предложении case. Иногда это делают преднамеренно; в таких случаях обязательно включите комментарии, чтобы предупредить других о ваших целях. Особый (необязательный) вариант с именем default выполняется в том случае, если значение выражения не соответствует ни одному из значений, указанных в предложениях case. Это эквивалентно предложению else, которое использовалось в предыдущем примере для «улавливания» любых неуказанных вариантов. На самом деле общую форму оператора switch можно представить в эквивалентной форме оператора if. if (выражение == value 1) { программный оператор программный оператор } else if (выражение == value2) { программный оператор программный оператор } else if (выражение == valuen) { программный оператор программный оператор > else { программный оператор программный оператор } Мы можем теперь преобразовать большой оператор if из программы 6.8А в эквивалентный оператор switch. Это показано в программе 6.9. Программа 6.9 // Программа вычисления простых выражений в форме // число оператор число import

// Здесь нужно вставить секции interface и implementation // для класса Calculator int main (int argc, char argv[]) { NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init]; double value 1, value2; char operator; Calculator *deskCalc = [[Calculator alloc] init]; NSLog (@"Type in your expression."); scant («%lf %c %lf, &value1, &operator, &value2); [deskCalc setAccumulator: valuel]; switch ( operator) { case [deskCalc add: value2]; break; case [deskCalc subtract: value2]; break; case [deskCalc multiply: value2]; break; case 7 : [deskCalc divide: value2]; break; default: NSLog (@»Unknown operator."); break; } NSLog (@"%.2Г, [deskCalc accumulator]); [deskCalc release]; [pool drain]; return 0; } Вывод программы 6.9 Type in your expression. (Введите ваше выражение) 178.99 – 326.8 -147.81 После считывания выражения значение переменной operator сравнивается со значениями каждого варианта case. Если найдено соответствие, то выполняются операторы внутри этого варианта case. Затем оператор break выполняет выход из оператора switch, после чего завершается выполнение программы. Если ни один из вариантов не соответствует значению переменной operator, то используется вариант по умолчанию default, в котором выводится сообщение «Unknown operator» (Неизвестный оператор). Оператор break для варианта default не является необходимым, т.к. после него в данном операторе switch не выполняется никаких операторов. Однако практика надежного программирования требует вставки break в конце каждого варианта. При написании оператора switch помните, что нельзя указывать одинаковые значения для двух разных предложений case. Однако один набор программных операторов можно связывать с несколькими case-значениями. Для этого нужно задать список из нескольких case-значений (с ключевым словом case перед каждым значением и двоеточием после значения) и общий набор программных операторов. Например, в следующем операторе switch выполняется метод multiply:, если значение operator указано символом «звездочка» или строчной буквой х. switch ( operator) case case 'x': [deskCalc multiply: value2]; break; } 6.3. Булевы переменные

Почти все, кто учится программировать, довольно скоро сталкиваются с задачей написания программы, которая создает таблицу простых чисел. Напомним, что положительное целое число р является простым числом, если оно не делится нацело ни на одно из других целых чисел, кроме 1 и самого себя. Первым простым числом является 2. Следующее простое число – 3, так как оно делится нацело только на 1 и 3; 4 не является простым числом, так как оно делится нацело на 2. Создать таблицу простых чисел можно несколькими способами. Например, чтобы создать таблицу простых чисел, не превышающих 50, достаточно напрямую проверить делимость каждого целого числа р на все целые числа от 2 до р-1. Если р делится без остатка на одно из этих чисел, значит, р не является простым числом, иначе оно является простым. В программе 6.10 создается список простых чисел, не превышающих 50. Программа 6.10 // Программа создания таблицы простых чисел (prime number) import

int main (int argc, char argv[]) { NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init]; int p, d, isPrime; for ( p = 2; p <= 50; ++p ) { isPrime = 1; for ( d = 2; d < p; ++d ) if ( p % d == 0 ) isPrime = 0; if ( isPrime != 0 ) NSLog (@"%i", p); [pool drain]; return 0; } Вывод программы 6.10 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 Внешний оператор for задает цикл по целым значениям от 2 до 50. Переменная цикла р представляет текущее значение, для которого выполняется проверка, является ли оно простым числом. В первом операторе цикла присваивается значение 1 переменной isPrime. Использование этой переменной будет описано чуть позже. Во втором цикле выполняется деление р на целые числа от 2 до р-1. Внутри этого цикла проверяется остаток от деления р на d. Если остаток равен 0, значит, р не является простым числом, поскольку оно делится на целое число, отличное от 1 и от него самого. Чтобы указать, что р уже не является «кандидатом» на простое число, переменной isPrime присваивается значение 0. После окончания внутреннего цикла проверяется значение isPrime. Если оно не равняется нулю, значит, не найдено целого числа, которое делит р нацело, и р является простым числом, после чего выводится его значение. Переменная isPrime принимает всего два значения: 0 или 1. Ее значение равно 1, пока р еще проверяется на принадлежность к множеству простых чисел. Как только находится хотя бы один делитель без остатка, isPrime присваивается значение 0, чтобы указать, что р не отвечает критерию принадлежности к простым числам. Такие переменные обычно называют булевыми (Boolean) переменными. Флажок (признак) обычно принимает одно из двух значений. Кроме того, значение флажка обычно проверяется хотя бы один раз в программе, чтобы определить, установлен он (значение TRUE или YES) или сброшен (FALSE или N0), а также выполнить определенное действие в зависимости от результата проверки. В Objective-C состояниям флажка TRUE и FALSE естественным образом соответствуют значения 1 и 0. Например, когда в программе 6.10 переменной isPrime внутри цикла присваивается значение 1, ей фактически присваивается значение TRUE, указывающее, что р пока считается простым числом («is prime»). Если при выполнении внутреннего цикла for найден делитель нацело, переменной isPrime фактически присваивается значение FALSE, чтобы указать, что р не является простым числом. Значение 1 обычно используется для представления значения TRUE (или состояния «оп»), а значение 0 – для представления значения FALSE (или состояния «off»). Это соответствует одному биту в компьютере. Если бит находится в состоянии «оп» (установлен), его значение равно 1, если он находится в состоянии «off» (сброшен), его значение равно 0. Но в Objective-C имеется более веская причина для использования именно этих логических значений. В начале этой главы говорилось, что если удовлетворяются условия, указанные в операторе if, то выполняется следующий за ним программный оператор. В языке Objective-C это означает условие (состояние) «не ноль». Например, if ( 100) NSLog (@"This will always be printed."); вызывает выполнение оператора NSLog ввиду ненулевого состояния в операторе if (в данном случае – значение 100), то есть удовлетворяется условие «не ноль». В каждой из программ этой главы мы фактически использовали понятия «не нуль – условие удовлетворяется» и «нуль – условие не удовлетворяется». В Objective-C при оценке выражения отношения ему присваивается значение 1, если соответствующее условие удовлетворяется, и 0, если условие не удовлетворяется. Поэтому оценка оператора if ( number < 0 ) number = -number; фактически происходит следующим образом. Выполняется оценка выражения отношения number < 0. Если это условие удовлетворяется (number меньше 0), то значение выражения равно 1, иначе его значение равно 0. В операторе if проверяется результат оценки выражения. В случае ненулевого результат выполняется следующий оператор. То же самое относится к оценке условий в операторах for, while и do. Оценка составных выражений отношения (сравнения) выполняется таким же образом. while ( char != 'е' && count != 80 ) Если верны оба условия, то результат равен 1, но если неверно хотя бы одно из условий, результат оценки равен 0. Затем выполняется проверка результатов оценки. Если результат равен 0, то выполнение цикла while прекращается, иначе его выполнение продолжается. Вернемся к программе 6.10 и понятию флажков. В Objective-C допустимо проверять значение флажка TRUE, например, с помощью следующего выражения. if ( isPrime) Оно эквивалентно следующему выражению. if ( isPrime != 0 ) Можно проверить значение флажка FALSE с помощью логического оператора отрицания !. В следующем выражении логический оператор отрицания используется, чтобы проверить переменную isPrime на значение FALSE (его можно прочитать как «если не isPrime»). if (! isPrime ) В общем виде логическое отрицание выражения записывается как ! выражение Так, если выражение равно 0, то оператор логического отрицания дает значение 1. Если оценка выражения не равна 0, то оператор отрицания дает значение 0. Оператор логического отрицания может можно использовать для изменения значения флажка, как в следующем выражении. my_move = ! my_move; Этот оператор имеет такой же уровень приоритета, как и унарный оператор «минус», т.е. имеет более высокий приоритет, чем все бинарные арифметические операторы и все операторы отношения. В следующем выражении задано условие на то, чтобы значение переменной х было не меньше значения переменной у, поэтому здесь необходимы круглые скобки. !(х<у) Этот оператор можно записать в эквивалентной форме: х >= у В Objective-C имеется пара встроенных средств, упрощающих работу с булевыми переменными. Одно из них —специальный тип B00L, который можно использовать для объявления переменных со значениями true или false. Второе средство – это встроенные значения YES и N0. Использование этих значений упрощает написание и чтение программ. Ниже приводится версия программы 6.10, переписанной с использованиемэтих средств. Примечание. Тип B00L добавляется механизмом, который называется препроцессором. Программа 6.10А // Программа создания таблицы простых чисел. // Вторая версия с использованием типа B00L и готовых значений import

int main (int argc, char argv[]) { NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init]; int p, d; BOOL isPrime; for ( р = 2; р <= 50; ++р ) { isPrime = YES; for ( d = 2; d < р; ++d ) if ( p % d == 0 ) isPrime = NO; if ( isPrime == YES ) NSLog (@»%i«, p); } [pool drain]; return 0; } Вывод программы 6.10A 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 6.4. Условный оператор

Возможно, самым необычным оператором в языке Objective-C является условный (conditional) оператор. В отличие от остальных операторов в Objective-C, которые являются унарными или бинарными, условный оператор является тернарным, или трехместным (ternary), то есть в нем требуются три операнда. В этом операторе для обозначений используются два символа: вопросительный знак (?) и двоеточие (:). Первый операнд ставят перед знаком ?, второй операнд – между знаками ? и третий операнд ставится после :. Ниже показан формат условного оператора в общем виде. условие ? выражение 1: выражение_2 В этом описании синтаксиса условие – это выражение (обычно выражение отношения), которое сначала оценивается системой Objective-C в условном операторе. Если результатом оценки является значение TRUE (то есть не нуль), то вычисляется выражение 1 и результат вычисления становится результатом данной операции. Если результатом оценки условия является значение FALSE (то есть нуль), то вычисляется выражение_2 и результат вычисления становится результатом данной операции. Условное выражение чаще всего используется, чтобы в зависимости от некоторого условия присвоить переменной одно из двух значений. Например, предположим, что у нас есть две целые переменные – х и s. Чтобы присвоить s значение -1, если х меньше 0, или значение х2 в противном случае, можно использовать следующий оператор. s = ( х < 0 ) ? -1 : х х; Сначала проверяется условие х < 0. Обычно условие помещается в круглые скобки, но это не обязательно, поскольку условный оператор имеет очень низкий приоритет – ниже всех остальных операторо, за исключением операторов присваивания и оператора «запятая». Если значение х меньше нуля, то вычисляется выражение, непосредственно следующее за символом ?. Это выражение представлено просто целой константой -1, которая присваивается переменной s, если х меньше нуля. Если значение х не меньше нуля, то вычисляется выражение, непосредственно следующее за символом оно присваивается переменной s. Таким образом, если х больше или равно нулю, то переменной s присваивается значение х х, или х2. Еще один пример условного оператора: оператор, где переменной maxvalue присваивается максимум из двух значений: а и Ь. max_value = ( а > b ) ? а : b; Если выражение после : (часть «иначе») содержит еще один условный оператор, то мы получаем возможности предложения else if. Например, функцию sign, которая реализована в программе 6.6, можно записать в одной программной строке с помощью двух условных операторов. sign = ( number < 0 ) ? -1 : (( number == 0 ) ? 0 : 1); Если number меньше нуля, то переменной sign присваивается значение -1; если number равно нулю, то переменной sign присваивается значение 0; иначе ей присваивается значение 1. Круглые скобки вокруг части «иначе» на самом деле не обязательны. Дело в том, что условный оператор объединяется справа налево, то есть когда этот оператор используется несколько раз в одном выражении, например, в е1 ? е2 : еЗ ? е4 : е5 группирование происходит справа налево и поэтому оценка выполняется следующим образом: е1 ? е2 : ( еЗ ? е4 : е5 ) Условные выражения не обязаны стоять в правой части операции присваивания – их можно применять в любой ситуации, где используются выражения. С помощью оператора NSLog вы можете вывести на дисплей знак (sign) переменной number без присваивания ее какой-либо переменной: NSLog (@"Sign = %i", ( number < 0 ) ? -1 : ( number == 0 ) ? О : 1); Условный оператор очень удобно использовать в Objective-C при написании макросов препроцессора (см. главу 12).

Упражнения

Напишите программу, которая запрашивает у пользователя ввод двух целых значений. Проверьте, делится ли первое число без остатка на второе число, и выведите на терминал соответствующее сообщение.

Программа 6.8А выводит значение, содержащееся в сумматоре, даже если введен неверный оператор или пользователь пытается выполнить деление на нуль. Решите эту проблему.

Внесите изменения в метод print из класса Fraction, чтобы целые числа выводились в обычном виде (например, дробь 5/1 должна выводиться как 5). Внесите изменения в этот метод, чтобы дроби с делителем, равным 0, выводились просто как 0.

Напишите программу, которая действует как простой калькулятор. Эта программа должна позволять пользователю вводить выражения в следующей форме: число оператор Программа должна распознавать следующие операторы:

/ S Е Оператор S указывает, что программа должна присвоить сумматору (accumulator) введенное число, и оператор Е указывает программе, что нужно закончить выполнение. Арифметические операции выполняются для содержимого сумматора с числом, которое введено для операции как второй операнд. Ниже приводится пример, показывающий, как должна работать эта программа. Начало вычислений 10 S Сумматору (Accumulator) присваивается значение = 10.000000 Содержимое сумматора 2 / Divide by 2 = 5.000000 Содержимое сумматора 55 – Вычитание 55 10 = -50.000000 100.25 S Сумматору присваивается значение 100.25 = 100.250000 4 Умножение на 4 = 401.000000 0 Е Завершение программы = 401.000000 End of Calculations. (Конец вычислений) Сделайте так, чтобы программа обнаруживала деление на 0, а также выполняла проверку на неизвестные операторы. Используйте для своих вычислений класс Calculator из программы 6.8 5, В программе 5.9 выполняется вывод цифр введенного числа в обратном порядке. Однако эта программа не работает должным образом, если введено отрицательное число. Определите, что происходит в этом случае, и затем внесите в программу изменения, чтобы правильно обрабатывались отрицательные числа. Это означает, например, что если введено число -8645, то программа должна вывести 5468-. 6 Напишите программу, которая читает число, введенное с терминала, и выводит каждую цифру этого числа буквами. Например, если пользователь ввел 932, то программа должна вывести следующее. девять три два (Выведите слово нуль, если пользователь ввел 0.) Примечание. Это довольно трудное упражнение!

Программа 6.10 в ряде случаев работает неэффективно. Например, это касается проверки четных чисел. Поскольку любое четное число больше 2 не может быть простым, программа могла бы пропускать все четные числа и как возможные простые числа, и как возможные делители. Внутренний цикл for тоже работает неэффективно, поскольку для р все время выполняется деление на все значения d от 2 до р-1. Чтобы избежать этой неэффективности, можно добавить значение isPrime в условия for. Тогда вы можете задать выполнение цикла for до тех пор, пока не найден делитель и значение d меньше р. Модифицируйте программу 6.10, чтобы внести эти два изменения, затем выполните эту программу, чтобы проверить ее работу.


    Ваша оценка произведения:

Популярные книги за неделю