810 likes | 928 Vues
第十章 陣列. 章節預覽. 理論與 Visual Basic 相關基本知識 10.1 陣列 10.2 動態陣列與靜態陣列 10.3 搜尋與排序 10.4 控制項陣列 控制項 10.5 清單方塊 (ListBox) 控制項 10.6 下拉式清單方塊 (ComboBox) 控制項 10.7 功能表( Menu ) 10.8 本章整合應用實例. 10.1:陣列. 陣列 ( 重要的資料結構 ) 陣列是一種儲存大量同性質資料的良好環境,由於不需要使用不同的變數,以及存取陣列元素的方便性,使得大多數的程式設計都看得到陣列的影子。
E N D
章節預覽 • 理論與Visual Basic相關基本知識 • 10.1 陣列 • 10.2 動態陣列與靜態陣列 • 10.3 搜尋與排序 • 10.4 控制項陣列 • 控制項 • 10.5 清單方塊(ListBox)控制項 • 10.6 下拉式清單方塊(ComboBox)控制項 • 10.7 功能表(Menu) • 10.8 本章整合應用實例
10.1:陣列 • 陣列(重要的資料結構) • 陣列是一種儲存大量同性質資料的良好環境,由於不需要使用不同的變數,以及存取陣列元素的方便性,使得大多數的程式設計都看得到陣列的影子。 • 『陣列』與數學的「矩陣」非常類似。也就是每一個陣列中的元素都有它的編號。更明確地說,『陣列』是一群資料型態相同的變數,並且在記憶體中會以連續空間來加以存放。 • 例如,存放每月的營業額,可以使用January、February、、、December等12個數值變數來加以儲存,也可以使用陣列來加以儲存,並且只需要使用同一個陣列變數名稱即可,例如:Month (12)。當我們宣告Month(12)陣列時,Month就是陣列名稱,而在記憶體中則會保留13個連續位置分別存放Month(0)~Month(12)陣列元素。 • 陣列中每個元件(陣列元素)相當於一個變數,透過索引就可以直接取得陣列的指定元素 • 例如Month(1)~Month(12)存放12個月份的營業額,要取出8月份的營業額,只要使用Month(8)當做變數名稱即可。因此,使用陣列可以免除大量變數命名的問題,使得程式具有較高的可讀性。
10.1:陣列 • 宣告陣列-Dim敘述 • 由於陣列佔用較大的記憶體空間,因此『陣列』在使用之前必須先加以宣告,而宣告的目的,則是決定要在主記憶體中保留多少個連續空間給該陣列使用,以及宣告陣列中每一個元素的資料型態。宣告陣列也是使用Dim敘述,以下是陣列宣告語法 • 【語法說明】: • 1. 陣列名稱:陣列名稱的命名規定與變數命名規定相同,盡量採用有意義的英文字或組合字。 • 2. 索引:索引決定了該陣列為1維陣列、2維陣列、、、。也決定了每一維數的元素數目。舉例如下: 語法:Dim 陣列名稱 (索引1 [.索引2 [.....]]) [As資料型態] 功能:宣告一維(二維、三維、、)陣列,以及元素的資料型態。
10.1:陣列 • 【範例】:假設我們有12個月的營業額要記錄,您可以使用Month也可以使用Trade(交易)做為陣列名稱,如下宣告1維陣列:Dim Trade (12) As Integer 月份 • 則Trade(7)代表7月份的營業額。 • 【範例】:假設我們有兩年的每月營業額要記錄,則可以如下宣告2維陣列: Dim Trade (2 , 12) As Integer 年 月份 • 則Trade(2,7)代表第2年7月份的營業額。 • 【範例】:假設我們有兩家公司兩年的每月營業額要記錄,則可以如下宣告3維陣列:Dim score (2 , 2 , 12) As Integer 公司 年 月份 • 則Trade(1,2,7)代表第1家公司第2年7月份的營業額。
10.1:陣列 • 3. As資料形態資料型態但對於陣列而言,其重要性遠比變數的資料型態來得重要許多,原因是當您宣告了陣列的資料型態之後,陣列中每一個元素都是使用了該資料型態,因此,假設您宣告了過於大的資料型態(例如:只需要Integer卻使用Long資料型態),而該陣列共有100個元素的話,就浪費了100倍的記憶體空間。因此,慎選陣列的資料型態是非常很重要的。以下是各種常用的陣列基本資料形態宣告: • (1) As Integer:【範例】Dim Trade(12) As Integer • (2) As Long:【範例】Dim Trade(12) As Long • (3) As Single:【範例】Dim Trade(12) As Single • (4) As Double:【範例】Dim Trade(12) As Double • (5) As String:【範例】Dim Item(12) As String • (6) As Variant:【範例】Dim Item(12) As Variant或Dim Item(12)
10.1:陣列 • 4. 陣列宣告時後,若無設定初始值,則數值陣列的每個元素值為0,字串陣列的每個元素值為『空字串』。自由資料型態陣列的每個元素值為『空值』(Empty)。 • 5. 和全域變數與區域變數一樣,若在某個程序中宣告的陣列,僅僅該程序才可以使用該陣列;若在表單檔的工作區域(一般程序)宣告時,則所有的程序都可以使用該陣列(共用)。 • 6. 陣列元素可以和其他變數或其他陣列元素做運算。 • 【範例】:Trade(0)=Trade(1) +Trade(2)+ 、、、+Trade(12)Trade(0)=Trade(1)*12Trade(0)=Trade(1) +XTrade(0)=Trade(1) +TEST(2)
10.1:陣列 • 陣列索引的下界與上界 • Visual Basic的陣列索引內定由0開始,所以宣告A(10),代表一共有11個元素可以使用,即A(0)~A(10),若不習慣,Visual Basic也提供了一些變通方法來改變索引的上下界。 • Option Base • 宣告陣列前,若先使用Option Base則可以將索引值設定為從1開始。以下是語法: • 【語法說明】: • 1. 符號『|』有「或」的涵義,亦即您可以宣告Option Base 0或Option Base 1。 • 2. Option Base敘述必須在表單檔宣告區使用,並且必須置於所有Dim敘述之前。 語法:Option Base {0 | 1} 功能:宣告陣列索引值的下界(Low Bound)為0或1。
10.1:陣列 • 3. 省略Option Base敘述,則預設為Option Base 0。(以0為下界)A(n)的陣列元素為n+1個,如下範例: • 陣列元件共四個,分別為A(0)、A(1)、A(2)、A(3)。 • 4.Option Base 1,則A(n)的陣列有n個(1~n),如下範例、 • 陣列元件共三個,分別為A(1)、A(2)、A(3)。
10.1:陣列 • 直接宣告陣列索引值下界與上界 • 除了使用Option Base 0與1做為陣列下界宣告之外,我們也可以直接在使用Dim宣告陣列時,指定陣列的下界與上界。語法如下: • 【語法說明】: • 1. 索引值的下界~上界範圍可以由-2,147,483,648~2,147,483,647。例如:Dim A(-3 TO 2),則陣列元素分別為A(-3)、A(-2)、A(-1)、A(0)、A(1)、A(2)等6個元素。 • 2. 第二次出現的(下界 TO上界)代表第二維的索引範圍。 語法:Dim陣列名稱(下界To上界[,下界To上界...])[As資料型態] 功能:宣告陣列索引值的範圍(從下界到上界)。
10.1:陣列 • 取得陣列索引的上、下界值 • 【範例】:假設二維陣列Dim A(100, 50 To 60),則取出的上下界值如下: • LBound(A, 1) 回傳值為0。 (第一維的下界值) • LBound(A, 2) 回傳值為50。 (第二維的下界值) • UBound(A, 1) 回傳值為100。 (第一維的上界值) • UBound(A, 2) 回傳值為60。 (第二維的上界值) 語法:L=LBound(陣列名稱[,維數]) 功能:取得指定陣列某一維的索引下界值。 語法:U=UBound(陣列名稱[,維數]) 功能:取得指定陣列某一維的索引上界值。
10.1:陣列 • 初始與宣告陣列函數-Array 函數 • 使用Dim來宣告陣列,無法同時設定陣列初始值,不過Visual Basic提供了另一個函數可以同時宣告陣列與設定初始值,那就是Array函數,其語法如下: • 【語法說明】: • 1. Array函數所宣告的陣列為自由型態的陣列。 • 2. 引數串列:引述串列將做為元素值,由於是自由型態陣列,因此引數中的元素可以是任一種資料型態,並且不必全部相同。當引數個數超過兩個時,使用逗號『,』來加以間隔。而引數個數同時決定了陣列的大小。舉例如下: 語法:Array(引數串列) 功能:宣告自由資料型態的陣列並且直接將引數串列的值指定為陣列元素的初始值。
10.1:陣列 • 【範例】:使用Array函數宣告rainfall_record陣列,同時設定元素初始值如下: • "新竹"為地名(字串);30為雨量(數值);"3月"為月份(字串)。 • Array函數所宣告陣列仍受Option Base影響陣列的下界,上例中,rainfall(1)= "新竹"。
10.1:陣列 • 【範例10-2】: • 使用Array宣告陣列。
10.1:陣列 • For Each ...Next 陣列迴圈 • 陣列與迴圈息息相關,例如透過一個迴圈可以將一維陣列的每一個元素值讀出或存入新值,也可以利用巢狀迴圈將多維陣列的每一個元素值讀出或存入新值。 • 例如下列範例將九九乘法之結果存入二維陣列A之中: • 也可以透過Visual Basic提供的另一種迴圈敘述For Each…Next來完成與陣列有關的運算。 • For Each…Next迴圈,稱之為『陣列迴圈』,它將會依照透過陣列元素件個數,決定迴圈內的敘述區塊要重覆執行的次數,其語法如下:
10.1:陣列 • 【語法說明】: • 1. 變數:資料型態必須為Variant。 • 2. 陣列的元素個數決定了迴圈內的敘述區塊重覆執行的次數。 • 3. 每次重覆迴圈時,變數值會等於陣列元素值,並且會由陣列第一個元素開始,依序指定給該變數。 • 4. 迴圈執行完畢會繼續執行緊接在Next後的敘述。 語法:For Each變數In陣列名稱 [敘述區段] [Exit For] Next 功能:依照陣列元素的個數,決定重複執行敘述區段的次數。
10.1:陣列 • 【範例10-3】: • 使用For Each…Next迴圈讀出陣列元素值。
10.1:陣列 • 二維陣列與多維陣列 • 陣列若具有兩個索引稱為『二維陣列』、具有三個索引稱為『三維陣列』,依此類推。二維陣列的使用十分廣泛(僅次於一維陣列)。您可以將二維陣列以數學之矩陣來加以看待,也就是二維陣列是由列(Row)與行(Column)組合而成。每一個元素恰恰落在特定之某一列的某一行。 • 『列』就是二維陣列的第一維索引,而『行』則是二維陣列的第二維索引,我們以下圖來解說A(4,3)二維陣列在記憶體中的儲存。
10.1:陣列 • 我們可以用二維陣列來表示複雜的資料,例如使用橫列來表示各分公司的營運狀況,直行表示各季的營業額,並事先宣告Option Base 1,使用『1』做為陣列索引下界。則可以如下圖安排整間公司的總體營運狀況。 • 以上的二維陣列宣告,可以使用列與行來分別代表兩個索引,索引之間則必須以逗號『,』加以分隔,宣告如下: 第四季 第一季 第二季 第三季 台北總公司(第1列) 新竹園區(第2列) 高雄分公司(第3列)
10.1:陣列 • 完整的二維陣列宣告語法如下: • 在上面的營運業績範例,A(3,4)陣列共有(3*4)=12個元素,若要取得高雄分公司第3季的營業額,則應該以相對應的索引值來加以取得,也就是A(3,3)。 • 二維陣列可以使用表格來加以示意,三維陣列則需要使用三度空間圖形加以示意,更多維度的陣列則無法使用幾何圖形來示意,但存取方法也大同小異。 • 盡量使用1~3維陣列來儲存資料,過多的維數將容易造成程式撰寫不易且維護困難的問題。 語法:Dim 陣列名稱 (索引1,索引2) [As資料型態] 功能:宣告二維陣列,以及元素的資料型態。
【範例10-4】:使用二維陣列存放學生的期中考成績【範例10-4】:使用二維陣列存放學生的期中考成績
【實作範例10-5】 • 【實作範例10-5】: • 使用二維陣列儲存得票數與得票率。 • 上機實作 • Step1:專案名稱為『p10_05』。 • Step2:在表單上產生下列控制項並設定屬性。 • Step3:編輯下頁程式碼。 • Step4:執行程式。
10.2:動態陣列與靜態陣列 • Visual Basic的陣列其實分為兩種 • 『動態陣列』(Dynamic Array) • 『靜態陣列』(Static array) • 『動態陣列』與『靜態陣列』的差別在於記憶體的使用狀況 • 『動態陣列』在程式尚未執行到有關該陣列的宣告之前,並不會配置任何記憶體給該陣列,也就是說,當程式執行到宣告陣列時,才會要求系統配置記憶體空間給動態陣列使用。 • 『靜態陣列』是程式在載入到記憶體時,同時也要求配置記憶體空間給靜態陣列使用。 • 因此,動態陣列比較節省記憶體空間的使用率。
10.2:動態陣列與靜態陣列 • 宣告動態陣列有3種方法: • Dim敘述:在程序中使用Dim宣告區域陣列 • 例如:Dim D(100) As Integer。 • ReDim敘述:在程序中使用ReDim宣告區域陣列 • 例如:ReDim D(100) As Integer。 • Dim與ReDim敘述:可以先在表單宣告區使用Dim來宣告表單內的空維數『全域陣列』,然後在程序中再以ReDim來宣告陣列的維數與索引之上下界。如下範例:
10.2:動態陣列與靜態陣列 • 宣告靜態陣列有2種方法: • 在程序中使用Static來宣告區域陣列 • 例如:Static S(30) As Integer。 • 說明: • (1) Static宣告語法及使用規則與在程序中的Dim敘述相同 • (2) 在程序中,使用Static宣告的陣列,當程式主控權離開程序後,陣列仍然佔用原來的記憶體空間,並且其資料並不會消失,因此,當該程序再次被呼叫可以重覆使用之前在陣列中儲存的資料。 • 在表單宣告區使用Dim來宣告維數、上下界固定的全域陣列 • 例如:Dim S(30) As Integer。 • 說明: • 在表單宣告區使用Dim宣告的全域靜態陣列,當表單檔被執行時,將一直佔據記憶空間,所以我們可以在所有的程序中,共用陣列中的元素內容。
10.2:動態陣列與靜態陣列 • 【範例10-6】: • 比較動態陣列與靜態陣列的差別。
10.2:動態陣列與靜態陣列 • 清除陣列-Erase敘述 • 『動態陣列』於程式執行時,可以使用ReDim敘述重新定義陣列的大小,除此之外,也可以利用Erase敘述來清除陣列。所謂清除陣列,其實就是強迫釋放動態陣列的記憶體空間。 • 『靜態陣列』也可以使用Erase敘述,但『靜態陣列』使用Erase敘述並不會釋放所佔用的記憶體空間,只會將陣列元素重新設為初始值。Erase語法如下: • 1. Erase敘述會將靜態陣列設為初始值,數值靜態陣列的元素初始值為0;字串靜態陣列的元素初始值為空字串。 • 2. 使用Array函數建立的陣列,遇到Erase敘述會被釋放 語法:Erase陣列名稱功能: 陣列名稱為動態陣列→釋放記憶體空間。 陣列名稱為靜態陣列→陣列元素被設定為初始值。
10.2:動態陣列與靜態陣列 • 【範例10-7】: • 使用Erase敘述清除靜態陣列與動態陣列
10.3:搜尋與排序 • 搜尋與排序是程式設計的一項基本且重要的問題。 • 『搜尋』(Searching) • 在一堆資料中,尋找您所想要的資料,例如:在英文字典中找尋某一個單字。 • 本章將介紹最簡單的『循序搜尋法』與常見的『二分搜尋法』。 • 『排序』(Sorting) • 將一堆雜亂的資料,依照某個鍵值(Key Value)依序排列,方便日後的查詢或使用。 • 例如:英文字典中每個單字就是已經排序後的結果『從a~z』。 • 本章將介紹『氣泡排序法』。
10.3:搜尋與排序 • 【氣泡排序法】: • 『氣泡排序法』是將相鄰兩個資料一一互相比較,依據比較結果,決定是否互換,由於整個執行過程,有如氣泡逐漸浮上水面,因此命名。 • 假設我們有24,7,36,2,65要做氣泡排序:
10.3:搜尋與排序 • 氣泡排序演算法
10.3:搜尋與排序 • 【實例說明】: • 若陣列的五個元素資料A(1),A(2),A(3),A(4),A(5)要由小到大排序,則以下是詳細步驟: • 第一回合: • 相鄰兩個資料相互比較,依照下列步驟,最大值將被放入A(5)中: • (1) A(1)和A(2)比較,若A(1)>A(2)則資料互換,否則資料不交換。 • (2) A(2)和A(3)比較,若A(2)>A(3)則資料互換,否則資料不交換。 • (3) A(3)和A(4)比較,若A(3)>A(4)則資料互換,否則資料不交換。 • (4) A(4)和A(5)比較,若A(4)>A(5)則資料互換,否則資料不交換。 • 很容易可以發現,經過上面四次比較之後,最大的資料一定會被放到A(5)之中,如此稱為『第一回合掃描』。
10.3:搜尋與排序 • 第二回合: • 由於在第一回合時,A(1)~A(5)的最大值已經被放到A(5)了,因此在第二回合掃描時,只需要仿照第一回合,將A(1)~A(4)中最大的值放到A(4)中即可(明顯地,第二回合掃描只需要比較3次)。 • 第三回合: • 由於在第一、二回合時,A(1)~A(5)的最大值及第二大值已經被放到A(5)、A(4)了,因此在第三回合掃描時,只需要仿照第一回合,將A(1)~A(3)中最大的值放到A(3)中即可(明顯地,第三回合掃描只需要比較2次)。 • 第四回合: • 由於在第一、二、三回合時,A(1)~A(5)的最大值、第二大值、第三大值已經被放到A(5)、A(4)、A(3)了,因此在第四回合掃描時,只需要仿照第一回合,將A(1)~A(2)中最大的值放到A(2)中即可(明顯地,第四回合掃描只需要比較1次)。 • 第五回合: • 最後剩下A(1),不必比較就知道A(1)中的值是最小的值。(第五回合可省略) • 五筆資料使用氣泡排序,需經過四個回合的掃描,共比較(4+3+2+1)=10次。 • N筆資料做氣泡排序,需要(N-1)次掃描,共比較(N-1)+(N-2)+(N-3)+…+3+2+1 = N(N-1)/2次。 • 在排序過程中,若有某一回合的掃描沒有交換任何的資料,則代表資料已經提早排序完成,此時可掠過後面尚未掃描的回合。因此N(N-1)/2次比較是最差的狀況。
10.3:搜尋與排序 • 【範例10-8】: • 使用氣泡排序法,依小到大排序24,7,36,2,65等5個資料。
10.3:搜尋與排序 • 『循序搜尋』 • 一種簡單的搜尋方法,也就是從第一筆資料開始尋找,然後是第二筆資料、、、一直到找到所要的資料或全部資料被找完為止。 • 假設有N筆資料,則最差需要作N次比較,而平均則需要N/2次比較。 • 通常在資料量比較少或資料未經排序的狀況下使用『循序搜尋法』。 • 『二分搜尋法』 • 效率高 • 將資料一半一半的切割開來,直到找到資料為止 • 關於『二分搜尋法』將在本章最後一節中加以說明。 • 【範例10-9】: • 使用循序搜尋法在未排序的資料中,尋找所需要的資料『57』。
10.4:控制項陣列 • 『控制項陣列』可以用來代表類似的控制項集合,並且透過索引值來區別同樣物件名稱中的各個控制項。『控制項陣列』語法如下: • 控制項陣列中的每一個控制項元素,由於名稱相同,因此觸發的事件程序將會共用,只不過在觸發的同時,會傳進一個Index參數以示區別。 • 產生控制項陣列: • 【方法一】:複製控制項 • 【方法二】:將兩個不同名稱的同性質控制項的名稱修正為相同名稱 語法:物件(索引值).Index 功能:取得或設定物件(控制項)陣列中某一個物件元素。
10.4:控制項陣列 • 控制項陣列程式設計 • 【實作範例10-10】: • 修正範例10-5,使用控制項陣列來取代同性質的控制項,以便於使用迴圈設定控制項的屬性值。 • 上機實作 • Step1:專案名稱為『p10_10』。 • Step2:在表單上產生下列控制項並設定屬性。 • Step3:編輯下頁程式碼。 • Step4:執行程式。 控制項陣列
10.5:清單方塊(ListBox)控制項 • 『清單方塊』控制項可以用來製作一連串的選項,使用者可以在清單中選擇所需要的選項。 • 『清單方塊』控制項允許設定單選與複選。 • 建立『清單方塊』 2:在表單上拉出清單方塊控制項大小 1:選取清單方塊工具
10.5:清單方塊(ListBox)控制項 • 『清單方塊』的常用屬性
10.5:清單方塊(ListBox)控制項 • 『清單方塊』控制項的常用方法(加入與移除項目) • Addltem:加入一個項目到清單方塊中,語法如下: • 【語法說明】:執行AddItem方法後,ListIndex屬性會變成『-1』。 • Removeltem:從清單方塊中移除某一個項目,語法如下 • 使用『清單方塊』設計介面,可以透過ListIndex屬性,取得目前被使用者選定的項目索引值,也可以藉由AddItem方法來增加新的項目。 【語法】:[物件名稱].AddItem項目名稱[,索引值] 【語法】:[物件名稱].RemoveItem 索引值
【實作範例10-11】 • 清單方塊的程式設計 • 【實作範例10-11】: • 使用清單方塊,設計一個售票系統。 • 上機實作 • Step1:專案名稱為『p10_11』。 • Step2:在表單上產生下列控制項並設定屬性。 • Step3:編輯程式碼。
【實作範例10-11】 • 【設定項目】:您如果要在編輯介面階段,設定清單的項目(List屬性),則可以依照下列步驟: 1:按下拉鈕 3:重複步驟1~2輸入下一個項目(每次重覆就可以輸入新的項目) 2:輸入第一個項目
【實作範例10-11】 • Step4:執行程式。
10.6:下拉式清單方塊(ComboBox)控制項 • 『下拉式清單方塊』控制項與清單方塊非常類似,但在某些狀況下,必須先按下『下拉鈕』,然後才能夠選取清單項目 • 『下拉式清單方塊』控制項還提供了輸入文字的功能。 • 建立『下拉式清單方塊』 2:在表單上拉出下拉式清單方塊控制項大小 1:選取下拉式清單方塊工具
10.6:下拉式清單方塊(ComboBox)控制項 • 『下拉式清單方塊』的3種型式(style屬性) • 『下拉式清單方塊』與『清單方塊』的常用屬性大多相同,但『下拉式清單方塊』另外還多了一個style屬性。 • style屬性是用來設定下拉式清單方塊的型式,型式一共有3種: • 『組合下拉式』清單方塊(style=0)程式執行時,「清單方塊」會被隱藏,必須按下拉鈕才會顯示方塊內容。使用者可以在「文字方塊」中直接輸入選項名稱,也可以由拉出「清單方塊」選取項目。 • 【選取項目】: • 【直接輸入項目名稱】: