软件工程师手册/语言字典/PLI/数组
注意: 本文需要对 PL/I 的基本了解,可以在软件工程师手册/语言字典/PLI中找到。
可以使用以下语法声明简单数组
DCL name_of_array ( higher_bound ) type_of_elements; or DCL name_of_array ( lower_bound : higher_bound ) type_of_elements;
如果省略下界,它将获得默认值 1。
example: proc options ( main ); dcl array_A ( 5) char (03); /* array_A has 5 elements with index 1 to 5 */ dcl array_B (0:5) char (03); /* array_B has 6 elements with index 0 to 5 */ array_A ( 1 ) = 4711; /* fill first element of array_A ... */ array_B ( 0 ) = array_A ( 1 ); /* ... and copy its value to first element of array_B */ end example;
多维数组通过用逗号分隔维度来声明。
example: proc options ( main ); dcl matrix ( 2 , 6:7 ) bin fixed (31); /* defines a 2-dimensional array of 4 elements: matrix ( 1 , 6 ) , matrix ( 1 , 7 ) , */ /* matrix ( 2 , 6 ) , matrix ( 2 , 7 ) */ matrix ( 1 , 6 ) = 123; /* store number into first matrix element */ matrix ( 2 , 7 ) = 456; /* store number into last matrix element */ end example;
数组的元素不仅可以是数字、字符串或指针之类的简单类型,还可以是条目变量、文件、结构...
example: proc options ( main ); dcl 1 month ( 12 ), /* means January ... December */ 2 income dec fixed ( 7 , 2 ), 2 outgo dec fixed ( 7 , 2 ); month ( 1 ) . income = 1234.56; /* store income-value of January */ month . income ( 2 ) = 2345.67; /* store income-value of February */ month ( 3 ) . outgo = 3456.78; /* store outgo-value of March */ month . outgo ( 4 ) = 4567.89; /* store outgo-value of April */ end example;
example: proc options ( main ); dcl 1 year ( 1999 : 2019 ), 2 month ( 12 ), 3 value ( 3 , 3 ) bin fixed (15); /* all of the following statements are equal */ year ( 2009 ) . month ( 9 ) . value ( 1 , 2 ) = 32767; year . month ( 2009 , 9 ) . value ( 1 , 2 ) = 32767; year . month . value ( 2009 , 9 , 1 , 2 ) = 32767; year . month ( 2009 , 9 , 1 , 2 ) . value = 32767; year ( 2009 , 9 , 1 , 2 ) . month . value = 32767; end example;
可以使用 INITIAL(缩写:INIT)属性来初始化数组。
必须为每个数组元素分别进行初始化。
要指定一个未初始化的单个元素,可以使用星号。
在下面的示例中,程序 left 将等效于程序 right。
left: proc options ( main ); right: proc options ( main ); dcl A ( 4 ) char (03) dcl A ( 4 ) char (03); init ( 'ABC' , * , 'XYZ' ); A ( 1 ) = 'ABC'; A ( 3 ) = 'XYZ'; end left; end right;
为了使初始化一个巨大的数组更加方便,可以使用迭代因子(前缀“(n)”表示:使用后面的值 n 次)。
left: proc options ( main ); right: proc options ( main ); dcl A ( 2 , 3 ) bin fixed (15) dcl A ( 2 , 3 ) bin fixed (15); init ( (2)5 , (2)* , (2)6 ); A ( 2 , 1 ) = 5; A ( 2 , 2 ) = 5; /* A ( 2 , 3 ) will be left uninitialised */ /* A ( 3 , 1 ) will be left uninitialised */ A ( 3 , 2 ) = 6; A ( 3 , 3 ) = 6; end left; end right; left: proc options ( main ); right: proc options ( main ); dcl A ( 2 , 3 ) bin fixed (15) dcl A ( 2 , 3 ) bin fixed (15); init ( (2)(-3,7) , 99 ); A ( 2 , 1 ) = -3; A ( 2 , 2 ) = 7; A ( 2 , 3 ) = -3; A ( 3 , 1 ) = 7; A ( 3 , 2 ) = 99; end left; end right;
注意:PL/I 也为字符串提供迭代因子,例如表达式“(4)X”等效于“XXXX”。
因此,如果初始化一个字符串数组,则必须明确迭代因子是针对字符串还是针对初始化。
init ( (2) (3) 'X' ) ... means use twice: 'XXX' init ( (6) 'X' ) ... means use once-only: 'XXXXXX' init ( (6) ( 'X' ) ) ... means use 6 times: 'X'
- 数组表达式可以包含数组和单个值。
- 表达式中的所有数组必须具有相同的结构,即它们必须具有相同的维度数,并且相应的维度必须具有相同的界限。
- 表达式的结果具有与所包含数组相同的结构。
- 表达式的结果可以分配给具有相同结构的数组变量。
在下面的示例中,程序 left 将等效于程序 right。
left: proc options ( main ); right: proc options ( main ); dcl A (2,6:7) bin fixed (15); dcl A (2,6:7) bin fixed (15); dcl B (2,6:7) bin fixed (15); dcl B (2,6:7) bin fixed (15); dcl C (2,6:7) bin fixed (15); dcl B (2,6:7) bin fixed (15); /* fill variable B */ /* fill variable B */ /* fill variable C */ /* fill variable C */ A = B + C * 5; A ( 1 , 6 ) = B ( 1 , 6 ) + C ( 1 , 6 ) * 5; A ( 1 , 7 ) = B ( 1 , 7 ) + C ( 1 , 7 ) * 5; A ( 2 , 6 ) = B ( 2 , 6 ) + C ( 2 , 6 ) * 5; A ( 2 , 7 ) = B ( 2 , 7 ) + C ( 2 , 7 ) * 5; end left; end right;
对数组执行的所有操作都是按元素方式进行的,以从右到左的维度顺序进行。
left: proc options ( main ); right: proc options ( main ); dcl A (2,2) init ( 1, 2, 10, 50 ); dcl A (2,2) init ( 1, 2, 10, 50 ); A = A + A ( 2 , 1 ); A ( 1 , 1 ) = A ( 1 , 1 ) + A ( 2 , 1 ); /* = 1 + 10 = 11 */ A ( 1 , 2 ) = A ( 1 , 2 ) + A ( 2 , 1 ); /* = 2 + 10 = 11 */ A ( 2 , 1 ) = A ( 2 , 1 ) + A ( 2 , 1 ); /* = 10 + 10 = 20 */ A ( 2 , 2 ) = A ( 2 , 2 ) + A ( 2 , 1 ); /* = 50 + 20 = 70 */ end left; end right;
使用星号表示法可以引用数组的横截面。
星号指定将使用此维度的整个范围。
If an array is declared as dcl A ( 2 , 3 ) char (06); the reference A ( * , 3 ) refers to a 1-dimensional array containing the elements A ( 1 , 3 ) and A ( 2 , 3 ), the reference A ( 1 , * ) refers to a 1-dimensional array containing the elements A ( 1 , 1 ) and A ( 1 , 2 ) and A ( 1 , 3 ).
在下面的示例中,程序 left 将等效于程序 right。
left: proc options ( main ); right: proc options ( main ); dcl A ( 2 , 2 ) char (10); dcl A ( 2 , 2 ) char (10); dcl B ( 2 , 2 ) char (10); dcl B ( 2 , 2 ) char (10); A ( * , * ) = 'hello PL/I'; A = 'hello PL/I'; /* fill all elements of A */ B ( * , 1 ) = A ( 2 , * ); B ( 1 , 1 ) = A ( 2 , 1 ); B ( 2 , 1 ) = A ( 2 , 2 ); end left; end right;
可以使用 DEFINED(缩写:DEF)属性将新声明的数组映射到现有的“旧”数组。
在下面的示例中,程序 left 将等效于程序 right。
left: proc options ( main ); right: proc options ( main ); dcl A ( 8 , 8 ) char (10); dcl A ( 8 , 8 ) char (10); dcl B ( 6 , 6 ) char (10) defined A; dcl C ( 4 ) char (10) def A ( * , 2 ); A ( 6 , 6 ) = 'hello PL/I'; B ( 6 , 6 ) = 'hello PL/I'; A ( 4 , 2 ) = 'hello PL/I'; C ( 4 ) = 'hello PL/I'; end left; end right;
要引用旧数组中指定的元素,新数组的声明可以包含iSUB 元素。
iSUB 表示
每当访问新数组时,该引用的第 i 个索引将用于计算旧数组的索引。
在下面的示例中,程序 left 将等效于程序 right。
left: proc options ( main ); right: proc options ( main ); dcl A ( 8 , 8 ) char (10); dcl A ( 8 , 8 ) char (10); dcl transposed ( 8 , 8 ) char (10) DEF A ( 2sub , 1sub ); dcl centered ( 4 , 4 ) char (10) DEF A ( 1sub + 2 , 2sub + 2 ); dcl diagonal ( 8 ) char (10) DEF A ( 1sub , 1sub ); A ( 2 , 5 ) = 'hello PL/I'; transposed ( 5 , 2 ) = 'hello PL/I'; /* swap indexes */ A ( 3 , 6 ) = 'hello PL/I'; centered ( 1 , 4 ) = 'hello PL/I'; /* increase indexes */ A ( 7 , 7 ) = 'hello PL/I'; diagonal ( 7 ) = 'hello PL/I'; /* use index twice */ end left; end right;
数组将以元素方式进行连接存储,以从右到左的维度顺序进行。
dcl A ( 2 , 2 , 2 ) char (10); allocates adjacent storage in the following order: +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | A (1,1,1) | A (1,1,2) | A (1,2,1) | A (1,2,2) | A (2,1,1) | A (2,1,2) | A (2,2,1) | A (2,2,2) | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
对数组的横截面的引用可能指向非连接存储。
dcl A ( 2 , 2 ) will allocates storage in the following order: +-------------+-------------+-------------+-------------+ | A ( 1 , 1 ) | A ( 1 , 2 ) | A ( 2 , 1 ) | A ( 2 , 2 ) | +-------------+-------------+-------------+-------------+ the reference A ( 1 , * ) refers to connected storage. +-------------+-------------+ | A ( 1 , 1 ) | A ( 1 , 2 ) | +-------------+-------------+ the reference A ( * , 1 ) refers to unconnected storage. +-------------+ - - - - - - +-------------+ | A ( 1 , 1 ) | gap | A ( 2 , 1 ) | +-------------+ - - - - - - +-------------+
对数组内部的结构化元素的引用将指向非连接存储。
dcl 1 A ( 2 ), 2 B ... , 2 C ... ; will allocates storage in the following order: +-------------+-------------+-------------+-------------+ | A ( 1 ) . B | A ( 1 ) . C | A ( 2 ) . B | A ( 2 ) . C | +-------------+-------------+-------------+-------------+ the reference A . B refers to unconnected storage. +-------------+ - - - - - - +-------------+ | A ( 1 ) . B | gap | A ( 2 ) . B | +-------------+ - - - - - - +-------------+
对定义数组的引用可能指向非连接存储。
dcl A ( 2 , 2 ) will allocates storage in the following order: +-------------+-------------+-------------+-------------+ | A ( 1 , 1 ) | A ( 1 , 2 ) | A ( 2 , 1 ) | A ( 2 , 2 ) | +-------------+-------------+-------------+-------------+ dcl B ( 2 ) def A ( 1sub , 1sub ) refers to unconnected storage. +-------------+ - - - - - - + - - - - - - +-------------+ | B ( 1 ) | | B ( 2 ) | | refers to | gap | refers to | | A ( 1 , 1 ) | | A ( 2 , 2 ) | +-------------+ - - - - - - + - - - - - - +-------------+
常用函数
- LBOUND ( A , i ) 返回数组 A 的第 i 维度的下界。
- HBOUND ( A , i ) 返回数组 A 的第 i 维度的上界。
- DIM ( A , i ) 返回数组 A 的第 i 维度的范围,即 DIM ( A , i ) = HBOUND ( A , i ) - LBOUND ( A , i ) + 1。
数组 A 必须不是结构数组。
example: proc options ( main ); dcl matrix ( 15 , -4:4 ); put skip list ( LBOUND ( matrix , 1 ) ); /* output: 1 */ put skip list ( HBOUND ( matrix , 1 ) ); /* output: 15 */ put skip list ( DIM ( matrix , 1 ) ); /* output: 15 */ put skip list ( LBOUND ( matrix , 2 ) ); /* output: -4 */ put skip list ( HBOUND ( matrix , 2 ) ); /* output: 4 */ put skip list ( DIM ( matrix , 2 ) ); /* output: 9 */ end example;
数学函数
- SUM ( A ) 返回数组 A 中所有元素的总和。
- PROD ( A ) 返回数组 A 中所有元素的乘积。
example: proc options ( main ); dcl A ( 4 ) bin fixed (31) init ( 1 , 2 , 3 , 4 ); put skip list ( SUM ( A ) ); /* output: 10 = 1 + 2 + 3 + 4 */ put skip list ( PROD ( A ) ); /* output: 24 = 1 × 2 × 3 × 4 */ end example;
逻辑函数
内置函数 ANY 和 ALL 需要位字符串数组作为参数。
它们将在Software_Engineers_Handbook/Language_Dictionary/PLI/bit_strings中解释。
在 PL/I for MVS 中,数组受到以下限制
- 维度的最大数量为 15。
- 最小下界为 - 2,147,483,648 = - 231。
- 最大上界为 + 2,147,483,647 = + 231 - 1。
- 最大内存大小为 2,147,483,648 字节 = 231 字节。