第十章 陣列.

Slides:



Advertisements
Similar presentations
第一單元 建立java 程式.
Advertisements

計算機概論 第4章 基本視窗程式應用 4-1 程式語言簡介 4-2 演算法與流程圖 4-3 視窗程式語言設計 4-4 資料結構.
陣列與清單控制項 [學生成績管理][井字遊戲]
課程名稱:程式設計 授課老師:________
陣列 Array chapter 3 德明科技大學資訊科技系.
C 程式設計— 陣列 台大資訊工程學系 資訊系統訓練班.
网 络 课 程 马 鞍 学 网 络 山 课 程 大 络 网 Visual Basic程序设计 第 一 讲 最容易接受的编程语言
高等医药院校药学类第三轮规划教材——大学计算机基础
第四章 數列與級數 4-1 等差數列與級數 4-2 等比數列與級數 4-3 無窮等比級數 下一頁 總目錄.
陳維魁 博士 儒林圖書公司 第九章 資料抽象化 陳維魁 博士 儒林圖書公司.
TQC+ JAVA全國教師研習會 PLWeb 程式設計練習平台 簡介.
第五章 数组.
Chapter 5 迴圈.
Visual Basic程序设计.
程式設計概論 1.1 程式設計概論 程式語言的演進 物件導向程式 程式開發流程 1.2 C++開發工具
第十一章 結構.
Visual Basic 2010 程式設計16堂特訓 第七堂 VB的迴圈流程控制.
第6章 数 组 6.1 一维数组 6.2 控件数组 6.3 二维数组.
第二章 Visual Basic语言基础.
資料結構設計與C++程式應用 Fundamentals of Data Structures and Their Applications Using C++ 第3章 佇列 資料結構設計與C++程式應用.
講師:戴志華 國立台灣大學電機工程研究所 Visual Basic 程式設計 講師:戴志華 國立台灣大學電機工程研究所.
第10章 陣列與清單控制項.
数组 第 6 章.
第5章 数组 Visual Basic程序设计.
Visual Basic程序设计 第七章 数组
1、数组的概念 2、静态数组 3、动态数组 4、数组的基本操作 5、控件数组
保留字與識別字.
類別(class) 類別class與物件object.
SQL Stored Procedure SQL 預存程序.
第4章 程序控制结构与算法基础.
第十二章 多模組與多專案.
PR150 (125K) Reader RS232.
Java 程式設計 講師:FrankLin.
Visual Basic程序设计.
JAVA 程式設計與資料結構 第四章 陣列、字串與數學物件.
Chap3 Linked List 鏈結串列.
VB程序设计语言 主讲教师:王 杨.
VB程序设计语言 主讲教师:王 杨.
程式設計 Visual Basic簡介 週次:2 建國技術學院 資管系 饒瑞佶 2003年9月17日.
表單(Form).
第一單元 建立java 程式.
網頁程式設計 本章投影片錄自HTML5、CSS3、RWD、jQuery Mobile跨裝網頁設計 陳惠貞 著 碁峰資訊股份有限公司出版
PLC-GPPW軟體使用教學 授課教師:張祖烈
陣列(Array).
資料結構 優點 缺點 1 陣列 (Array) 沒有額外變量 (例head, next,...) 運作/操作較簡單 更新資料時,若要保持順序,需要移動較大量資料 靜態結構Static (宣告時已決定了陣列元素多少,不能在程式執行期間增減元素) 2 隊列Queue (FIFO) 容易更新 加入enqueue:
第 19 章 XML記憶體執行模式.
陣列
小结 郭清溥.
打地鼠(陣列版).
第一次Labview就上手 參考書籍: LabVIEW for Everyone (Jeffrey Travis/Jim Kring)
第二章、第三章错题分析.
CH05. 選擇敘述.
挑戰C++程式語言 ──第8章 進一步談字元與字串
GridView.
C qsort.
流程控制:Switch-Case 94學年度第一學期‧資訊教育 東海大學物理系.
MiRanda Java Interface v1.0的使用方法
函數應用(二)與自定函數.
陣列與結構.
第5章 数组 5.1 数组概述 5.2 静态数组和动态数组 5.3 数组的基本操作 5.4 控件数组 5.5 数组在自定义数据类型中的应用.
反覆迴圈、陣列、副程式 靜宜大學資管系 楊子青
反覆迴圈、陣列、副程式 靜宜大學資管系 楊子青
資料表示方法 資料儲存單位.
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
String類別 在C語言中提供兩種支援字串的方式 可以使用傳統以null結尾的字元陣列 使用string類別
Array(陣列) Anny
SQLite資料庫 靜宜大學資管系 楊子青.
C語言程式設計 老師:謝孟諺 助教:楊斯竣.
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
InputStreamReader Console Scanner
Presentation transcript:

