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

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

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


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



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

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

/ Пример использования оператора #import Примечание. В этой программе предполагается, что определения заданы в файле с именем metric.h (галлон = 4 кварты) / import import

int main (int argc, char *argv[])

{ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; float liters, gallons; NSLog (@"*** Liters to Gallons ***"); NSLog (@*Enter the number of liters:"); scanf ("%f", Sliters); gallons = liters * QUARTS_PER_UTER / 4.0; NSLog (@"%g liters = %g gallons", liters, gallons); [pool drain]; return 0;

} Вывод программы 12.1

Liters to Gallons (Литры в галлоны) Enter the number of liters: (Введите количество литров) 55.75 55.75 liters = 14.7319 gallons. (55.75 литров = 14.7319 галлонов) В программе 12.1 используется только одно определенное значение (QUARTS_PER_LITER) из include-файла metric.h. Тем не менее, это вполне показательный пример: после ввода в файл metric.h определения доступны в любой программе, где применяется соответствующий оператор «import. Одним из наиболее важных преимуществ использования файла импорта является возможность централизовать все определения, что гарантирует использование в программах одного и того же значения. Кроме того, ошибки в include-файле достаточно исправить только в одном месте, не изменяя все программы, использующие это значение. Любую программу, в которой используется неверное значение, достаточно перекомпилировать, не редактируя. Другие системные include-файлы содержат объявления для различных функций, хранящихся в базовой системной библиотеке С. Например, файл limits.h содержит системно-зависимые значения, которые задают размеры символьных и целых типов данных. Максимальный размер типа int определяется вну три этою файла именем INT_MAX, максимальный размер unsigned long int определяется с помощью ULONG^MAX, и т.д. Файл float.h задает информацию о типах данных с плавающей точкой: FLTMAX указывает максимальное число с плавающей точкой, a FLT_DIG – число десятичных цифр для точности типа float. Файл string.h содержит объявления для библиотечных процедур копирования, сравнения и конкатенации, которые выполняют операции с символьными строками. Если вы работаете исключительно со строчными классами Foundation (см. главу 15), то эти процедуры вам не потребуются. ## 12.3. Условная компиляция Препроцессор Objective-C позволяет работать с условной компиляцией (conditional compilation). Условная компиляция обычно применяется для создания одной программы, которую можно компилировать для выполнения в различных компьютерных системах. Она часто используется для включения или отключения в программе различных операторов, например, операторов отладки, которые выводят значения переменных или отслеживают последовательность выполнения программы. ### Операторы #ifdef, #endif, #else и #ifndef К сожалению, программа может основываться на системно-зависимых параметрах, которые различны для разных процессоров (например, Power PC или Intel) в разных версиях операционной системы (например, Tiger или Leopard). Для большой программы, содержащей много таких зависимостей от оборудования или программного обеспечения вам пришлось бы изменять много операторов типа define. Чтобы свести к минимуму эту проблему, вы можете включить в программу значения определений операторов типа define для разных машин, используя средства условной компиляции препроцессора. Например, в следующих операторах для DATADIR определяется значение „/uxnl/data“, если ранее был определен символ MAC_0S_X, в противном случае присваивается значение „usrdata“. ifdef MAC_0S_X define DATADIR «/uxnl/data» else define DATADIR «usrdata» endif После символа #, начинающего оператор препроцессора, можно помещать один или несколько пробелов. Операторы #ifdef, #else и #endif действуют в соответствии с их именами. Если символ, указанный в строке #ifdef, уже определен (с помощью оператора #define или из командной строки при компиляции программы), компилятор обрабатывает последующие строки до #else, #elrf или ftendif; в противном случае они игнорируются. Чтобы определить символ POWER_PC для препроцессора, достаточно оператора define P0WER_PC 1 или define POWER.PC. Как видно из примера, после определенного имени не требуется текста, чтобы выполнить проверку #ifdef. Компилятор также позволяет определить имя для препроцессора, если программа компилируется с использованием специальной опции в команде компилятора. В командной строке

gcc -framework Foundation -D P0WER_PC program.m – для препроцессора определяется имя P0WER_PC, чтобы все операторы #ifdef POWER PC внутри программы program.m давали значение TRUE (отметим, что -D POWER PC следует ввести в командной строке до указания имя программы). Это средство позволяет определять имена без редактирования исходной программы. В Xcode для добавления новых определенных имен и указания их значений нужно выбрать Add User-Defined Setting (Добавить пользовательское значение) в Project Settings (Настройки проекта). После оператора #ifndef следуют такие же строки, как после оператора #ifdef. В нем последующие строки обрабатываются в том случае, если указанный символ не определен. Как уже говорилось, условная компиляция полезна для отладки программ. Можно включить в программу много вызовов printf для вывода промежуточных результатов и отслеживания последовательности выполнения. Для запуска этих операторов можно выполнить их условную компиляцию в программе, если определено некоторое имя, например DEBUG. Следующую последовательность операторов можно использовать для вывода значений некоторых переменных, только если программа была откомпилирована с определением имени DEBUG. ifdef DEBUG NSLog (@"User name = %s, id = %i", userName, userid); endif В вашей программе может быть много таких отладочных операторов. При отладке программу можно компилировать с определением имени DEBUG, чтобы выполнялась компиляция отладочных операторов. Если программа работает правильно, ее можно перекомпилировать без определения DEBUG. Это позволяет сократить размер программы, поскольку все отладочные операторов не будут компилироваться. ### Операторы препроцессора #if и #elif Оператор препроцессора #if представляет более общий подход к управлению условной компиляцией. Этот оператор позволяет проверить, равно ли нулю константное выражение. Если результат выражения не равен нулю, последующие строки до Seise, telif или tendif обрабатываются; в противном случае они пропускаются. Рассмотрим следующие строки из файла Foundation NSString.h. if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_0S_X_VERSI0N _10_5 define NSMaximumStringLength (INT MAX-1) endif Здесь сравниваю тся значения определенных переменных MAC_OS_X_VERSION_MIN_REQUIRED и MAC_OS_X_VERSIONJO_5. Если первое значение меньше второго, то обрабатывается следующий оператор tdefine; в противном случае он пропускается. Это позволяет задать максимальную длину строки, равную максимальному размеру целого типа минус 1, если программа компилируется в системе MAC OS X 10.5 или последующих версиях. В строках с #if применяется также специальный оператор

defined (имя) Следующие наборы операторов дают одинаковый результат: if defined (DEBUG) ... endif и ifdef DEBUG ... endif Следующие операторы включены в файл NSObjcRuntime.h, чтобы определить имя NSJNI INF (если оно не было определено раньше) в зависимости от конкретного компилятора. if defined(NSJNUNE) #if defined(_GNUC_) #define NSJNUNE static _inline_attribute_((always_inline)) #elif defined(_MWERKS_J || defined(_cplusplus) #define NSJNUNE static inline #elif defined(MSC_VER) #define NS_INUNE static_inline #elif defined(_"wiN32_) #define NS_INUNE static_inline_ #endif endif Ниже приводится еще один типичный случай применения #if. if defined (DEBUG) && DEBUG ... endif Операторы между #if и #cndif будут обрабатываться в том случае, если имя DEBUG определено и имеет ненулевое значение. ### Оператор #undef Сделать определенное имя неопределенным позволяет оператор #undef. Чтобы удалить определение имени, нужно написать строку undef имя Следующий оператор удаляет определение POWER_PC. undef POWER_PC Последующие операторы #ifdef P0WER_PC или #if defined (POWER_PC) будут давать значение FALSE. На этом заканчивается наше описание возможностей препроцессора. В приложении В приводятся дополнительные операторы препроцессора, которые не были описаны здесь. Упражнения 1. Найдите на своей машине файлы limits.h и float.h. Посмотрите, что находится в этих файлах. Если в эти файлы включены другие файлы, просмотрите и их. 2. Определите макрос с именем MIN, который дает минимальное из двух значений. Напишите программу, которая проверяет определение этого макроса. 3. Определите макрос с именем МАХЗ, который дает максимальное из трех значений. Напишите программу, которая проверяет это определение. 4. Напишите макрос с именем IS_UPPER_CASE, который выдает ненулевое значение, если символ является прописной буквой. 5. Напишите макрос с именем IS_ALPHABETIC, который выдает ненулевое значение, если символ является буквой. Сделайте так, чтобы в этом макросе использовались макрос IS_LOWER CASE, определенный в данной главе, и макрос IS_UPPER_CASE, определенный в упражнении 4. 6. Напишите макрос с именем IS_DIGfT, который выдает ненулевое значение, если символ является цифрой от 0 до 9. Используйте этот макрос в определении другого макроса с именем IS_SPECIAL, который выдает ненулевое значение, если символ является специальным символом (то есть не буквой и не цифрой). Обязательно используйте макрос IS_ALPHABET1C из упражнения 5. 7. Напишите макрос с именем ABSOLUTE VALUE, который вычисляет абсолютное значение своего аргумента. Этот макрос должен правильно вычислять такие выражения, как ABSOLUTE_VALUE (х + delta) ```

Рассмотрим определение макроса printint из этой главы#define printx(n) printf ("%in", x ## n) Можно ли использовать следующие строки для вывода значений 100 переменных отх1 до хЮО? Почему?for (i = 1; i <= 100; ++i) printx (i);

Глава 13. Базовые средства из языка С

В этой главе описываются средства языка Objective-C, взятые из базового языка программирования С. Вам необязательно знать их. Такие средства, как функции, структуры, указатели, объединения и массивы лучше изучать по мере необходимости. Поскольку С является процедурным языком, некоторые из этих средств противоречат основам объектно-ориентированного программирования и могут также не согласовываться с некоторыми стратегиями Foundation framework, например, с методологией выделения памяти или работой с символьными строками, содержащими символы из нескольких байтов. Примечание. На уровне Objective-C существуют способы работы с многобайтными символами, но в Foundation имеется нам нога более удобное решение с помощью собственного класса NSString. С другой стороны, в некоторых приложениях может потребоваться низкоуровневый подход. Например, при работе с большими массивами данных мо– iyr применяться встроенные структуры данных в виде массивов из Objective-C вместо объектов-массивов из Foundation (см. главу 15). Функции могут оказаться удобным средством для группировки повторяющихся операций и разбиения программы на модули. Ознакомьтесь с данной главой, чтобы получить общее представление, и вернитесь к ней, когда закончите изучение части II (Foundation Framework), или пропустите ее и перейдите к части II, где описывается Foundation framework. Если вам придется поддерживать чей-то код или вы начнете изучать header– формы Foundation framework, вам могут встретиться некоторые конструкции, описанные в этой главе. Некоторые из типов данных Foundation, такие как NSRange, NSPoinrt и NSRect, требуют элементарного понимания описываемых здесь структур. В таких случаях вы всегда сможно вернуться к этой главе. 13.1. Массивы

Язык Objective-C позволяет определить набор упорядоченных элементов данных, который называется массивом (array). В этом разделе описывается определение и управление массивами. В последующих разделах описывается использование массивов совместно с функциями, структурами, символьными строками и указателями. Предположим, что вам нужно считать набор оценок (grades) и затем выполнить с ними некоторые операции, например, расположить их в порядке возрастания, вычислить среднее значение и найти медиану. Вы не можете выполнить эти операции, пока не введете все оценки. В Objective-C вы можете определить переменную с именем grades, которая представляет не одно значение оценки, а весь набор оценок. Для ссылки на элементы этого набора используется число, которое называется порядковым номером, или индексом (index или subscript). В математике /-й элемент набора х обозначается как х; в Objective-C он обозначается как x[i]

Тем самым, выражение grades[5]

соответствует элементу с номером 5 в массиве с именем grades. В Objective-C элементы массива начинаются с номера 0, поэтому grades[0]

на самом деле обозначает первый элемент массива.

Отдельный элемент массива можно использовать в любом месте как обычную переменную. Например, элемент массива можно присвоить другой переменной с помощью оператора g = grades[50];

Здесь значение, содержащееся в gradesfSO], присваивается переменной д. В общем виде, если i объявлена как целая переменная, оператор g = grades[i];

