zoukankan      html  css  js  c++  java
  • [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中存储的地址可用的值,正如在上面的例子中所示的那样。

  • 相关阅读:
    加入创业公司有什么利弊
    Find Minimum in Rotated Sorted Array II
    Search in Rotated Sorted Array II
    Search in Rotated Sorted Array
    Find Minimum in Rotated Sorted Array
    Remove Duplicates from Sorted Array
    Spiral Matrix
    Spiral Matrix II
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/strengthen/p/10563645.html
Copyright © 2011-2022 走看看