第十章 陣列

章節預覽 理論與Visual Basic相關基本知識 控制項 10.1 陣列 10.2 動態陣列與靜態陣列 10.3 搜尋與排序 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)*12 Trade(0)=Trade(1) +X Trade(0)=Trade(1) +TEST(2)

【範例10-1】:使用陣列存放資料。 4 5 6 7 8~10 11~13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29~30 31~32 33~34 35~36 37 Dim WeekDay(7) As String Private Sub Form_Activate() Dim Temper(7) As Single Temper(1) = 28 : Temper(2) = 26.5 : Temper(3) = 22 Temper(4) = 24 : Temper(5) = 23.8 : Temper(6) = 26 Temper(7) = 29 Cls FontSize = 12 Print " 溫度統計" Print "========================" For i = 1 To 7 Print WeekDay(i), Temper(i) Temper(0) = Temper(0) + Temper(i) Next i Temper(0) = Temper(0) / 7 Print WeekDay(0), Temper(0) End Sub Private Sub Form_Load() WeekDay(0) = "本周平均" : WeekDay(1) = "星期一" WeekDay(2) = "星期二" : WeekDay(3) = "星期三" WeekDay(4) = "星期四" : WeekDay(5) = "星期五" WeekDay(6) = "星期六" : WeekDay(7) = "星期日"

10.1:陣列 陣列索引的下界與上界 Option Base 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)。 Option Base 0 '可省略本行 Dim A(3) Option Base 1 Dim 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:陣列 取得陣列索引的上、下界值 語法:L=LBound(陣列名稱[,維數]) 功能:取得指定陣列某一維的索引下界值。 【範例】:假設二維陣列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)= "新竹"。 Option Base 1 rainfall_record =Array("新竹",30,"3月")

10.1:陣列 【範例10-2】: 使用Array宣告陣列。 4 5 6 7 8 9 10 11 12 13 14 15 Option Base 1 Private Sub Form_Activate() Temper = Array(28, 26.5, 22, 24, 23.8, 26) Cls FontSize = 12 Print " 溫度統計" Print "========================" For i = 1 To 6 Print "星期" & i, Temper(i) Next i End Sub

10.1:陣列 For Each ...Next 陣列迴圈 陣列與迴圈息息相關,例如透過一個迴圈可以將一維陣列的每一個元素值讀出或存入新值,也可以利用巢狀迴圈將多維陣列的每一個元素值讀出或存入新值。 例如下列範例將九九乘法之結果存入二維陣列A之中: 也可以透過Visual Basic提供的另一種迴圈敘述For Each…Next來完成與陣列有關的運算。 For Each…Next迴圈,稱之為『陣列迴圈』,它將會依照透過陣列元素件個數,決定迴圈內的敘述區塊要重覆執行的次數,其語法如下: Dim A(1 To 9, 1 To 9) As Integer For I = LBound(A, 1) To UBound(A, 1) For J=LBound(A, 2) To UBound(A, 2) A(I,J)=I*J Next J Next I

10.1:陣列 【語法說明】: 1. 變數:資料型態必須為Variant。 2. 陣列的元素個數決定了迴圈內的敘述區塊重覆執行的次數。 語法:For Each變數In陣列名稱 [敘述區段] [Exit For]    Next 功能:依照陣列元素的個數,決定重複執行敘述區段的次數。 【語法說明】: 1. 變數:資料型態必須為Variant。 2. 陣列的元素個數決定了迴圈內的敘述區塊重覆執行的次數。 3. 每次重覆迴圈時,變數值會等於陣列元素值,並且會由陣列第一個元素開始,依序指定給該變數。 4. 迴圈執行完畢會繼續執行緊接在Next後的敘述。

10.1:陣列 【範例10-3】: 使用For Each…Next迴圈讀出陣列元素值。 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Private Sub Form_Activate() Dim A(1 To 9, 1 To 9) As Integer Dim result As Variant For I = LBound(A, 1) To UBound(A, 1) For J = LBound(A, 2) To UBound(A, 2) A(I, J) = I * J Next J Next I FontSize = 12 Sum = 0 For Each result In A Sum = Sum + 1 Print Format(result, "00 "); If Sum Mod 9 = 0 Then Print Next End Sub