присваивает переменной g значение, содержащееся в элементе с номером i массива grades.

Чтобы сохранить значение в элементе массива, нужно указать этот элемент массива слева от знака равенства. В операторе grades[ 100] = 95;

значение 95 сохраняется в элементе с номером 100 массива grades.

Для перебора элементов массива нужно изменять значение переменной, которая используется как индекс массива. Например, в цикле for (i = 0; i < 100; ++i) sum += grades[i];

выполняется перебор первых 100 элементов массива grades (элементы 0-99), и значение каждой оценки (grade) добавляется к переменной sum. По окончании цикла for переменная sum будет содержать сумму первых 100 значений массива grades (если sum присвоено значение 0 до начала цикла).

Как и с другими типами переменных, необходимо объявить массив, прежде чем использовать его. Объявление массива – это объявление типа элементов, содержащихся в массиве (например, int, float или объект) и максимального числа элементов в массиве.

Определение Fraction *fracts [100];

объявляет tracts как массив, содержащий 100 дробей (fraction). Для обозначения элементов этого массива нужно использовать индексы от 0 до 99. Выражение fracts[2] = [fracts[Q] add: fracts[1]];

представляет вызов метода add: класса Fraction для сложения первых двух дробей из массива tracts и сохранения результата в третьем элементе массива.

