Массив в Foundation Framework — это упорядоченный набор объектов. Чаще всего(но не обязательно) элементы массива имеют один определенный тип. Аналогично мутабельным и немутабельным строкам, существуют мутабельные и немутабельные массивы.
Для работы с немутабельными(immutable) массивами используется класс NSArray. Для мутабельных(mutable) массивов используется класс NSMutableArray. Последний класс является подклассом предыдущего и наследует его методы.
Для работы с объектами-массивами в программах нужно включить строку:
1 |
#import <Foundation/NSArray.h> |
В программе 1.7 задается массив для хранения названий месяцев, а затем выводится названия месяцев.
Программа 1.7:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#import <Foundation/NSObject.h> #import <Foundation/NSArray.h> #import <Foundation/NSString.h> #import <Foundation/NSAutoreleasePool.h> int main(int argc, char *argv[]) { int i; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // Создание массива, содержащего названия месяцев NSArray *monthNames = [NSArray arrayWithObjects: @"Январь", @"Февраль", @"Март", @"Апрель", @"Май", @"Июнь", @"Июль", @"Август", @"Сентябрь", @"Октябрь", @"Ноябрь", @"Декабрь", nil]; // Теперь вывод всех элементов этого массива NSLog(@"Месяц Название"); NSLog(@"===== ========"); for(i = 0; i < 12; ++i) NSLog(@" %2i%@", i + 1, [monthNames objectAtIndex: i]); [pool drain]; return 0; } |
Вывод программы 1.7:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Месяц Название ===== ======== 1 Январь 2 Февраль 3 Март 4 Апрель 5 Май 6 Июнь 7 Июль 8 Август 9 Сентябрь 10 Октябрь 11 Ноябрь 12 Декабрь |
Метод этого класса arrayWithObjects: создает массив со списком объектов в виде его элементов. Объекты перечисляются по порядку и разделяются запятыми.
Это специальный синтаксис методов, которые принимают переменное число аргументов. Чтобы закончить список, нужно поставить nil в качестве последнего значения списка(nil не сохраняется внутри массива).
В программе 1.8 массиву monthNames присваиваются 12 строковых значений в виде аргументов для метода arrayWithObjects:.
Элементы массива идентифицируются свои индексом(порядковым номером). Аналогично объектам класса NSString, индексирование начинается с нуля, поэтому массив, содержащий 12 элементов, имеет допустимые индексы 0-11. Метод objectAtIndex: считывает элемент массива по его индексу.
В этой программе каждый элемент из массива считывается с помощью метода objectAtIndex: в цикле for. Каждый считываемый элемент выводится с помощью NSLog.
В программе 1.8 создается таблица простых(prime) чисел. Поскольку простые числа добавляются в массив по мере их создания, здесь требуется мутабельный массив. Память для объекта primes класса NSMutableArray выделяется с помощью метода arrayWithCapacity:.
Указанный аргумент 20 задаст начальный размер массива. Размер мутабельного массива автоматически увеличивается во время выполнения программы.
Хотя простые числа являются целыми, мы не может сохранять значения типа int внутри этого массива. Данный массив может содержать только объекты, поэтому нам нужно сохранять в массиве primes целы объекты класса NSNumber.
Программа 1.8:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#import <Foundation/NSObject.h> #import <Foundation/NSArray.h> #import <Foundation/NSString.h> #import <Foundation/NSAutoreleasePool.h> #import <Foundation/NSValue.h> #define MAXPRIME 50 int main(int argc, char *argv[]) { int i, p, prevPrime; BOOL isPrime; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // Создание массива для хранения простых чисел NSMutableArray *primes = [NSMutableArray arrayWithCapacity: 20]; // Сохранение в массиве первых двух простых чисел (2 и 3) [primes addObject: [NSNumber numberWithInteger: 2]]; [primes addObject: [NSNumber numberWithInteger: 3]]; // Вычисление остальных простых чисел for(p = 5; p <= MAXPRIME; p += 2) { // проверяется, что p - простое число isPrime = YES; i = 1; do { prevPrime = [[primes objectAtIndex: i] integerValue]; if(p % prevPrime == 0) isPrime = NO; ++i; } while( isPrime == YES && p / prevPrime >= prevPrime); if(isPrime) [primes addObject: [NSNumber numberWithInteger: p]]; } // Вывод результатов for(i = 0; i < [primes count]; ++i) NSLog(@"%i", (long)[[primes objectAtIndex: i] integerValue]); [pool drain]; return 0; } |
Вывод программы 1.8:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 |
MAXPRIME определяется как максимальное простое число для вычислений(в нашем случае 50).
После выделения памяти для массива primes задаются два первых элемента массива с помощью следующих операторов:
1 2 |
[primes addObject: [NSNumber numberWithInteger: 2]]; [primes addObject: [NSNumber numberWithInteger: 3]]; |
Метод addObject: добавляет объект в конец массива. В данном случае добавляются объекты класса NSNumber, создаваемые соответственно из целых значений 2 и 3.
Затем в программе начинается цикл for для поиска простых чисел, начиная с 5, вплоть до MAXPRIME с пропуском промежуточных четных чисел (p += 2).
Для каждого возможного числа p и проверяется его делимость на предыдущие простые числа. В случае делимости p не является простым числом. Для ускорения мы проверяем делимость только на простые числа, не превышающие квадратный корень из p.
Дело в том, что если число не является простым, оно должно делиться на простое число, которое не больше его квадратного корня. Поэтому выражение:
1 |
p / prevPrime >= prevPrime |
верно, если prevPrime меньше, чем квадратный корень из p.
Если при выходе из цикла do-while флаг isPrime по-прежнему равен YES, значит, мы нашли еще одно простое число. В этом случае p добавляется в массив primes, и выполнение программы продолжается.
Краткое замечание по эффективности. Классы Foundation очень удобный для работы с массивами, однако при работе с большими массивами чисел и сложными алгоритмами нужно научиться выполнять такие задачи с помощью низкоуровневых конструкций языка для массивов, которые могут оказаться более эффективными с точки зрения использования памяти и скорости выполнения.