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中存储的地址可用的值,正如在上面的例子中所示的那样。

  • 相关阅读:
    Oracle PL/SQL
    plsql命令行窗口执行脚本打印输出
    Oracle 数据库维护管理之--数据库基本信息表管理与优化参考1
    Oracle 数据库维护管理之--dbms_lock
    Oracle sys或者system的默认密码
    Docker学习--docker的基本认识
    正则表达式--指定时间格式校验
    Docker学习--基本docker命令
    HTTP协议以及HTTP请求中8种请求方法
    如何查看class文件的jdk版本
  • 原文地址:https://www.cnblogs.com/strengthen/p/10563645.html
Copyright © 2011-2022 走看看