10.1:陣列 二維陣列與多維陣列 陣列若具有兩個索引稱為『二維陣列』、具有三個索引稱為『三維陣列』,依此類推。二維陣列的使用十分廣泛(僅次於一維陣列)。您可以將二維陣列以數學之矩陣來加以看待,也就是二維陣列是由列(Row)與行(Column)組合而成。每一個元素恰恰落在特定之某一列的某一行。 『列』就是二維陣列的第一維索引,而『行』則是二維陣列的第二維索引,我們以下圖來解說A(4,3)二維陣列在記憶體中的儲存。

10.1:陣列 第一季 第二季 第三季 第四季 A(1,1) A(1,2) A(1,3) A(1,4) A(2,1) A(2,2) 我們可以用二維陣列來表示複雜的資料,例如使用橫列來表示各分公司的營運狀況,直行表示各季的營業額,並事先宣告Option Base 1,使用『1』做為陣列索引下界。則可以如下圖安排整間公司的總體營運狀況。 以上的二維陣列宣告,可以使用列與行來分別代表兩個索引,索引之間則必須以逗號『,』加以分隔,宣告如下: 第一季 第二季 第三季 第四季 A(1,1) A(1,2) A(1,3) A(1,4) A(2,1) A(2,2) A(2,3) A(2,4) A(3,1) A(3,2) A(3,3) A(3,4) 台北總公司(第1列) 新竹園區(第2列) 高雄分公司(第3列) Option Base 1 Dim A(3,4) As Integer

10.1:陣列 完整的二維陣列宣告語法如下: 在上面的營運業績範例,A(3,4)陣列共有(3*4)=12個元素,若要取得高雄分公司第3季的營業額,則應該以相對應的索引值來加以取得,也就是A(3,3)。 二維陣列可以使用表格來加以示意,三維陣列則需要使用三度空間圖形加以示意,更多維度的陣列則無法使用幾何圖形來示意,但存取方法也大同小異。 盡量使用1~3維陣列來儲存資料,過多的維數將容易造成程式撰寫不易且維護困難的問題。 語法:Dim 陣列名稱 (索引1,索引2) [As資料型態] 功能:宣告二維陣列,以及元素的資料型態。

【範例10-4】:使用二維陣列存放學生的期中考成績 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Option Base 1 Private Sub Form_Activate() Dim Score(5, 4) As Single Score(1, 1) = 85: Score(1, 2) = 78: Score(1, 3) = 65 Score(2, 1) = 75: Score(2, 2) = 85: Score(2, 3) = 69 Score(3, 1) = 63: Score(3, 2) = 67: Score(3, 3) = 95 Score(4, 1) = 94: Score(4, 2) = 92: Score(4, 3) = 88 Score(5, 1) = 74: Score(5, 2) = 65: Score(5, 3) = 73 FontSize = 10 LoopCount = 0 Print "成績", "計概", "數學", "英文", "平均" Print "===============================================================" Student_Name = Array("鐵雄", "大明", "珍珍", "阿丁", "阿龍") For I = 1 To 5 Print Student_Name(I) & " "; Score(I, 4) = (Score(I, 1) + Score(I, 2) + Score(I, 3)) / 3 For J = 1 To 4 Print Format(Score(I, J), " 00.00 "); Next J Print Next I End Sub

【實作範例10-5】 【實作範例10-5】: 上機實作 使用二維陣列儲存得票數與得票率。 Step1:專案名稱為『p10_05』。

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Option Base 1 Dim PVote(3, 2) As Single Private Sub txtP1_Change() PVote(1, 1) = Val(txtP1.Text) For I = 1 To 3 PVote(I, 2) = 100 * PVote(I, 1) / (PVote(1, 1) + PVote(2, 1) + PVote(3, 1)) Next I lblP1Rate = PVote(1, 2): lblP2Rate = PVote(2, 2): lblP3Rate = PVote(3, 2) End Sub Private Sub txtP2_Change() PVote(2, 1) = Val(txtP2.Text) Private Sub txtP3_Change() PVote(3, 1) = Val(txtP3.Text)

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來宣告陣列的維數與索引之上下界。如下範例: 範例: Dim D() As Integer Private Sub Form_Activate() ReDim D(1 To 10,2 To 50) As Integer End Sub

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】: 比較動態陣列與靜態陣列的差別。 4 5 6 7 8 9 10 11 12 13 Private Sub Form_Click() Dim D(1 To 3) As Integer Static S(1 To 3) As Integer FontSize = 12 For i = 1 To 3 D(i) = D(i) + i S(i) = S(i) + i Print "D(" & i; ")=" & D(i) & " S(" & i & ")=" & S(i) Next i End Sub