В программе 13.1 создается таблица из первых 15 чисел Фибоначчи. Попытайтесь предсказать ее результаты. Какая связь существует между числами этой таблицы? // Программа генерации первых 15 чисел Фибоначчи #import int main (int arge, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int Fibonacci [15], i; Fibonacci [0] = 0; /* by definition */ Fibonacci[1] = 1; /* ditto 7 for ( i = 2; i < 15; ++i) Fibonacci[i] = Fibonacci[i-2] + Fibonacci [i-1]; for ( i = 0; i < 15; ++i) NSLog (@"%i", Fibonacci^]); [pool drain]; return 0; }

Вывод программы 13.1 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Первые два числа Фибоначчи, которые мы назовем F0 и F, определяются соответственно как 0 и 1. Затем каждое следующее число Фибоначчи F определяется как сумма двух предыдущих чисел Фибоначчи F 2 и F,. Например, F2 вычисляется как сумма значений F0 и F, В приведенной профамме это соответствует вычислению Fibonacci[2] путем сложения значений Fibonacci[0] и Fibonacci[1]. Вычисление выполняется внутри цикла for для значений F0-F14 (то есть от Fibonacci[2] до Fibonacci[14]). Инициализация элементов массива

Элементам массива можно назначать начальные значения точно так же, как переменным при их объявлении. Для этого нужно просто перечислить начальные значения массива, начиная с первого элемента. Значения в списке разделяются запятыми, и весь список заключается в фигурные скобки.

