數組是有序資料的集合。數組中的元素可以不屬於同一個資料型態。用一個統一的數組名和下標來唯一地確定數組中的元素,更改其中一個元素並不會影響其它元素。數組的下標是有界的,分為下界和上界。數組可以用Dim、Private、Public或Static來聲明,它們的語法格式相同。以下只介紹用Dim宣告數組的方法。
1.數組的定義與聲明
數組的定義語法如下:
Dim 陣列名( [[下標下界To ] 下標上界] ) [As 資料型別]
例如(假設在目前模組中數組的預設下界為0)):
① Dim A(10) As Integer
表示數組名為A,此數組下標下界為預設值0,下標上界為10,有11個Integer類型的元素,從A(0)、A(1)到A(10)。
② Dim B(1 To 20) As Integer
表示數組名為B,此數組下標下界為1,下標上界為20,有20個Integer類型的元素,從B(1)到B(20)。
③Dim DayArray(50)
表示DayArray 是一個有51 個索引(從0 到50)元素的Variant 陣列。
④Dim Matrix(3, 4) As Integer
表示Matrix 是一個二維Integer 陣列。
⑤Dim MyMatrix(1 To 5, 4 To 9, 3 To 5) As Double
表示MyMatrix 是一個明確指定了上下界的三維double 陣列。
⑥Dim BirthDay(1 To 10) As Date
表示BirthDay 是索引從1 到10 的Date型陣列。
2. Option Base 語句
Option Base 語句在模組層級使用,用來宣告陣列下標的預設下界。
Option Base 語句的語法如下:
Option Base {0 | 1}
說明:預設狀態下數組下界為0,此時無需使用Option Base 語句。如果使用該語句規定數組下界1,則必須在模組的數組宣告之前使用Option Base 語句。
注意:
(1)Dim、Private、Public、ReDim 以及Static 語句中的To 子句提供了更靈活的方式來控制陣列的下標。不過,如果沒有使用To 子句明確地指定下界,則可以使用Option Base 將預設下界設為1。使用Array 函數建立的陣列的下界也受Option Base 語句指定的下界的決定, 除非Array 是由類型庫(例如VBA.Array )名稱限定,如果是由類型庫名稱限定,則使用Array 函數建立的陣列的下界不受Option Base 的影響。
(1) Option Base 語句只會影響位於包含該語句的模組中的陣列下界。
關於數組聲明的幾點說明:
①數組名命名規則和變數名的相同。
②數組名後是用圓括弧括起來的,不能用方括弧,不同於C語。
③下標的下界必須不能大於其上界。
④可以用變數名或常數名(以及實數)作下標的邊界。當下標的邊界是常數名時,數組的大小固定,當下標的邊界是變數名稱時,數組的大小可作動態定義,即數組的大小取決於程式運行過程中變數的值。因此,VB 中數組又可分為兩種數組:靜態數組、動態數組。
3.靜態數組
靜態數組是指數組元素的數量是固定不變的,即它們所佔用的記憶體空間大小是固定不變的。根據固定大小數組的維數不同,可以將它分成一維數組和多維數組。
聲明多維數組的語法格式為:
Dim 陣列名([下標邊界清單]) [As 資料型別]
下標邊界的定義形式:[下標下界To]下標上界
下標邊界列表指用逗號分開的陣列各維的下標邊界,即
[下標下界To]下標上界,[下標下界To]下標上界,…,[下標下界To]下標上界
(第一維) (第二維) (第n維)
當n=1時,數組稱作一維數組;當n=2時,數組稱作二維數組;依次類推,當n=m時,數組稱作m維數組。
以下舉例介紹一維數組的使用。
'宣告一個長度為51的字串陣列FriendsName
Dim FriendsName(50) As String
'宣告一個長度為11的全域整數數組Class
Public Class(10) As Integer
一維數組中的元素個數為(上界-下界+1)。
為數組賦初值可以採用循環語句,如:
Dim I As Integer
For I = 0 To 11 '循環語句的使用程式流程的控制
C(I) = I
Next I
如果不明確指定下標下界,則陣列的下標下界由Option Base 語句控制。如果沒有Option Base 語句則下界為預設為0。
數組的維數並不限於2,在VB中,可以擴大至於60,在實際應用上對三維以上的數組的應用是不多的。定義一個多維數組時只需一條Dim語句指定數組的所有下標邊界即可,使用多維數組的可以很方便的表示一些有意義的統計數據。例如:
Dim Profit(16,10,12) As Currency
這個Profit陣列可用來表示以店名、部門及月份為參數的某百貨公司的利潤。如:Profit(2,8,11)代表了第二分店的第八部門在11月份的利潤。
4.動態數組
有時在陣列開始使用前,不能知道需要多大的陣列才能滿足實際需求。當然可以把陣列的大小定義到足夠大來滿足任意的實際應用需要,這種方法效率很低(大量浪費記憶體空間)。如果使用動態數組,就可以在程式運行時根據實際需要,精確定義數組的大小。
在宣告數組時,不給出維數列表就是將數組宣告為動態數組。例如:
Dim MyArry() As Integer
在使用動態數組前,必須使用ReDim語句把它重新定義。如前面聲明的數組MyArry,可以用以下語句將它定義為一個動態二維數組。
ReDim MyArry(10,10)
也可以重複執行ReDim語句,多次定義動態數組。使用ReDim最多能定義數組的維數是60。 ReDim語句可以改變數組每維的元素個數,但不能改變維數。以下是ReDim語句的一個標準應用舉例。
Dim MyArry() As Single '宣告動態數組
ReDim MyArry(30,20,10) '重新定義數組
ReDim MyArry(50,23,21) '再次重新定義數組
ReDim的語法與Dim的相同,此外,它還有選擇項Preserve關鍵字:
ReDim Preserve 陣列名稱([ [下標下界To]下標上界]) [As 資料型別]
例如:
ReDim MyArry(50,23,21)
ReDim Preserve MyArry(50,23,50)
注意:使用ReDim 時,重新定義數組會使所有數組元素的值消失,而使用Preserve可以保留資料。但用Preserve只能在改變數組的最後一維的大小時,保留數組的資料。對於一維數組來說,所有數據都會保留,而對於多維數組:只能改變最後一維的大小,才能保留全部數組數據,否則出錯。
5. LBound 函數與UBound 函數
LBound 函數和Ubound函數都是傳回一個Long 型數據,前者得到的值為指定數組維可用的最小下標,而後者得到的是最大下標。它們的語法為:
LBound(數組名[, 指定的維數])
UBound(數組名[, 指定的維數])
其中數組名是必選的。指定的維數是可選的,表示指定傳回哪一維的下界。 1 表示第一維,2 表示第二維,如此類推。如果省略指定的維數,就預設為1。
關於如何使用LBound 函數與UBound 函數可參考下例:
Dim A(1 to 100,3,-3 to 4) As Integer '定義一三維數組,假定沒有使用Option Base 語
'句改變數組下界的預設值。
對數組A使用Lbound 和Ubound函數,其傳回值清單如下
所有維度的預設下界取決於Option Base 語句的設定。可以看出對一數組使用LBound 函數與UBound 函數,可用來確定一個數組中元素的個數。
對於那些在宣告中用To 子句來設定維數的陣列而言,它們可以用任何整數作為下邊界而不受Option Base 語句的限制。
6.數組的進階功能
儘管數組最通常被用來儲存成組的變量,但是在別的一些方面數組也是很有用的。可以將一個陣列的內容賦值給另一個陣列、建立傳回陣列的函數,也可以建立傳回陣列的屬性。在許多情況下,這些技術能改進應用程式的效能。
正如可以將一個變數的值賦給另一個變量,例如StrA = StrB ,也可以將一個數組的內容賦給另一個數組。例如,要將一位元組型陣列從一個位置複製到另一個位置。可以透過每次複製一個位元組來實現,程式如下:
Sub ByteCopy(oldCopy() As Byte, newCopy() As Byte)
'參數oldCopy()是來源數組,newCopy()是目標數組
Dim i As Integer
ReDim newCopy (Lbound(oldCopy) To UBound(oldCopy)) '重新定義動態數組
For i = Lbound(oldCopy) To Ubound(oldCopy) '迴圈賦值
newCopy(i) = oldCopy(i)
Next
End Sub
一個更有效的簡單的方法就是直接將一個陣列賦給另一個陣列:
Sub ByteCopy(oldCopy() As Byte, newCopy() As Byte)
'參數oldCopy()是來源數組,newCopy()是目標數組
newCopy = oldCopy '利用陣列直接進行賦值
End Sub
關於變數賦值有一些規則需要銘記。例如,雖然可以將一個宣告為整型的變數賦給一個宣告為長整型的變數而不會產生任何問題,但是將一個長整型變數賦給一個整數變數就很容易導致溢位錯誤。除了遵守有關資料類型變數之間賦值時的規則外,數組賦值還要遵循另外一些規則,包括數組維數,每一維的大小,以及數組是固定的還是動態的。
①維數、資料型別不同的陣列賦值考慮的幾個因素
l 賦值符左邊的陣列類型:固定數組(Dim x(1 to 10) As Integer) 或動態數組(Dim x() As Integer)。
l 賦值符左邊數組的維數是否和賦值符右邊數組的維數匹配。
l 賦值符兩邊數組的每一維的陣列元素個數是否相符。即使數組的聲明不同,維數也可能匹配。例如一個陣列的每一維元素從0 開始編號而另一個則從1 開始,維數也可能符合。
l 賦值符兩邊所有元素的資料型別必須是相容的。這些規則和變數賦值的規則是一致的。
表3-6顯示了這些因素的影響:
數組賦值時的錯誤可能發生在編譯時,也可能發生在運行時(例如,如果資料類型不能強制轉換或賦值試圖重新聲明(ReDim) 一個靜態數組)。設計程式時要新增錯誤處理以確保陣列在賦值之前是相符的。
②編寫傳回數組的函數
從一個函數傳回一組值是可能實現的。例如,從函數傳回一組位元組而不必將其先轉換為字串然後再轉換回來。
下面是一個使用返回位元組數組的函數的簡單範例:
Private Sub Form_Load()
Dim b As Byte
Dim i As Integer
Dim ReturnArray() As Byte
b = Cbyte(54)
ReturnArray() = ArrayFunction(b) '呼叫函數
For i = Lbound(ReturnArray) To Ubound(ReturnArray)
Msgbox ReturnArray(i) '透過彈出訊息框循環顯示數組值
Next
End Sub
Public Function ArrayFunction(b As Byte) As Byte()
Dim x(2) As Byte
x(0) = b
x(1) = b + CByte(200)
x(2) = b + b
ArrayFunction = x '傳回結果為陣列x
End Function
在執行上述範例後, ReturnArray() 是一個三元素數組,其中包含了分配給ArrayFunction 中數組的值。 ArrayFunction 語句將一個陣列作為參數傳遞;且陣列的資料類型必須和函數的資料類型相同(在本例中是位元組)。因為這是一個函數調用,傳遞數組時不必帶括號。
注意:
1.雖然可以透過賦值給另一個數組(ArrayFunction = x())來傳回一個數組,但出於效能方面的考慮,並不建議使用這種方法。
2.必須為傳回數組的函數指定一個類型,這個類型可以是Variant。這樣一來,Function X() As Variant() 是有效的而Function X() As () 將會失敗。
3.當呼叫一個傳回數組的函數時,用來保存返回值的變數也必須是一個數組,而且其資料類型必須和函數返回類型相同,否則將顯示一個類型不匹配的錯誤。
定義簡單數組
有兩種方法在asp中定義和初始化數組,讓我們看看每種的範例:
方法一:
MyArray = Array(Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct, Nov,Dec)
數組大小由初始化元素個數決定。
方法二:
Dim myArray(2) '指定陣列大小
myArray(0)=Jan
myArray(1)=Feb
數組動態擴展
DIM myArray()
REDIM myArray(20) '將陣列大小重新定義為20
ReDim Preserve MyArray(i) 'Preserve 保留數組中的原有數據
二維數組
舉例:
dim MyArray(5,10) '定義了一個二維數組
二維賦值舉例:
MYArray(3,3)=100
二維數組還有一種變相的實作方法:
dim MyArray(5)
MyArray(0)=Array(...) '一維數組
MyArray(1)=Array(...)'一維數組
…
訪問的時候,用MyArray(x)(y)這樣的格式
數組的下標
用上面的方法定義數組,每一維數組的第一個元素的下標是0,最後一個元素的下標就是元素數量-1
但也可以指定數組的下標,如:
dim MyArray1(3 to 10) '下標從3到10,MyArray(3)即取得第一個元素的值
有用的數組函數
Ubound(數組名)函數--傳回陣列的最後一個元素的下標。
Lbound(數組名)函數--傳回數組的第一個元素的下標,預設為0。
更多應用:
數組排序函數
function Sort(ary)
KeepChecking = TRUE
Do Until KeepChecking = FALSE
KeepChecking = FALSE
For I = 0 to UBound(ary)
If I = UBound(ary) Then Exit For
If ary(I) > ary(I+1) Then
FirstValue = ary(I)
SecondValue = ary(I+1)
ary(I) = SecondValue
ary(I+1) = FirstValue
KeepChecking = TRUE
End If
Next
Loop
Sort = ary
End function
數組排序函數應用例子
Dim MyArray
MyArray = Array(1,5,123,12,98)
MyArray = Sort(MyArray)
For I = Lbound(MyArray) to Ubound(MyArray)
Response.Write MyArray(I) & <br>
Next
將一個字串分割並傳回數組
Dim MyArray
MyArray = Split(字串,分割符)
For I = Lbound(MyArray) to Ubound(MyArray)
Response.Write MyArray(I) & <br>
Next
在Application和Session中使用陣列
Application.Lock
Application(StoredArray) = MyArray
Application.Unlock
LocalArray = Application(StoredArray)
覆寫Application中的數組
Application.Lock
Application(StoredArray) = LocalArray
Application.Unlock
Session使用方法與Application相同
從資料庫中把資料導入數組中
Dim MyArray
取出全部記錄
MyArray = RS.GetRows
取出前10項記錄
MyArray = RS.GetRows(10)
For row = 0 To UBound(MyArray, 2)
For col = 0 To UBound(MyArray, 1)
Response.Write (col, row) & <br>
Next
Next
向另一個頁面傳遞數組
有很多種方法向另一頁傳遞數組,例如以下三種:
1.定義一個又逗號分隔的字串,然後再下一頁中用Split函數重新建立數組。
2.將陣列儲存在一個Session變數中,然後在下一個頁面中呼叫。
3.透過表單的隱含區域來傳遞數組,他們都是自動用逗號分開,然後再用Split函數重新建立數組。
前兩種方法很好,但是都比第三種複雜。在這裡我們將只介紹第三種,因為它是最簡單的。
文件1.asp:
<%
dim I
dim myArray(20)
for I=0 to 20
myArray(I)=Item & I
next
%>
<html>
<body>
<form name=testform method=post action=2.asp>
<%
for I=0 to ubound(myArray)
response.write <input type=hidden name=myArray value=' & myArray(I) & '>
next
%>
<p>
<input type=submit>
</form>
</body>
</html>
以上我們做的是在一個表單中用單獨的隱含域儲存數組中的每個元素,我們再看看下一頁:
檔案2.asp
<html>
<body>
<%
dim arrString
dim myArray
dim I
arrString=request(myArray)
myArray = split(arrString,,)
for I=0 to ubound(myArray)
response.write Item &I& = & myArray(I) & <br> & vbCrLf
next
%>
</body>
</html>