10.2:動態陣列與靜態陣列 清除陣列-Erase敘述 『動態陣列』於程式執行時,可以使用ReDim敘述重新定義陣列的大小,除此之外,也可以利用Erase敘述來清除陣列。所謂清除陣列,其實就是強迫釋放動態陣列的記憶體空間。 『靜態陣列』也可以使用Erase敘述,但『靜態陣列』使用Erase敘述並不會釋放所佔用的記憶體空間,只會將陣列元素重新設為初始值。Erase語法如下: 1. Erase敘述會將靜態陣列設為初始值,數值靜態陣列的元素初始值為0;字串靜態陣列的元素初始值為空字串。 2. 使用Array函數建立的陣列,遇到Erase敘述會被釋放 語法:Erase陣列名稱 功能: 陣列名稱為動態陣列→釋放記憶體空間。 陣列名稱為靜態陣列→陣列元素被設定為初始值。

10.2:動態陣列與靜態陣列 【範例10-7】: 使用Erase敘述清除靜態陣列與動態陣列 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Private Sub Form_Activate() Static S(10) As Integer Dim D(10) As Integer S(10) = 100 D(10) = 100 FontSize = 12 Print "使用Erase前" Print "S(10)=" & S(10) & " D(10)="; D(10) Erase S, D Print "使用Erase後" Print "S(10)=" & S(10) 'Print "D(10)="; D(10) End Sub

10.3:搜尋與排序 搜尋與排序是程式設計的一項基本且重要的問題。 『搜尋』(Searching) 『排序』(Sorting) 在一堆資料中,尋找您所想要的資料,例如:在英文字典中找尋某一個單字。 本章將介紹最簡單的『循序搜尋法』與常見的『二分搜尋法』。 『排序』(Sorting) 將一堆雜亂的資料,依照某個鍵值(Key Value)依序排列,方便日後的查詢或使用。 例如:英文字典中每個單字就是已經排序後的結果『從a~z』。 本章將介紹『氣泡排序法』。

10.3:搜尋與排序 【氣泡排序法】: 『氣泡排序法』是將相鄰兩個資料一一互相比較,依據比較結果,決定是否互換,由於整個執行過程,有如氣泡逐漸浮上水面,因此命名。 假設我們有24,7,36,2,65要做氣泡排序:

10.3:搜尋與排序 氣泡排序演算法 輸入:未排序的資料X(1)~X(n) 輸出:已排序的資料 k←n Do While k<>0 t←0 For i=1 To k-1 If X(i)>X(i+1) Then X(i)←→ X(i+1) 'X(i)與X(i+1)互換 t←i End If Next i k←t Loop

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:搜尋與排序 五筆資料使用氣泡排序,需經過四個回合的掃描,共比較(4+3+2+1)=10次。 第二回合: 由於在第一回合時,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:搜尋與排序 『循序搜尋』 『二分搜尋法』 【範例10-9】: 一種簡單的搜尋方法,也就是從第一筆資料開始尋找,然後是第二筆資料、、、一直到找到所要的資料或全部資料被找完為止。 假設有N筆資料,則最差需要作N次比較,而平均則需要N/2次比較。 通常在資料量比較少或資料未經排序的狀況下使用『循序搜尋法』。 『二分搜尋法』 效率高 將資料一半一半的切割開來,直到找到資料為止 關於『二分搜尋法』將在本章最後一節中加以說明。 【範例10-9】: 使用循序搜尋法在未排序的資料中,尋找所需要的資料『57』。

【範例10-9】 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Option Base 1 Private Sub Form_Activate() Dim Target As Integer find_flag = False Target = 57 Data = Array(74, 41, 54, 86, 63, 57, 33, 79) FontSize = 12 For i = 1 To UBound(Data) Print "資料" & i & " " & Data(i); If Target = Data(i) Then Print " 找到了" find_flag = True Exit For Else Print " 不是要找的資料" End If Next i If Not (find_flag) Then Print "很抱歉,您要找的資料不在陣列中!" End Sub

10.4:控制項陣列 『控制項陣列』可以用來代表類似的控制項集合,並且透過索引值來區別同樣物件名稱中的各個控制項。『控制項陣列』語法如下: 控制項陣列中的每一個控制項元素,由於名稱相同,因此觸發的事件程序將會共用,只不過在觸發的同時,會傳進一個Index參數以示區別。 產生控制項陣列: 【方法一】:複製控制項 【方法二】:將兩個不同名稱的同性質控制項的名稱修正為相同名稱 語法:物件(索引值).Index 功能:取得或設定物件(控制項)陣列中某一個物件元素。