В операторе int integers[5] = { 0, 1, 2, 3, 4 };

элементу integers[0] присваивается значение 1, integers[1] – значение 1, integers[2] – значение 2, и т.д. Массивы символов инициализируются аналогичным образом. Например, в операторе char letters[5] = {'а', 'b', 'с', 'd', 'е'};

определяется массив символов, и пяти элементам этого массива присваиваются соответственно значения 'a', 'b', 'с', 'd' и 'е'.

Вы не обязаны полностью инициализировать весь массив. Если указано меньшее количество начальных значений, инициализируется соответствующее количество элементов; остальные значения задаются равными нулю. Например, в объявлении float sample_data[500] = { 100.0, 300.0, 500.5 };

инициализируются первые три значения массива sample_data (соответственно 100.0,300.0 и 500.5), а остальным 497 элементам присваивается значение 0. Заключая номер элемента в прямоугольные скобки, можно инициализировать определенные элементы массива в любом порядке. Например, в строках, int x = 1233; int а[] = {[9] = х + 1, [2] = 3, [1] = 2, [0] = 1 };

определяется массив а из 10 элементов (по максимальному указанному индексу) и для последнего элемента задается значение х + 1 (1234). Кроме того, происходит инициализация первых трех элементов (значения 1,2 и 3 соответственно). Массивы символов

