[Objective-C语言教程]数组(14)

Objective-C编程语言提供了一种叫作数组的数据结构,它可以存储相同类型的固定大小顺序元素的集合。数组用于存储数据集合,但将数组视为相同类型的变量集合通常更有用。

可以声明一个数组变量(例如numbers)并使用numbers[0]numbers[1]...numbers[99]来表示单个变量,例如:number0number1...number99,而不是声明单个变量。 使用索引来访问数组中的特定元素。

所有数组都包含连续的内存位置。 最低地址对应于第一个元素,最高地址对应于最后一个元素。

1. 声明数组

在Objective-C中声明一个数组,程序员需要指定元素的类型和数组所需的元素数量,如下所示 -

type arrayName [ arraySize ];

这称为一维数组。 arraySize必须是大于零的整数常量,type可以是任何有效的Objective-C数据类型。 例如,要声明一个名称为balancedouble类型的10元素数组,请使用此语句 -

double balance[10];

现在,balance是一个变量数组,最多可容纳10double类型。

2. 初始化数组

可以逐个初始化Objective-C中的数组,也可以使用单个语句,如下所示 -

double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};

大括号{}之间的值的数量不能大于在方括号[]之间为数组声明的元素的数量。以下是分配数组的单个元素的示例 -

如果省略数组的大小,则会创建一个足以容纳初始化的数组。 因此,如果这样写 -

double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0};

这将创建与上一示例中完全相同的数组。

balance[4] = 50.0;

上面的语句将数组中的第5元素赋值为50.0。 具有第四个索引的数组它拥有5个元素,因为所有数组都将0作为第一个元素的索引,也称为基本索引。 以下是上面讨论的相同数组的图形表示 -

3. 访问数组元素

通过索引数组名称来访问元素。通过将元素的索引放在数组名称后面的方括号中来完成的。 例如 -

double salary = balance[9];