10.4:控制項陣列 控制項陣列程式設計 控制項陣列 【實作範例10-10】: 修正範例10-5,使用控制項陣列來取代同性質的控制項,以便於使用迴圈設定控制項的屬性值。 上機實作 Step1:專案名稱為『p10_10』。 Step2:在表單上產生下列控制項並設定屬性。 Step3:編輯下頁程式碼。 Step4:執行程式。 控制項陣列

【實作範例10-10】 5 6 7 8 9 10 11 12 13 14 15 Private Sub txtP_Change(Index As Integer) Dim Total, Rate As Single Total = 0 For I = 0 To 2 Total = Total + Val(txtP(I).Text) Next I Rate = 100 * Val(txtP(I).Text) / Total lblPRate(I).Caption = Str(Rate) End Sub

10.5:清單方塊(ListBox)控制項 『清單方塊』控制項可以用來製作一連串的選項,使用者可以在清單中選擇所需要的選項。 『清單方塊』控制項允許設定單選與複選。 建立『清單方塊』 2:在表單上拉出清單 方塊控制項大小 1:選取清單 方塊工具

10.5:清單方塊(ListBox)控制項 『清單方塊』的常用屬性 屬性 屬性值說明 Columns(欄位個數) 設定清單方塊有幾個水平欄位。 List(Index) (選項內容) 設定清單方塊某一選項的內容。Index:索引值 ListCount(項目總數) 設定清單方塊項目總數。 ListIndex(索引值) 設定清單方塊選定項目的索引值。 Text(預選內容) 設定預選的清單項目內容。 Sorted (排序) 設定清單方塊內的項目是否排序(以字母順序)。 MultiSelect(複選) 設定清單方塊內的選項是否允許複選。

10.5:清單方塊(ListBox)控制項 『清單方塊』控制項的常用方法(加入與移除項目) Addltem:加入一個項目到清單方塊中,語法如下: 【語法說明】:執行AddItem方法後,ListIndex屬性會變成『-1』。 Removeltem:從清單方塊中移除某一個項目,語法如下 使用『清單方塊』設計介面,可以透過ListIndex屬性,取得目前被使用者選定的項目索引值,也可以藉由AddItem方法來增加新的項目。 【語法】:[物件名稱].AddItem項目名稱[,索引值] 【語法】:[物件名稱].RemoveItem 索引值

【實作範例10-11】 清單方塊的程式設計 【實作範例10-11】: 使用清單方塊,設計一個售票系統。 上機實作 Step1:專案名稱為『p10_11』。 Step2:在表單上產生下列控制項並設定屬性。 Step3:編輯程式碼。

3:重複步驟1~2輸入下一個項目 (每次重覆就可以輸入新的項目) 【實作範例10-11】 【設定項目】:您如果要在編輯介面階段,設定清單的項目(List屬性),則可以依照下列步驟: 1:按下拉鈕 3:重複步驟1~2輸入下一個項目 (每次重覆就可以輸入新的項目) 2:輸入第一個項目

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Dim Item(10) As String Dim Price(10) As Integer Dim TotalPrice As Long Private Sub cmdOrder_Click() TotalPrice = TotalPrice + Val(txtSubTotal.Text) txtTotal = Str(TotalPrice) txtQty = "0" txtSubTotal = "0" End Sub Private Sub Form_Load() For I = 0 To 5 Item(I) = lstTicket.List(I) Price(I) = 200 Next I Item(6) = "全部兄弟場次": Price(6) = 200 * 3 * 0.95 Item(7) = "全部興農場次": Price(7) = 200 * 3 * 0.8 Item(8) = "全部統一場次": Price(8) = 200 * 3 * 0.85 Item(9) = "全部中信場次": Price(9) = 200 * 3 * 0.8 Item(10) = "全部場次":: Price(10) = 200 * 6 * 0.7 For I = 6 To 10 lstTicket.AddItem Item(I)

【實作範例10-11】 30 31 32 33 34 35 36 37 38 39 40 41 Private Sub lstTicket_Click() SelectItem = lstTicket.ListIndex txtTicket = Item(SelectItem) txtPrice = Str(Price(SelectItem)) txtQty = "0" txtSubTotal = "0" txtTotal = Str(TotalPrice) End Sub Private Sub txtQty_Change() txtSubTotal = Str(Val(txtPrice) * Val(txtQty)) Step4:執行程式。

10.6:下拉式清單方塊(ComboBox)控制項 『下拉式清單方塊』控制項與清單方塊非常類似,但在某些狀況下,必須先按下『下拉鈕』,然後才能夠選取清單項目 『下拉式清單方塊』控制項還提供了輸入文字的功能。 建立『下拉式清單方塊』 2:在表單上拉出下拉式 清單方塊控制項大小 1:選取下拉式 清單方塊工具

