序列和数组映射

From Apache OpenOffice Wiki
< Zh‎ | Documentation
Revision as of 17:03, 4 July 2018 by Sancho (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search



许多 UNO 接口使用序列及简单类型。在 OpenOffice.org Basic 中,与序列相对应的是数组。数组是 Basic 语言的标准元素。下面的示例说明了如何声明数组:

 Dim a1( 100 ) ' Variant array, index range: 0-100 -> 101 elements
 
 Dim a2%( 5 ) ' Integer array, index range: 0-5 -> 6 elements
 
 Dim a3$( 0 ) ' String array, index range: 0-0 -> 1 element
 
 Dim a4&( 9, 19 ) ' Long array, index range: (0-9) x (0-19) -> 200 elements


Basic 中没有特殊的索引运算符,如 C++ 和 Java 中的 []。而是使用普通括号 () 访问数组元素:

 Dim i%, a%( 10 )
 for i% = 0 to 10           ' this loop initializes the array
     a%(i%) = i%
 next i%
 
 dim s$
 for i% = 0 to 10           ' this loop adds all array elements to a string
     s$ = s$ + " " + a%(i%)
 next i%
 msgbox s$                  ' Displays the string containing all array elements
  
 Dim b( 2, 3 )
 b( 2, 3 ) = 23
 b( 0, 0 ) = 0
 b( 2, 4 ) = 24             ' Error ”Subscript out of range”

如示例所示,Dim 命令中的索引不同于 C++ 和 Java 数组声明。它们不是描述元素的数目,而是描述允许的最大索引。数组元素比给定索引多一个。这对于将 OpenOffice.org Basic 数组映射成 UNO 序列非常重要,因为 UNO 序列遵循 C++/Java 数组语义。


当 UNO API 需要一个序列时,Basic 程序员可以使用一个相应的数组。在以下示例中,oSequenceContainer 是一个对象,其具有一个类型为 sequence<short> 的属性 TheSequence。要将一个长度为 10、值为 0, 1, 2, ...9 的序列指定给该属性,可以使用以下代码:

 Dim i%, a%( 9 ) ' Maximum index 9 -> 10 elements
 for i% = 0 to 9 ' this loop initializes the array
     a%(i%) = i%
 next i%
 
 oSequenceContainer.TheSequence = a%()
 
 ' If “TheSequence” is based on XPropertySet alternatively
 oSequenceContainer.setPropertyValue( “TheSequence”, a%() )


Basic 程序员在编程时,需要了解不同的索引语义。在以下示例中,程序员传送包含一个元素的序 列,但实际上传送了两个元素:

 ' Pass a sequence of length 1 to the TheSequence property:
 Dim a%( 1 )   ' WRONG: The array has 2 elements, not only 1!
 a%( 0 ) = 3   ' Only Element 0 is initialized, 
               ' Element 1 remains 0 as initialized by Dim
   
 ' Now a sequence with two values (3,0) is passed what 
 ' may result in an error or an unexpected behavior!
 oSequenceContainer.setPropertyValue( “TheSequence”, a%() )


Documentation note.png 将 Basic 数组作为一个整体用于参数或用于属性访问时,在 Basic 代码中数组后面应始终跟有 '()',否则,某些情况下可能会发生错误。


使用一个称为 Array() 的 OpenOffice.org Basic RTL 函数,通过一步就可以创建、初始化数组并将它指定给 Variant 变量,这非常有用,尤其是对于小型序列:

 Dim a ' should be declared as Variant
 a = Array( 1, 2, 3 )
 
 ' is the same as
 
 Dim a(2)
 a( 0 ) = 1
 a( 1 ) = 2
 a( 2 ) = 3


有时,有必要将空序列传送到 UNO 接口。在 Basic 中,可以通过在 Dim 命令中忽略索引来声明空序列:

 Dim a%() ' empty array/sequence of type Integer
 
 Dim b$() ' empty array/sequence of String

UNO 返回的序列在 Basic 中也表示为数组,但不必事先声明这些数组。应该将用于接受序列的变量声明为 Variant。要访问 UNO 返回的数组,需要获得有关 Basic RTL 函数 LBound()UBound() 所包含的元素数目的信息。


函数 LBound() 返回下限索引,而 UBound() 返回上限索引。以下代码示意了一个循环,该循环将遍历所返回序列的所有元素:

 Dim aResultArray ' should be declared as Variant
 aResultArray = oSequenceContainer.TheSequence
 
 dim i%, iFrom%, iTo%
 iFrom% = LBound( aResultArray() )
 iTo% = UBound( aResultArray() )
 for i% = iFrom% to iTo% ' this loop displays all array elements
 msgbox aResultArray(i%)
 next i%


函数 LBound() 是一个标准的 Basic 函数,而不是 UNO 上下文中所特有的。Basic 数组不必从索引 0 开始,因为可能写入如下所示的内容:

 Dim a (3 to 5 )


这使数组的下限索引为 3。但是,UNO 返回序列的索引通常从 0 开始。一般仅使用 UBound(),这时上面的示例可以简化为:

 Dim aResultArray ' should be declared as Variant
 aResultArray = oSequenceContainer.TheSequence
 
 Dim i%, iTo%
 iTo% = UBound( aResultArray() )
 For i% = 0 To iTo% ' this loop displays all array elements
     MsgBox aResultArray(i%)
 Next i%


序列/数组的元素数目非常容易计算:

 u% = UBound( aResultArray() )
 ElementCount% = u% + 1


对于空数组/序列,UBound 返回 -1。这样,随后按如下所示计算元素数目时,UBound 的语义就可以保持一致:

 ElementCount% = u% + 1' = -1 + 1 = 0


Documentation note.png UNO 序列与 Basic 数组之间的映射前提二者都使用一个基于零的索引系统。为了避免出现问题,不要使用语法
  Dim a ( IndexMin to IndexMin ) 

或 Basic 命令 Option Base 1。这二者使所有 Basic 数组的索引都不是从 0 开始。


UNO 还支持包含序列的序列。在 Basic 中,这对应于包含数组的数组。不要将包含序列的序列与多维数组相混淆。在多维数组中,所有子数组始终具有相同数目的元素,而在包含序列的序列中,每个序列可以具有不同的大小。示例:

 Dim aArrayOfArrays ' should be declared as Variant
 aArrayOfArrays = oExample.ShortSequences ' returns a sequence of sequences of short
 
 Dim i%, NumberOfSequences%
 Dim j%, NumberOfElements%
 Dim aElementArray
 
 NumberOfSequences% = UBound( aArrayOfArrays() ) + 1
 For i% = 0 to NumberOfSequences% - 1' loop over all sequences
     aElementArray = aArrayOfArrays( i% )
     NumberOfElements% = UBound( aElementArray() ) + 1
     
     For j% = 0 to NumberOfElements% - 1 ' loop over all elements
         MsgBox aElementArray( j% )
     Next j%
 Next i%


要在 Basic 中创建一个包含数组的数组,可以将子数组作为主数组的元素::

 ' Declare master array
 Dim aArrayOfArrays( 2 )
 
 ' Declare sub arrays
 Dim aArray0( 3 )
 Dim aArray1( 2 )
 Dim aArray2( 0 )
 
 ' Initialise sub arrays
 aArray0( 0 ) = 0
 aArray0( 1 ) = 1
 aArray0( 2 ) = 2
 aArray0( 3 ) = 3
 
 aArray1( 0 ) = 42
 aArray1( 1 ) = 0
 aArray1( 2 ) = -42
 
 aArray2( 0 ) = 1
 
 ' Assign sub arrays to the master array
 aArrayOfArrays( 0 ) = aArray0()
 aArrayOfArrays( 1 ) = aArray1()
 aArrayOfArrays( 2 ) = aArray2()
 
 ' Assign the master array to the array property
 oExample.ShortSequences = aArrayOfArrays()


在这种情况下,运行时函数 Array() 非常有用。这样,示例代码就可以变得更加简练:

 ' Declare master array
 Dim aArrayOfArrays( 2 )
 
 ' Create and assign sub arrays
 aArrayOfArrays( 0 ) = Array( 0, 1, 2, 3 )
 aArrayOfArrays( 1 ) = Array( 42, 0, -42 )
 aArrayOfArrays( 2 ) = Array( 1 )
 
 ' Assign the master array to the array property
 oExample.ShortSequences = aArrayOfArrays()


如果嵌套使用 Array(),就可以编写更简练的代码,但会使得人们难以理解将要生成的数组:

 ' Declare master array variable as variant
 Dim aArrayOfArrays
 
 ' Create and assign master array and sub arrays
 aArrayOfArrays = Array( Array( 0, 1, 2, 3 ), Array( 42, 0, -42 ), Array( 1 ) )
 
 ' Assign the master array to the array property
 oExample.ShortSequences = aArrayOfArrays()

对于更高阶次的序列,也可以进行相应处理。

Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages