跳轉到內容

軟體工程師手冊/語言字典/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 位元組。
華夏公益教科書