10.6:下拉式清單方塊(ComboBox)控制項 『下拉式清單方塊』的3種型式(style屬性) 『下拉式清單方塊』與『清單方塊』的常用屬性大多相同,但『下拉式清單方塊』另外還多了一個style屬性。 style屬性是用來設定下拉式清單方塊的型式,型式一共有3種: 『組合下拉式』清單方塊(style=0) 程式執行時,「清單方塊」會被隱藏,必須按下拉鈕才會顯示方塊內容。使用者可以在「文字方塊」中直接輸入選項名稱,也可以由拉出「清單方塊」選取項目。 【選取項目】: 【直接輸入項目名稱】:

10.6:下拉式清單方塊(ComboBox)控制項 『組合式』清單方塊(style=1) 清單方塊出現在下方(設計介面時請拉大ComboBox高度),使用者可以在「文字方塊」中直接輸入選項名稱,也可以由拉出「清單方塊」選取項目。 【選取項目】: 【直接輸入項目名稱】: 『單純下拉式』清單方塊(style=2) 程式執行時,「清單方塊」會被隱藏,必須按下拉鈕才會顯示方塊內容。使用者無法在「文字方塊」中直接輸入選項名稱,但可以由拉出「清單方塊」選取項目。 【無法直接輸入項目名稱】:

【實作範例10-12】 下拉式清單方塊的程式設計 【實作範例10-12】: 由於『組合下拉式』清單方塊允許直接在「文字方塊」中輸入項目,因此我們設計一個統計剩餘票系統,當輸入新的項目時,要求使用者輸入該新項目的總票數。 上機實作 Step1:專案名稱為『p10_12』。 Step2:在表單上產生 控制項並設定屬性。 Step3:編輯下頁 程式碼。 Step4:執行程式。

【實作範例10-12】 4 5 6 7 8 9 10 11 12 64 65 66 67 68 69 70 71 72 73 74 75 76 Dim Item(10) As String Dim Price(10) As Integer Dim Stock(10) As Integer Private Sub cboTicket_Click() SelectItem = cboTicket.ListIndex txtPrice = Price(SelectItem) txtStock = Stock(SelectItem) End Sub Private Sub Form_Activate() For i = 0 To 4 Item(i) = cboTicket.List(i) Price(i) = 200 Next i Stock(0) = 2223 Stock(1) = 4323 Stock(2) = 3123 Stock(3) = 1769 Stock(4) = 1374 cmdAddNew.Visible = False cmdCancel.Visible = False

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 Private Sub cboTicket_KeyDown(KeyCode As Integer, Shift As Integer) If KeyCode = 13 Then '13是Enter鍵 i = 0 Do While i < cboTicket.ListCount If cboTicket.Text = Item(i) Then txtPrice = Price(i) txtStock = Stock(i) Exit Sub End If i = i + 1 Loop If i = cboTicket.ListCount Then AddNew = MsgBox("您要新增項目" + cboTicket.Text + "嗎?", 33) If AddNew = 1 Then cboTicket.Locked = True cmdAddNew.Visible = True cmdCancel.Visible = True txtPrice.SetFocus txtPrice = "" txtStock = "" Else cboTicket.Text = "" End Sub

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 78 79 80 81 82 Private Sub cmdAddNew_Click() cboTicket.Locked = False cboTicket.AddItem cboTicket.Text Item(cboTicket.ListCount - 1) = cboTicket.List(cboTicket.ListCount - 1) Price(cboTicket.ListCount - 1) = Val(txtPrice) Stock(cboTicket.ListCount - 1) = Val(txtStock) cboTicket.SetFocus cmdAddNew.Visible = False cmdCancel.Visible = False End Sub Private Sub cmdCancel_Click() cboTicket.Text = "" txtPrice = "" txtStock = "" Private Sub txtPrice_KeyDown(KeyCode As Integer, Shift As Integer) If KeyCode = 13 Then txtStock.SetFocus End If

10.7:功能表(Menu) 功能表 一個簡單的功能表如右圖: 之前所設計的程式都是單一畫面或單一功能的程式,如果想要設計更複雜更完整的程式,則需要設計『功能表』。 一個簡單的功能表如右圖: 【名詞】: 1. 標題:功能表列或(次)功能表 選項的文字。 2. 有效指令/失效指令: 有效指令用實體字顯示, 失效指令用虛體字顯示。 3. 快速鍵:可直接按組合鍵執行選項。 4. 核取記號:該選項的開/關狀態。選取此選項時,核取記號由出現變為消失或由消失變為出現。 5. 箭頭符號:該選項之下尚有次功能表。