В программе 13.2 показано, как использовать массив символов. Однако здесь есть одна особенность, требующая обсуждения. Вы уже видите ее? #import int main (int arge, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; char word[] = {'H', 'e', 'l', 'l', 'o', '!'}; int i; for ( i = 0; i < 6; ++i) NSLog word[i]); [pool drain]; return 0; }

Вывод программы 13.2 H e l l о !

Наиболее примечательной особенностью этой программы является объявление массива символов word без указания числа элементов. При определении массива без указания числа элементов размер массива определяется автоматически по числу инициализируемых элементов. Поскольку в программе 13.2 для массива word инициализируются шесть значений, язык Objective-C по умолчанию определяет, что данный массив содержит шесть элементов.

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

Если поместить завершающий нуль-символ ('') в конце массива символов, то создастся символьная строка (characterstring). Если в программе 13.2 заменить инициализацию массива word па строку char word[] = {'Н', 'е', 'l', 'l', 'o', '!', ''};

то в дальнейшем можно выводить эту строку с помощью одного вызова NSLog, например, NSLog (@"%s", word);

Символы форматирования %s указывают NSLog, что вывод символов должен продолжаться до тех пор, пока не будет достигнут завершающий нуль-символ. А именно этот символ мы поставили в конце массива word. Многомерные массивы

Все массивы, рассмотренные выше, являются линейными, то есть имеют одну размерность. Язык Objective-C позволяет определять массивы любой размер-ности. В этом разделе описываются двумерные массивы.

Типичным примером двумерного массива являются матрицы. Рассмотрим матрицу 4x5. 10 5 -3 17 82 9 0 0 8 -7 32 20 1 0 14 0 0 8 7 6

В математике для указания элемента матрицы используют два индекса. Если назвать эту матрицу М, то обозначение М.. будет указывать элемент /-й строки, у-го столбца, где / изменяется от 1 до 4 и/ изменяется от 1 до 5. Обозначение М3 2 указывает значение 20, которое находится в третьей строке втором столбце этой матрицы. Аналогичным образом, Л/45 указывает элемент, который находится в четвертой строке пятом столбце (значение 6).

В Objective-C при обозначении элементов двумерной матрицы используются аналогичные обозначения. Но поскольку в Objective-C нумерация начинается с 0, первая строка матрицы имеет номер 0, и первый столбец матрицы тоже имеет номер 0. Поэтому приведенная выше матрица будет иметь следующие обозначения строк и столбцов. Строка (i) Столбец (j) 0 1 2 3 4 0 10 5 -3 17 82 1 9 0 0 8 -7 2 32 20 1 0 14 3 0 0 8 7 6

Применяемое в математике обозначение Mij. заменяется в Objective-C обозначением M[i][j]

