LPC 语言基础教程:6.2 数组

本文节选自《LPC语言基础教程:从零学习游戏开发》,版权归@mudren,欢迎转载,但必须注明来源(mud.ren)。

数组也是日常开发中最常用的数据类型之一,前面章节已经讲解了数组数据类型的赋值方式,下面补充数组的更多知识。

对数组元素的增删改查:

int main(object me, string arg)
{
    int *arr = ({});
    // 增
    arr += ({1});
    arr += ({1});
    // 改
    arr[0] = 2;
    // 删
    arr -= ({2});
    // 查:arr[n]或arr[<n]或arr[x..y]

    return 1;
}

重要提示:对数组+-隐含copy操作,数组指向了新的地址。

另外,数组还支持&|运算:

({ 1, 2, 3 }) & ({ 2, 4 }) = ({ 2 })
({ 1, 2, 3 }) | ({ 2, 4 }) = ({ 1, 2, 3, 4 })

both &= and |= now work with arrays

从特性来说,LPC中的数组更类似Python语言中的列表(list),操作灵活

除了以上运算符,还支持数组延展运算符...,示例:

int main(object me, string arg)
{
    int *a = ({2, 3, 4});
    int *b = ({1, a..., 5}); // b = ({1,2,3,4,5})
    mixed *c = ({"mudren", 18, "武当派"});

    printf("%O\n", b);
    // 输出:name = mudren, age = 18, family = 武当派
    printf("name = %s, age = %d, family = %s\n", c...);

    return 1;
}

需要注意的是,数组的数据类型只在单独赋值时会做限制,在声明数组元素并赋值时可以赋值任何类型,比如一个字符串数组的元素可以在声明时赋值整型数据,但在单独赋值时元素类型必须和数组类型一致。

数组是一种特殊的数据类型,变量存的是地址而不是值,我们看看以下示例:

// 示例:6.2.1

int main(object me, string arg)
{
    int *a, *b = ({1});
    a = b;
    a[0] = 2;
    printf("a = %O\nb = %O\n", a, b);

    return 1;
}

运行结果如下:

a = ({ /* sizeof() == 1 */
  2
})
b = ({ /* sizeof() == 1 */
  2
})

示例中改变了数组 a 的值,但数组 b 的值也变了,因为数组变量名指向数组首地址,数组变量存的是地址而不是数值。 如果需要把数组 b 的值赋值给数组 a ,且改变一个的值时不影响另一个,可以使用 copy() 外部函数,具体语法如下:

名称

copy - 可以递归的复制一个变量值

语法

mixed copy(mixed arg);

说明

返回变量 `arg` 的复制。变量只能是以下类型:array、buffer、class、mapping。

看看以下示例:

// 示例:6.2.2

int main(object me, string arg)
{
    int *a, *b = ({1});
    a = copy(b);
    a[0] = 2;
    printf("a = %O\nb = %O\n", a, b);

    return 1;
}

运行结果如下:

a = ({ /* sizeof() == 1 */
  2
})
b = ({ /* sizeof() == 1 */
  1
})

比较特别的是,LPC 语言中数组可以直接使用 + 合并,数组元素也可以直接使用 - 移除,这个也在前面章节有讲解,但是有个细节需要注意,我们看看以下示例:

// 示例:6.2.3

int main(object me, string arg)
{
    int *a, *b = ({1});
    a = b;
    a[0] = 2;
    b += a;
    printf("a = %O\nb = %O\n", a, b);

    return 1;
}

运行结果如下:

a = ({ /* sizeof() == 1 */
  2
})
b = ({ /* sizeof() == 2 */
  2,
  2
})

示例中数组 b 的改变并没有影响数组 a,这是因为使用 + 做数组运算时并不是改变了原始数组的值,而是改变了数组在内存中的地址。

数组相关外部函数如下:

  1. allocate - 初始化数组
  2. arrayp(pointerp)- 判断变量是否是数组
  3. element_of - 返回数组的随机元素
  4. filter_array - 过滤数组元素并返回过滤后的数组
  5. implode - 合并数组为字符串
  6. map_array - 修改数组元素并返回修改后的数组
  7. member_array - 判断指定值是否是数组中的元素
  8. shuffle - 随机打乱字符串元素
  9. sort_array - 数组排序
  10. unique_array - 分组数组元素并返回

函数具体用法请看:https://wiki.mud.ren/index.php?title=Lpc:Efun

当数组当元素还是数组时,就是二维数组,我们可以使用以下方式定义二维数组:

a = allocate(10);
a[0] = allocate(10);
a[1] = allocate(10);
...

或者

mixed a;
a = ({ ({ 1, 2, 3 }), ({ 1, 2, 3 }) });

使用 mixed 定义可以定义二维数组,也可以定义元素类型为混合类型的数组。如果变量类型只为数组,推荐也加上 *(使用 mixed *a;),虽然这并没有什么用,但是可以统一数组的定义样式,知道这个变量应该是一个数组。

mixed类型数组元素不只是可以是数组,而是可以是任何类型的数据,不像其他多数编程语言数组元素限制同一种数据类型,如:({1,'a',"b",({1,2,3}),(["a":"b"]), me})是一个合法的数组。

数组在使用时需要注意索引越界问题,可以使用 sizeof() 外部函数获取数组元素个数,具体语法如下:

名称

sizeof() - 返回 array、mapping、buffer 或 string 类型数据的元素个数

语法

int sizeof( mixed var );

描述

返回 array、mapping、buffer 或 string 类型数据 `var` 的元素个数,如果 `var` 不是以上类型,返回 0 。

另外,和字符串类似,数据也有一种定界符样式,和字符串不同的是使用@@

@@poem
二月春来半,宫中日渐长。
柳垂金屋暖,花发玉楼香。
拂匣先临镜,调笙更炙簧。
还将歌舞态,只拟奉君王。
poem

这就是一个字符串数组,每行分别是一个字符串元素。

最后,数组也可以调用函数,如下格式:

({x,y,z})->func();

数组的每个元素都会调用func()。

京ICP备13031296号-4