上面的语句将从数组中取出第10个元素,并将值赋给salary变量。 以下是一个例子,它将使用上述所有三个概念,即数组声明,分配和访问数组 -

 1 #import <Foundation/Foundation.h>
 2 
 3 int main () {
 4    int n[ 10 ];   /* n 是10个整数的数组 */
 5    int i,j;
 6 
 7    /* 从 n 到 0 初始化数组的值 */         
 8    for ( i = 0; i < 10; i++ ) {
 9       n[ i ] = i + 100;    /* 从i 至 i + 100 设置数组元素的值  */
10    }
11 
12    /* 输出每个数组元素的值 */
13    for (j = 0; j < 10; j++ ) {
14       NSLog(@"Element[%d] = %d
", j, n[j] );
15    }
16 
17    return 0;
18 }

执行上面示例代码,得到以下结果:

 1 2018-11-15 02:52:00.725 main[97171] Element[0] = 100
 2 2018-11-15 02:52:00.727 main[97171] Element[1] = 101
 3 2018-11-15 02:52:00.727 main[97171] Element[2] = 102
 4 2018-11-15 02:52:00.727 main[97171] Element[3] = 103
 5 2018-11-15 02:52:00.728 main[97171] Element[4] = 104
 6 2018-11-15 02:52:00.728 main[97171] Element[5] = 105
 7 2018-11-15 02:52:00.728 main[97171] Element[6] = 106
 8 2018-11-15 02:52:00.728 main[97171] Element[7] = 107
 9 2018-11-15 02:52:00.728 main[97171] Element[8] = 108
10 2018-11-15 02:52:00.728 main[97171] Element[9] = 109

4. Objective-C数组详细介绍

数组对Objective-C很重要,需要更多细节。 以下几个与数组相关的重要概念应该对Objective-C程序员清楚 -

编号概念描述
1 多维数组 Objective-C支持多维数组,多维数组的最简单形式是二维数组。
2 将数组传递给函数 通过指定不带索引的数组名称来向函数传递指向数组的指针。
3 从函数返回数组 Objective-C允许函数返回一个数组。
4 指向数组的指针 只需指定数组名称即可生成指向数组第一个元素的指针,而无需任何索引。

4.1 多维数组

Objective-C编程语言允许多维数组,下面是多维数组声明的一般形式 -

type name[size1][size2]...[sizeN];

例如,以下声明创建一个三维:5,10,4整数数组 -

int threedim[5][10][4];

4.11 二维数组

多维数组的最简单形式是二维数组。 实质上,二维数组是一维数组的列表。 要声明一个大小为xy的二维整数数组,可以参考如下代码 -

type arrayName [ x ][ y ];

其中,type可以是任何有效的Objective-C数据类型,arrayName是有效的Objective-C标识符。可将二维数组视为一个表格,其中包含x行和y列。包含34列的二维数组a,如下所示 -

因此,数组a中的每个元素都由a[i][j]形式的元素名称标识,其中a是数组的名称,ij是唯一标识数组a中每个元素的下标。

4.12. 初始化二维数组

通过为每行指定括号值来初始化多维数组。以下是一个包含3行的数组,每行有4列。

1 int a[3][4] = {  
2    {0, 1, 2, 3} ,   /*  第0行索引的初始值设定项  */
3    {4, 5, 6, 7} ,   /*  第1行索引的初始值设定项  */
4    {8, 9, 10, 11}   /*  第2行索引的初始值设定项  */
5 };

指示预期行的嵌套大括号是可选的。 以下初始化数组等同于前面的示例 -

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

4.13 访问二维数组元素

通过使用下标(即,数组的行索引和列索引)来访问二维数组中的元素。 例如 -

int val = a[2][3];

上面的语句将从数组的第3行获取第4个元素。可以在上图中验证它,阅读下面的程序,使用嵌套循环来处理(访问)二维数组 -

 1 #import <Foundation/Foundation.h>
 2 
 3 int main () {
 4 
 5    /* 定义一个 5行 2 列的二维数组 */
 6    int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};
 7    int i, j;
 8 
 9    /* 输出每个元素的值 */
10    for ( i = 0; i < 5; i++ ) {
11       for ( j = 0; j < 2; j++ ) {
12          NSLog(@"a[%d][%d] = %d
", i,j, a[i][j] );
13       }
14    }
15 
16    return 0;
17 }

执行上面示例代码,得到以下结果:

 1 2018-11-15 03:19:28.766 main[119405] a[0][0] = 0
 2 2018-11-15 03:19:28.768 main[119405] a[0][1] = 0
 3 2018-11-15 03:19:28.768 main[119405] a[1][0] = 1
 4 2018-11-15 03:19:28.768 main[119405] a[1][1] = 2
 5 2018-11-15 03:19:28.768 main[119405] a[2][0] = 2
 6 2018-11-15 03:19:28.768 main[119405] a[2][1] = 4
 7 2018-11-15 03:19:28.768 main[119405] a[3][0] = 3
 8 2018-11-15 03:19:28.768 main[119405] a[3][1] = 6
 9 2018-11-15 03:19:28.768 main[119405] a[4][0] = 4
10 2018-11-15 03:19:28.768 main[119405] a[4][1] = 8

如上所述,可以拥有任意数量的数组,但创建的大多数数组一般都是一维或二维。

4.2 将数组传递给函数

如果要将一维数组作为参数传递给函数,则必须以下列三种方式之一声明函数形式参数,并且所有三种声明方法都会产生类似的结果,因为每个都告诉编译器接受一个整数指针。类似地,可以将多维数组作为形式参数传递。

方式-1

使用指针形式参数如下(在下一章学习指针的用法)。

1 - (void) myFunction(int *) param {
2 .
3 .
4 .
5 }

方式-2

使用大小数组的形式参数如下 -

1 - (void) myFunction(int [10] )param {
2 .
3 .
4 .
5 }

方式-3

形式参数作为未指定大小数组如下 -

1 -(void) myFunction: (int []) param {
2 .
3 .
4 .

示例

现在,考虑以下函数,它将数组作为参数与另一个参数一起使用,并根据传递的参数,它将返回通过数组传递的数值的平均值,如下所示 -

 1 -(double) getAverage:(int []) arr andSize:(int) size {
 2    int    i;
 3    double avg;
 4    double sum;
 5 
 6    for (i = 0; i < size; ++i) {
 7       sum += arr[i];
 8    }
 9 
10    avg = sum / size;
11    return avg;
12 }

现在,将上述函数调用如下 -

 1 #import <Foundation/Foundation.h>
 2 
 3 @interface SampleClass:NSObject
 4 
 5 /* 函数声明 */
 6 -(double) getAverage:(int []) arr andSize:(int) size;
 7 
 8 @end
 9 
10 @implementation SampleClass
11 
12 -(double) getAverage:(int []) arr andSize:(int) size {
13    int    i;
14    double avg;
15    double sum =0;
16 
17    for (i = 0; i < size; ++i) {
18       sum += arr[i];
19    }
20 
21    avg = sum / size;
22    return avg;
23 }
24 
25 @end
26 int main () {
27 
28    /* 一个拥有 5 个元素的数组 */
29    int balance[5] = {1000, 2, 3, 17, 50};
30    double avg;
31 
32    SampleClass *sampleClass = [[SampleClass alloc]init];
33    /* 将指针传递给数组作为参数 */
34    avg = [sampleClass getAverage:balance andSize: 5] ;
35 
36    /* 输出返回值 */
37    NSLog( @"Average value is: %f ", avg );
38 
39    return 0;
40 }

执行上面示例代码,得到以下结果:

2018-11-15 03:28:08.265 main[86840] Average value is: 214.400000

如上所见,就函数而言,数组的长度无关紧要,因为Objective-C不对形式参数执行边界检查。

4.3 从函数返回数组

Objective-C编程语言不允许将整个数组作为参数返回给函数。 但是,可以通过指定不带索引的数组名称来返回指向数组的指针。 我们将在下一节学习指针,读者可可以跳过本节,直到理解Objective-C中的指针概念,然后再返回学习本节内容。

如果要从函数返回一维数组,则必须声明一个返回指针的函数,如下例所示 -

1 int * myFunction() {
2 .
3 .
4 .
5 }

要注意的是Objective-C不主张将局部变量的地址返回到函数外部,因此必须将局部变量定义为静态变量。

现在,考虑以下函数,它将生成10个随机数,并将它们放入数组返回,调用此函数如下 -

 1 #import <Foundation/Foundation.h>
 2 
 3 @interface SampleClass:NSObject
 4 - (int *) getRandom;
 5 @end
 6 
 7 @implementation SampleClass
 8 
 9 /* 用于生成和返回随机数的函数 */
10 - (int *) getRandom {
11    static int  r[10];
12    int i;
13 
14    /* 设置随机种子 */
15    srand( (unsigned)time( NULL ) );
16    for ( i = 0; i < 10; ++i) {
17       r[i] = rand();
18       NSLog( @"r[%d] = %d
", i, r[i]);
19    }
20 
21    return r;
22 }
23 
24 @end
25 
26 /* 调用上面定义的函数的主函数 */
27 int main () {
28 
29    /* 一个指向int的指针 */
30    int *p;
31    int i;
32 
33    SampleClass *sampleClass = [[SampleClass alloc]init];
34    p = [sampleClass getRandom];
35    for ( i = 0; i < 10; i++ ) {
36       NSLog( @"*(p + %d) : %d
", i, *(p + i));
37    }
38 
39    return 0;
40 }

执行上面示例代码,得到以下结果:

 1 2018-11-15 03:34:00.443 main[117032] r[0] = 932030458
 2 2018-11-15 03:34:00.445 main[117032] r[1] = 1604274933
 3 2018-11-15 03:34:00.445 main[117032] r[2] = 996406515
 4 2018-11-15 03:34:00.445 main[117032] r[3] = 1073657342
 5 2018-11-15 03:34:00.445 main[117032] r[4] = 1208715588
 6 2018-11-15 03:34:00.445 main[117032] r[5] = 611149669
 7 2018-11-15 03:34:00.445 main[117032] r[6] = 417647883
 8 2018-11-15 03:34:00.445 main[117032] r[7] = 1140301536
 9 2018-11-15 03:34:00.445 main[117032] r[8] = 95760175
10 2018-11-15 03:34:00.445 main[117032] r[9] = 2100150993
11 2018-11-15 03:34:00.445 main[117032] *(p + 0) : 932030458
12 2018-11-15 03:34:00.445 main[117032] *(p + 1) : 1604274933
13 2018-11-15 03:34:00.445 main[117032] *(p + 2) : 996406515
14 2018-11-15 03:34:00.445 main[117032] *(p + 3) : 1073657342
15 2018-11-15 03:34:00.445 main[117032] *(p + 4) : 1208715588
16 2018-11-15 03:34:00.445 main[117032] *(p + 5) : 611149669
17 2018-11-15 03:34:00.445 main[117032] *(p + 6) : 417647883
18 2018-11-15 03:34:00.445 main[117032] *(p + 7) : 1140301536
19 2018-11-15 03:34:00.445 main[117032] *(p + 8) : 95760175
20 2018-11-15 03:34:00.445 main[117032] *(p + 9) : 2100150993

4.4 指向数组的指针

在学习与Objective-C中的指针相关的章节之前,您理解本章很可能有点吃力。

因此,在学习本节之前,我们假设您对Objective-C编程语言中的指针有一点了解。数组名称是指向数组第一个元素的常量指针。 因此,在声明中 -

double balance[50];

balance是指向&balance [0]的指针,它是balance数组的第一个元素的地址。 因此,以下程序片段为p分配第一个balance元素的地址 -

1 double *p;
2 double balance[10];
3 
4 p = balance;

将数组名称用作常量指针是合法的,反之亦然。 因此,*(balance + 4)balance[4]访问数据的合法方式。

将第一个元素的地址存储在p中后,可以使用* p*(p + 1)*(p + 2)等访问数组元素。 以下是显示上述所有概念的示例 -

 1 #import <Foundation/Foundation.h>
 2 
 3 int main () {
 4 
 5    /* 一个拥有 5 个元素的数组 */
 6    double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
 7    double *p;
 8    int i;
 9 
10    p = balance;
11 
12    /* 输出数组中所有元素的值 */
13    NSLog( @"Array values using pointer
");
14    for ( i = 0; i < 5; i++ ) {
15       NSLog(@"*(p + %d) : %f
",  i, *(p + i) );
16    }
17 
18    NSLog(@"Array values using balance as address
");
19    for ( i = 0; i < 5; i++ ) {
20       NSLog(@"*(balance + %d) : %f
",  i, *(balance + i) );
21    }
22 
23    return 0;
24 }

执行上面示例代码,得到以下结果:

 1 2018-11-15 03:49:56.217 main[177516] Array values using pointer
 2 2018-11-15 03:49:56.220 main[177516] *(p + 0) : 1000.000000
 3 2018-11-15 03:49:56.220 main[177516] *(p + 1) : 2.000000
 4 2018-11-15 03:49:56.220 main[177516] *(p + 2) : 3.400000
 5 2018-11-15 03:49:56.220 main[177516] *(p + 3) : 17.000000
 6 2018-11-15 03:49:56.220 main[177516] *(p + 4) : 50.000000
 7 2018-11-15 03:49:56.220 main[177516] Array values using balance as address
 8 2018-11-15 03:49:56.220 main[177516] *(balance + 0) : 1000.000000
 9 2018-11-15 03:49:56.220 main[177516] *(balance + 1) : 2.000000
10 2018-11-15 03:49:56.220 main[177516] *(balance + 2) : 3.400000
11 2018-11-15 03:49:56.220 main[177516] *(balance + 3) : 17.000000
12 2018-11-15 03:49:56.220 main[177516] *(balance + 4) : 50.000000

在上面的例子中,p是一个指向double的指针,它可以存储double类型变量的地址。当在p中有地址,那么*p将给出在p中存储的地址可用的值,正如在上面的例子中所示的那样。

原文地址:https://www.cnblogs.com/strengthen/p/10563645.html