Напомним, что первый индекс указывает номер строки, и второй индекс – номер столбца. Тем самым, sum = М[0][2] + M[2J[4];

означает сложение значения из строки 0 столбца 2 (-3) со значением из строки 2 столбца 4 (14) и присваивание результата (11) переменной sum.

Описание двумерных массивов выполняется так же, как для одномерных массивов; например, int М[4][5];

означает объявление массива М как двумерного массива, содержащего 4 строки и 5 столбцов (всего 20 элементов). Каждый элемент этого массива должен со-держать целое значение.

Двумерные массивы можно инициализировать аналогично одномерным. Перечисление элементов выполняется по строкам. Чтобы отделить инициали-зацию одной строки от другой, используются фигурные скобки. Таким образом, чтобы определить и инициализировать массив М с элементами из приведенной выше таблицы, можно использовать следующий оператор. int М[4][5] = { {10, 5, -3, 17, 82 }, { 9, 0, 0, 8, -7 }, {32,20, 1,0, 14}, { 0, 0, 8,7, 6 } };

Уделите особое внимание синтаксису этого оператора. Отметим, что после каждой закрывающей фигурной скобки (кроме последней) требуется запятая. Использование внутренних пар фигурных скобок не является обязательным. Если они не указаны, инициализация происходит по строкам, поэтому преды-дущий оператор можно было бы написать следующим образом. int М[4][5] = { 10, 5, -3, 17, 82, 9, 0, 0, 8, -7, 32, 20,1,0, 14, 0, 0, 8, 7,6};

Как и в случае одномерных массивов, можно инициализировать не весь мас-сив. Например, в следующем операторе инициализируются только первые три элемента каждой строки матрицы. int М[4][5] = { { 10, 5, -3}, { 9, 0, 0 }, { 32, 20, 1 }, { 0, 0, 8 } };

Остальным значениям присваивается значение 0. Отметим, что в данном случае для правильной инициализации необходимы внутренние пары фигурных скобок. Без таких скобок были бы инициализированы первые две строки и первые два элемента третьей строки. (Проверьте это сами.) 13.2. Функции

Процедура NSLog, которую мы использовали в каждой профамме этой книги, является примером функции. Каждая программа содержит функцию с именем main. Вернемся к нашей первой программе (программа 2.1), где на терминал выводилась фраза «Программировать на Objective-C интересно». #import int main (int arge, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSLog (@"Программировать интересно."); [pool drain]; return 0; }

Следующая функция с именем printMessage выводит тот же текст. void printMessage (void) { NSLog (@"Программировать интересно."); }

Единственным отличием между printMessage и функцией main из профаммы 2.1 является первая строка. В первой строке определения функции компилятору сообщаются четыре факта об этой функции.

Кто может вызывать ее.

Тип значения, которое она возвращает.

Ее имя.

Количество и тип аргументов, которые она принимает.

В первой строке определения функции printMessage компилятору сообщается, что имя функции printMessage и что она не возвращает никакого значения (первое применение ключевого слова void). В отличие от методов, тип возвращаемого значения функции не заключают в круглые скобки. Компилятор выдаст сообщение об ошибке, если вы сделаете это.

После сообщения, что printMessage не возвращает значений, ключевое слово void применяется во второй раз, указывая, что этой функции не передаются ни-какие аргументы.

Напомним, что main – это специальное имя в системе Objective-C, которое указывает, где должно начаться выполнение данной программы, main необхо-димо указывать всегда. Мы можем добавить функцию main к приведенному выше коду, чтобы получить законченную программу (см. программу 13.3). #import void printMessage (void) { NSLog (@"Программировать интересно."); } int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; printMessage(); [pool drain]; return 0; }

Вывод программы 13.3 Программировать интересно.

Программа 13.3 состоит из двух функций; printMessage и main. Поскольку printMessage не принимает никаких аргументов, при ее вызове используется просто пара круглых скобок. Аргументы и локальные переменные

В главе 5 мы разрабатывали программы для вычисления треугольных чисел. Здесь мы определим функцию с именем calculateTriangularNumber для генерации треугольного числа и будем вызывать ее. В качестве аргумента функции указы-вается номер треугольного числа. Функция будет вычислять нужное число и выводить результаты. В программе 13.4 показана функция для выполнения этой задачи и процедура main для ее проверки. #import // Функция для вычисления п-го треугольного числа void calculateTriangularNumber {int n) { int i, triangularNumber = 0; for (i = 1; i <= n; ++i) triangularNumber += i; NSLog (@"Triangular number %i is %i", n, triangularNumber); } int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; calculateTriangularNumber (10); calculateTriangularNumber (20); calculateTriangularNumber (50); [pool drain]; return 0; }

Вывод программы 13.4 Triangular number 10 is 55 (10-е треугольное число равно 55) Triangular number 20 is 210 Triangular number 50 is 1275

Рассмотрим первую строку функции calculateTriangularNumber. void calculateTriangularNumber (int n)

Она указывает компилятору, что calculateTriangularNumber – это функция, которая не возвращает никакого значения (ключевое слово void) и которой передается один api-умент с именем п типа int. Отметим еще раз, что тип аргумента нельзя помещать в круглые скобки, как мы привыкли делать при написании методов.

Открывающая фигурная скобка указывает начало определения функции. Поскольку нам нужно вычислять я-е треугольное число, мы должны задать пе-ременную для сохранения значения треугольного числа при его вычислении. Нам нужна также переменная, действующая как индекс цикла. Для этих целей переменные TriangularNumber и i определяются и объявляются с типом int. Их оп-ределение и инициализацию мы выполняем так же, как для других переменных внутри процедуры main в предыдущих программах.

Локальные переменные действуют в функциях так же, как в методах. Если для переменной внутри функции задано начальное значение, это начальное значение присваивается переменной при каждом вызове данной функции.

Переменные, определенные внутри функции, называются автоматическими локальными (automatic local) переменными, поскольку они автоматически «создаются» каждый раз, когда происходит вызов данной функции, а их значения являются локальными по отношению к данной функции.

Статические локальные (Static local) переменные описываются с помощью ключевого слова static, сохраняют свои значения при вызовах функций и имеют начальные значения по умолчанию, равные 0.

Значение локальной переменной доступно только внутри функции, где оп-ределена эта переменная. Ее значение нельзя получить с помошыо непосред-ственного доступа извне этой функции.

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

Внутри процедуры main при первом вызове функции calculateTriangularNumber ей передается в качестве аргумента значение 10. После этого управление передается непосредственно в функцию, где значение 10 становится значением формального параметра п внутри этой функции. Затем функция вычисляет значение 10-го треугольного числа и выводит результат.

При следующем вызове calculateTriangularNumber передается аргумент 20. Значение 20 становится значением формального параметра п внутри функции. Затем функция вычисляет значение 20-го треугольного числа и выводит резуль-тат. Возвращение результатов функций

Как и методы, функции могут возвращать значение. Тип значения, возвращае-мого с помощью оператора return, должен быть согласован с типом возвращае-мого значения, объявленного для этой функции. В объявлении функции, которое начинается с float kmh_to_mph (float km_speed)

содержится определение функции с именем kmh_to_mph, которая принимает один аргумент типа float с именем km_speed и возвращает значение тоже типа float. Аналогичным образом, int ged (int u, int v)

определяет функцию ged (наибольший общий делитель) с целыми аргументами и и v и возвращает целое значение.

Мы перепишем алгоритм определения наибольшего общего делителя, ис-пользуемый в программе 5.7, в форме функции. Этой функции передаются два аргумента в виде двух чисел, для которых нужно определить их наибольший общий делитель (ged, greatest common divisor), см. программу 13.5. #import // Эта функция ищет наибольший общий делитель двух // неотрицательных целых значений и возвращает соответствующий результат int gcd (int u, int v) { int temp; while ( v != 0 ) { temp = u % v; u = v; v = temp; } return u; } main {) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int result; result = ged (150, 35); NSLog (@"The ged of 150 and 35 is %i", result); result – ged (1026, 405); NSLog (@nThe ged of 1026 and 405 is %i“, result); NSLog (<§>nThe ged of 83 and 240 is %Г, ged (83, 240)); [pool drain]; return 0; }

Вывод программы 13.5 The gcd of 150 and 35 is 5 (Наибольший общий делитель 150 и 35 равен 5) The gcd of 1026 and 405 is 27 The gcd of 83 and 240 is 1

Функция ged принимает два целых аргумента. Данная функция имеет доступ к этим аргументам через имена формальных параметров и и V. После объявления переменной temp типа int программа выводит на терминал значения аргументов и и v вместе с соответствующим сообщением. Затем функция вычисляет и возвращает наибольший общий делитель этих двух целых чисел.

В строке result = gcd (150, 35);

происходит вызов функции gcd с аргументами 150 и 35 и сохранение значения, которое возвращает функция, в переменной result.

Если не указан тип возвращаемого значения функции, компилятор предпо-лагает, что функция возвращает целое значение (если она вообще возвращает значение). Многие программисты не указывают тип возвращаемого значения, если функция должна возвращать целые значения. Однако такой подход про-тиворечит практике надежного программирования. Компилятор предупредит, что для возвращаемого значения задан по умолчанию тип int, но это признак того, что вы делаете что-то неверно!


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

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