【實作範例10-13】 【實作範例10-13】: 實作上圖的功能表。詳細規格如下: Step1:專案名稱為『p10_13』。 Step2:建立表單名稱為『f10_13』,屬性Caption為『f10_13』,屬性Appearance設為『0-平面』。

【實作範例10-13】 Step3:先選取表單,然後執行【工具/功能表編輯器】指令。將出現如下的功能表編輯器對話方塊。

【實作範例10-13】 Step4:設定【格式】功能表與【關於】功能表;請按下列步驟設定。 1:輸入。 3:輸入 5:輸入。 7:輸入 4:按下。 2:出現了格式。 6:出現了關於。

【實作範例10-13】 Step5:設定【轉換為大寫】指令;請按下列步驟設定。 4:輸入。(&U)將來會變成(U) 6:輸入 7:選取(設定快捷鍵) 5:出現轉換 為大寫(&U) 3:關於被移往下一個 1:選取關於 2:按下 8:按下 9:被移往下一層

【實作範例10-13】 Step6:設定【轉換為小寫】指令;請按下列步驟設定。 2:取消啟用。(這樣就變成失效指令)

1:於欄位中輸入『-』 ,將來就會變成分隔線。 【實作範例10-13】 Step7:設定『分隔線』;如下畫面(把分隔線當作指令來設定)。 1:於欄位中輸入『-』 ,將來就會變成分隔線。

【實作範例10-13】 Step8:參照前面步驟設定『字型』、『第二條分隔線』、『結束』,結果如圖。 設定

【實作範例10-13】 Step9:在『第二條分隔線』前插入【底線】指令,並如下設定。 1:輸入 2:輸入 3:勾選(將來指令前就會出現核選記號)

【實作範例10-13】 Step10:設定【粗體】指令;請按下列步驟設定。 4:輸入 6:輸入 5:出現了粗體 2:按下 1:選取底線 3:底線被移往下一個 7:按下 8:被移往下一層

【實作範例10-13】 Step11:仿照Step10,設定【斜體】指令,結果如圖,最後按下【確定】鈕即可完成功能表的製作。 2:按下 1:設定

【實作範例10-14】 『功能表』 程式設計 【實作範例10-14】: 設計一個透過功能表內所提中的指令進行字型設定的程式。 上機實作 Step1:專案名稱為『p10_14』。 Step2:在表單上產生 控制項並設定屬性。並設定 功能表內的指令選項。 Step3:編輯下頁 程式碼。

【實作範例10-14】 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Private Sub Form_Load() If mnuUnderline.Checked Then lblResult.FontUnderline = True Else lblResult.FontUnderline = False End If End Sub Private Sub mnuAbout_Click() Cls Print " 版權所有!!" Private Sub mnuBold_Click() lblResult.FontBold = True Private Sub mnuEnd_Click() End Private Sub mnuItalic_Click() lblResult.FontItalic = True

【實作範例10-14】 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 Private Sub mnuLowerCase_Click() lblResult.Caption = LCase(txtSource.Text) mnuLowerCase.Enabled = Fasle mnuUpperCase.Enabled = True End Sub Private Sub mnuUnderline_Click() If mnuUnderline.Checked Then mnuUnderline.Checked = False lblResult.FontUnderline = False Else mnuUnderline.Checked = True lblResult.FontUnderline = True End If Private Sub mnuUpperCase_Click() lblResult.Caption = UCase(txtSource.Text) mnuUpperCase.Enabled = Fasle mnuLowerCase.Enabled = True

執行【格式/轉換為大寫】、 【格式/底線】、 【格式/字型/粗體】、 【格式/字型/斜體】指令後。 【實作範例10-14】 Step4:執行程式。 執行【格式/轉換為大寫】、 【格式/底線】、 【格式/字型/粗體】、 【格式/字型/斜體】指令後。

10.8:本章整合應用實例 【實作範例10-15】: 上機實作 使用陣列、控制項陣列及清單方塊重新設計範例9-14。 Step1:專案名稱為『p10_15』。 Step2:在表單上產生 控制項並設定屬性。 Step3:編輯程式碼。 Step4:執行程式。

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 Dim PVote(0 To 5) As Integer Dim PName(0 To 5) As String Private Sub cmdSta_Click() picSta.Cls PI = 3.1415926 For I = 0 To 5 If I <= 2 Then ManVotes = ManVotes + PVote(I) Else WomanVotes = WomanVotes + PVote(I) End If Next I If (ManVotes + WomanVotes) > 0 Then ManRate = Int(ManVotes / (ManVotes + WomanVotes) * 100) WomRate = 100 - ManRate lblSexRate(0).Caption = Str(ManRate) & "%" lblSexRate(1).Caption = Str(WomRate) & "%" If ManRate > 0 Then picSta.FillStyle = 5 picSta.FillColor = QBColor(1) picSta.Circle(800, 800),800,QBColor(1),-0.01,-2*PI*ManRate/100 If WomRate > 0 Then picSta.FillStyle = 0 picSta.FillColor = QBColor(0) picSta.Circle(800, 800),800,QBColor(0),-2*PI*ManRate/100,-2*PI MsgBox "請先投票!!" End Sub

39 40 41 42 43 44 45 46 47~48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70~71 72 73 74 Private Sub cmdVote_Click() If optSex(0).Value = True Then I = 0 Else I = 3 End If For J = 0 To 2 If lstPerson.Selected(J) = True Then PVote(I) = PVote(I) + 1 : lblP(J) = PVote(I) I = I + 1 Next J End Sub Private Sub Form_Load() PName(0) = "老沈": PName(1) = "小章": PName(2) = "大千" PName(3) = "阿琴": PName(4) = "阿霞": PName(5) = "阿華" For I = 0 To 5 PVote(I) = 0 Next I Private Sub optSex_Click(Index As Integer) If Index = 0 Then lstPerson.Clear lstPerson.AddItem (PName(I)) : lblP(J) = PVote(I)

【實作範例10-16】 1:先對男性投票, 清單方塊的選項可以複選 2:再對女性投票 3:按下【統計】鈕 4:得票分布圓餅圖

【範例10-16】二分搜尋法 【範例10-16】:二分搜尋法。 二分搜尋法比循序搜尋法來得有效率許多,平均只需要做log2N+1次比較即可找到資料。雖然速度比較快,但使用二分搜尋法找尋資料必須先將資料經過排序之後,才可以使用用二分搜尋法。以下是用二分搜尋法的原理及步驟

【範例10-16】二分搜尋法 二分搜尋法原理: 先從記錄中央開始搜尋,若該記錄比目標還小,則往大的剩餘另一半搜尋,若記錄比目標還還大,則往小的剩餘另一半搜尋,若相等,則找到資料。重覆此步驟直到找到資料為止,或者發現要搜尋的資料不存在。因此,每次會剩下1/2、1/4、1/8、、、,在第k次比較時,最多只剩下『n/2k』筆記錄未搜尋,在最壞的狀況下,只剩單一記錄n/2k =1,所以k=log2n,所以最多的比較次數為log2n。

【範例10-16】二分搜尋法 二分搜尋演算法: 輸入:已排序的資料X(1)~X(n)、要找尋的目標資料K 輸出:目標資料的索引值m Low←1 Upper←n Do While (Low<=Upper) m←(Low+Upper)/2 '計算中間位置 Select Case X(m) Case X(m)>K 'K位於上半部 Upper←m-1 Case X(m)<K 'K位於下半部 Low←m+1 Case X(m)=K '找到了 return m End Select Loop return "找不到"

【範例10-16】二分搜尋法 【實例說明】: 8個陣列元素A(1)~A(8)為『33,41,52,54,63,74,79,86』, 尋找目標為52,使用二分搜尋法搜尋,則詳細步驟如下: 1. 計算中間位置為(1+8)/2=4.5取整數為4。 2. A(4)=54>52,所以Upper=4-1=3。 3. 計算中間位置為(1+3)/2=2。 4. A(2)=41<52,所以Lower=2+1=3。 5. 計算中間位置為(3+3)/2=3。 6. A(3)=52,所以找到了。

【範例10-16】二分搜尋法 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Option Base 1 Private Sub Form_Activate() X = Array(33, 41, 52, 54, 63, 74, 79, 86) K = 52 '搜尋目標K Low = 1 Upper = 8 FontSize = 14 Print "在X陣列中尋找" & K: Print Do While (Low <= Upper) m = Int((Low + Upper) / 2) '計算中間位置 Print "目前正在比對X(" & m & ")=" & X(m) Select Case X(m) Case Is > K 'K位於上半部 Upper = m - 1 Case Is < K 'K位於下半部 Low = m + 1 Case Is = K '找到了 Print: Print "要找的" & K & "位於X(" & m & ")" Exit Sub End Select Loop Print: Print "找不到" & K End Sub

10.9:本章回顧 理論與Visual Basic相關基本知識 控制項 陣列 搜尋與排序 動態陣列與靜態陣列 控制項陣列 清單方塊(ListBox)控制項 下拉式清單方塊(ComboBox)控制項 功能表(Menu)

本章習題