21
9-1 模組化程式設計 9-2 建立程序與函數 9-3 傳值或傳址呼叫 9-4 程序與函數的變數範圍 9-5 常用的內建函數

9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

  • Upload
    others

  • View
    9

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-1 模組化程式設計

9-2 建立程序與函數

9-3 傳值或傳址呼叫

9-4 程序與函數的變數範圍

9-5 常用的內建函數

Page 2: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-2

9-1 模組化程式設計

目前應用程式或系統軟體的功能愈來愈強大,從前一個人寫出的試算表程

式,幾個人開發的作業系統將成為神話,模組化程式設計在應用程式開發上也

就愈顯其重要性。

9-1-1 模組的基礎

應用程式或系統軟體因為需要大量人員參與分析、設計與開發,因此將一

個大型應用程式的功能分割成一個個獨立的子功能,就是一件非常重要的工作。

模組化

模組化是把大型功能切割成無數子功能,至於如何切割成一個個子功能的

「模組」(Modules),這屬於結構化分析的範疇,我們最常使用的是第 7章的由上而下設計方法(Top-down Design)。

對應到程式設計,模組化程式設計是將大程式切割成一個個小程式。以

Visual Basic語言來說,模組化的基本單位是程序與函數(Functions),因為模組可大可小,可能只是單一程序或函數,也可能是整個子功能的函數庫。不過,

每一個程序和函數都可以解決一個小問題,等到所有小問題都解決了,程序與

函數組合的軟體就開發完成。

程序與函數是一個黑盒子

程序與函數是一個執行特定功能的程式區塊,在呼叫時,我們不用了解程

序與函數內部實際的程式碼,程序與函數如同是一個「黑盒子」(Black Box),只要告訴我們如何使用此黑盒子的「使用介面」(Interface)即可,如下圖所示:

Page 3: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-3

上述圖例可以看出程式碼只知道呼叫程序或函數時,需要傳入的參數和取

得傳回值,它是程序與函數和外部溝通的使用介面,一個對外的邊界,實際程

式碼內容是隱藏在使用介面之後,其實際內容的程式碼撰寫稱為「實作」

(Implementation)。

程序與函數的最大差異在於程序沒有傳回值;而函數有傳回值。程序與函

數的語法和語意說明,如下所示:

語法(Syntax):說明程序與函數需要傳入何種資料型態的「參數」(Parameters,或稱引數)和傳回值(或稱回傳值)。

語意(Semantic):指出程序與函數可以作什麼事?

換句話說,在撰寫程序與函數時,我們需要了解其語法規則,呼叫程序與

函數時需要了解其語意規則,才能正確的呼叫程序與函數。

9-1-2 再談由上而下設計方法

由上而下設計方法是一種循序漸進了解問題的方法,它是在面對問題時先

考慮將整個解決問題的方法分解成數個大模組,然後針對每一個大模組,一一

分割成數個小模組,如此一直細分,直到細分的小問題建立的模組完成後,再

將它們組合起來,一層層的向上爬來完成整個應用程式或系統軟體的設計。

例如:玩拼圖遊戲一定先將整個拼圖粗分為數個區域,等每一個區域都拼

好後,整張拼圖也就完成了。現在,筆者準備直接使用房屋繪圖來說明如何分

割工作,如下圖所示:

上述圖例左邊的房屋圖形可以分割成多個小工作來分別繪製,換句話說,

我們可以使用由上而下設計方法來完成整個繪圖工作。

Page 4: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-4

分割繪出房屋圖形工作

整個房屋的繪圖工作可以粗分成三個子工作,如下所示:

(1) 繪出屋頂和外框。

(2) 繪出窗戶。

(3) 繪出門。

依據上述工作的分割建立各問題之間的模組架構,如下圖所示:

在上述圖例的【主程式】分別呼叫這些模組,其虛擬碼如下所示:

Call Draw Outline

Call Draw Windows

Call Draw Door

分割繪出屋頂和外框子工作

針對第一個子工作【繪出屋頂和外框】(Draw Outline),我們可以再次進行分割,分割成二個下一層的孫工作,如下所示:

(1) 繪出屋頂。

(2) 繪出房屋的外框。

依據上述分割建立下一層問題之間的模組架構,如下圖所示:

Page 5: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-5

上述圖例的【繪出屋頂和外框(Draw Outline)】模組是依序呼叫其下

的 2個模組,其虛擬碼如下所示:

Call Draw Roof

Call Draw House Frame

現在,我們只需重複上述分析,繼續一步一步向下進行工作的分割,例如:

窗戶有 2個,【繪出窗戶】可以分為【繪出窗戶 1】和【繪出窗戶 2】;【繪出門】可以分為【繪出門框】和【繪出門把】。

最後,將問題分割成一個個小問題後,每一個小問題就是一個 Visual Basic語言的程序或函數,只需完成這些程序與函數即可解決整個房屋繪圖的問題。

9-2 建立程序與函數

程序與函數可以將程式中,一些常用的共同程式碼獨立成程式區塊,也就

是建立結構化程式設計的模組。在 Visual Basic語言的程序可以分為兩種,如下所示:

事件處理程序:事件處理程序是處理指定事件的程序(一定是 Sub,因為不會有傳回值),在本章前的Windows應用程式已經使用 Click事件處理程序,關於事件的進一步說明請參閱第 11章。

一般程序或函數:將程式區塊使用一個程序或函數名稱來代替,以便程式可以重複呼叫程序與函數來執行特定功能。Visual Basic 語言的程序分為Sub程序和 Function函數兩種。

9-2-1 建立程序與函數

Visual Basic語言的程序是使用 Sub和 End Sub包圍的程式區塊,在 Sub關鍵字後是程序名稱,程序沒有傳回值。Function 函數類似 Sub 程序只是改為Function和 End Function包圍,其主要差異是函數有傳回值。

Page 6: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-6

程序的建立與呼叫

在 Visual Basic語言建立程序的語法,如下所示:

[Public | Private] Sub 名稱

程式區塊

End Sub

上述 Sub指令前的 Public或 Private是存取修飾子。Public是公用程序,即在專案中的所有程式檔案都可以呼叫。Private 只允許在同一個程式檔案進行呼叫。如果沒有指定,預設是 Public。

程序名稱的命名和變數名稱相同。例如:顯示提示字串的 ShowPrompt()程序,如下所示:

Sub ShowPrompt()

Dim msg As String

msg = "50元: "

lblOutput.Text = msg

End Sub

上述 Sub/End Sub是一個程式區塊,且沒有傳回值。在程式碼呼叫程序是使用 Call關鍵字,然後在其後加上程序名稱,如下所示:

Call ShowPrompt()

上述程序呼叫因為程序沒有參數,可以省略括號。不使用 Call 關鍵字也可以,如下所示:

ShowPrompt

上述程式碼也可以呼叫 ShowPrompt()程序。

函數的建立與呼叫

在 Visual Basic語言建立函數的語法,如下所示:

[Public | Private] Function 函數名稱 [As 資料型態]

程式區塊

Return 值 | 函數名稱 = 值

End Function

Page 7: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-7

上述 Function函數和 Sub程序十分相似,As之後是傳回值的資料型態。函數傳回值是使用 Return 關鍵字來傳回,或將函數名稱指定成需要傳回的值。例如:將台幣現鈔換成 50元零錢的 ReturnChange()函數,如下所示:

Function ReturnChange()

Dim Amount As Integer

Amount = CInt(txtAmount.Text)

Dim Change As Integer = 0

Do While Amount >= 50

Amount = Amount - 50

Change = Change + 1

Loop

Return Change

End Function

上述 ReturnChange()函數傳回可以換成幾個 50元硬幣,使用 Return傳回計算結果。傳回值也可以將函數名稱指定成傳回值,如下所示:

ReturnChange = Change

上述程式碼也可以指定函數的傳回值。函數因為有傳回值,通常都是在指

定敘述的右邊呼叫函數,如下所示:

lblOutput.Text &= ReturnChange()

上述程式碼將 lblOutput標籤控制項的 Text屬性指定成函數的傳回值。

範例專案 Ch9-2-1\換零錢機

在 Windows 應用程式使用 TextBox 控制項輸入兌換金額後,呼叫程序與函數顯示與計算可換成幾個 50元硬幣的零錢,其執行結果如下圖所示:

在上方輸入金額後,按【換零錢】鈕,可以在下方看到可換成 7個 50元硬幣的零錢,不過,如果金額沒有完全兌換完,程式並不會計算和顯示剩下多少

錢。

Page 8: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-8

表單設計工具

請建立 Windows Form 專案【換零錢機】且開啟表單 Form1(檔案名稱為Form1.vb),然後在表單設計工具新增 Label、TextBox和 Button控制項,其建立步驟如下所示:

選表單 Form1 後,在「屬性」視窗更改【Text】屬性值為【換零錢機】,

【Size】屬性值為【300, 150】。

在表單新增【金額:】的 Label 控制項後,即可在之後新增名為【txtAmount】的 TextBox 控制項,【Text】屬性值為【350】。

在右邊新增名為【換零錢】的 Button 控制項,如下圖所示:

在下方新增黑底白字的 Label 標籤控制項,在「屬性」視窗更改的相關屬

性值,如下表所示:

屬性 值

Name lblOutput

AutoSize False

BorderStyle FixedSingle

BackColor ControlText

ForeColor Control

Font-Size 10

TextAlign MiddleCenter

Button Label

TextBox

Page 9: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-9

在清除 Label 控制項的【Text】屬性值後,就完成使用介面的建立,如下

圖所示:

程式碼編輯器

在表單設計工具按二下名為【換零錢】的 Button 按鈕控制項,可以建立

Button1_Click()事件處理程序,和 ShowPrompt()程序與 ReturnChange()函數。

01: Sub ShowPrompt()

02: Dim msg As String

03: msg = "50元: "

04: lblOutput.Text = msg

05: End Sub

06:

07: Function ReturnChange()

08: Dim Amount As Integer

09: Amount = CInt(txtAmount.Text)

10: Dim Change As Integer = 0 ' 計算零錢數

11: ' 換零錢的迴圈

12: Do While Amount >= 50

13: Amount = Amount - 50 ' 每次減 50元

14: Change = Change + 1

15: Loop

16: Return Change

17: End Function

18:

19: Private Sub Button1_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles Button1.Click

20: Call ShowPrompt() ' 呼叫程序

21: lblOutput.Text &= ReturnChange() ' 呼叫函數

22: End Sub

Label

Page 10: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-10

程式碼解說

第 1~5列:ShowPrompt()程序可以在 Label標籤控制項顯示一段提示文字。

第 7~17列:ReturnChange()函數可以換零錢,在第 9列取得使用者輸入的金額後,使用第 12~15列的 Do While/Loop迴圈計算可兌換的零錢數,在第 16列使用 Return關鍵字傳回兌換個數。

第 20~21列:分別呼叫 ShowPrompt()程序和 ReturnChange()函數。

程序與函數的執行過程

Visual Basic程式是如何執行程序與函數,以本節範例專案為例,程式是在Button1_Click()事件處理程序的第 20 列呼叫 ShowPrompt()程序,此時程式碼執行順序跳到此程序的第 1列,在執行完第 5列後返回呼叫點,如下圖所示:

然後繼續執行程式,在第 21 列呼叫 ReturnChange()函數,程式碼跳到此函數的第 7列,在執行完第 17列返回呼叫點的 Button1_Click()事件處理程序,即可完成整個程式的執行。事實上!程序與函數只是更改程式碼的執行順序,在

呼叫點跳到程序或函數來執行,在執行完後,回到程式的呼叫點繼續執行其他

的程式碼。

9-2-2 擁有參數的程序與函數

程序與函數可以在程序與函數加上參數,當呼叫時傳入不同的參數值後,

相同的程序與函數也可以得到不同的執行結果。

Page 11: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-11

建立擁有參數的程序與函數

在 Visual Basic語言建立擁有參數的程序與函數,其語法如下所示:

[Public | Private] [Sub | Function] 名稱(參數 1, 參數 2, …)

程式區塊

[Return 值 | 名稱 = 值]

End [Sub | Function]

上述括號的參數稱為「正式參數」(Formal Parameters)或「假的參數」(Dummy Parameters)。正式參數是識別字,其角色如同變數,需要指定資料型態,而且可以在程式區塊中使用。例如:顯示提示字串的 ShowPrompt()程序擁有 1 個參數,如下所示:

Sub ShowPrompt(msg As String)

lblOutput.Text = msg

End Sub

上述程序擁有一個參數。擁有參數的函數,例如:換零錢函數 ReturnChange()擁有 2個參數,如下所示:

Function ReturnChange(Amount As Integer, Unit As Integer)

Dim Change As Integer = 0

Do While Amount >= Unit

Amount = Amount - Unit

Change = Change + 1

Loop

Return Change

End Function

上述 ReturnChange()函數擁有 2個參數,第 1個是金額,第 2個是零錢單位,因為參數不只一個,所以使用「,」逗號分隔。此函數可以將參數金額兌換成指定單位的零錢。

在 ReturnChange()函數因為擁有參數,所以不只可以兌換 50 元硬幣,只需輸入不同單位的參數,我們一樣可以兌換成其他不同種類的零錢,例如:10 元或 5元硬幣。

Page 12: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-12

呼叫擁有參數的程序與函數

程序與函數如果擁有參數,在呼叫時可以指定不同的參數值。因為

ShowPrompt()程序擁有參數,所以呼叫時需要指定參數值,如下所示:

Call ShowPrompt("可兌換數: ")

上述程序呼叫的括號中有指定參數值。擁有參數的函數呼叫,如下所示:

lblOutput.Text &= ReturnChange(Amount, Unit)

上述程式碼呼叫函數來兌換零錢,參數是 2 個變數值,其傳回值是顯示在Label標籤控制項。

在呼叫程序與函數時的參數稱為「實際參數」(Actual Parameters),即傳入的參數值,需要和正式參數定義的資料型態相同,每一個正式參數都需對應

相同型態的實際參數。

範例專案 Ch9-2-2\換零錢機

這個 Windows 應用程式是修改第 9-2-1 節的【換零錢機】,改為使用擁有參數的程序與函數來兌換零錢,表單新增 TextBox 控制項輸入零錢的單位,其執行結果如下圖所示:

在上方輸入金額和零錢單位後,按【換零錢】鈕,可以在下方看到計算結

果的零錢數,以此例是 88個 5元硬幣,前面字串是 ShowPrompt()程序顯示的提示文字。

Page 13: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-13

表單設計工具

請建立Windows Form專案【換零錢機】,這是直接複製和貼上第 9-2-1節範例專案資料夾,然後新增輸入單位的 Label 和 TextBox 控制項來修改使用介面,其建立步驟如下所示:

請在「方案總管」視窗按二下 Form1.vb 開啟表單設計工具。

選表單 Form1 後,在「屬性」視窗更改【Size】屬性值為【300, 200】,

並且調整 lblOutput 標籤控制項的尺寸和位置,即向下方拖拉空出中間部

分的編輯區域。

在空出的編輯區域新增【零錢單位:】的 Label 控制項後,在之後新增名為

【txtUnit】的 TextBox 控制項,【Text】屬性值為【10】。如下圖所示:

程式碼編輯器

在表單設計工具按二下名為【換零錢】的 Button 按鈕控制項,可以修改

Button1_Click()事件處理程序、ShowPromt()程序和 ReturnChange()函數。

01: Sub ShowPrompt(ByVal msg As String)

02: lblOutput.Text = msg

03: End Sub

04:

05: Function ReturnChange(ByVal Amount As Integer, _

ByVal Unit As Integer)

06: Dim Change As Integer = 0 ' 計算零錢數

07: ' 換零錢的迴圈

08: Do While Amount >= Unit

TextBox Label

Page 14: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-14

09: Amount = Amount - Unit ' 每次減一單位

10: Change = Change + 1

11: Loop

12: Return Change

13: End Function

14:

15: Private Sub Button1_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles Button1.Click

16: Dim Amount, Unit As Integer

17: Amount = CInt(txtAmount.Text)

18: Unit = CInt(txtUnit.Text)

19: Call ShowPrompt("可兌換數:") ' 呼叫程序

20: lblOutput.Text &=ReturnChange(Amount, Unit)' 呼叫函數

21: End Sub

程式碼解說

第 1~3列:ShowPrompt()程序擁有一個 String型態的參數 msg,前方 ByVal關鍵字指出參數是傳值參數,這是 Visual Basic語言預設的參數傳遞方式,在 VBE輸入程序或函數的參數時,如果沒有指明就會自動加上 ByVal,其進一步說明請參閱第 9-3節。

第 5~13 列:ReturnChange()函數擁有 2 個 Integer 資料型態的參數,在第8~11列的迴圈計算可兌換多少零錢,在第 12列使用 Return關鍵字傳回兌換個數。

第 15~21 列:Button1_Click()事件處理程序是在第 17~18 列取得使用者輸入的金額與單位,第 19~20列分別呼叫ShowPrompt()程序和ReturnChange()函數計算與顯示兌換的零錢數。

9-2-3 強迫跳出程序與函數

在執行程序或函數時如果需要中斷程序或函數的執行,此時可以使用 Exit Sub 跳出程序;Exit Function 中斷函數的執行,即跳出函數。例如:換零錢的ReturnChange()函數,如下所示:

Function ReturnChange(Amount As Integer, Unit As Integer)

Dim Change As Integer = 0

Do While True

Amount = Amount - Unit

If Amount >= 0 Then

Change = Change + 1

Page 15: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-15

Else

Return Change

Exit Function

End If

Loop

End Function

上述函數使用 Do While/Loop無窮迴圈來兌換零錢,當金額小於 0時,表示金額已經兌換完,所以使用 Exit Function中斷函數的執行(即中斷 Do While/Loop迴圈)。

不過,ReturnChange()函數只能傳回兌換成的零錢數,如果有小於零錢數的餘額,函數並不會傳回,這部分處理需要使用函數的傳址參數,進一步說明請

參閱第 9-3節。

範例專案 Ch9-2-3\換零錢機

這個 Windows 應用程式是修改第 9-2-2 節的【換零錢機】,改為使用RadioButton 選項按鈕選擇零錢種類,在 ReturnChange()函數的迴圈改用 Exit Function來兌換零錢,其執行結果如下圖所示:

在上方輸入金額和選擇種類後,按【換零錢】鈕,可以在下方看到可換成

幾個選擇種類的零錢和還剩下多少錢。

表單設計工具

請建立Windows Form專案【換零錢機】,這是直接複製和貼上第 9-2-2節範例專案資料夾,然後新增選擇零錢種類的 GroupBox和 3個 RadioButton控制項來修改使用介面,其建立步驟如下所示:

Page 16: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-16

請在「方案總管」視窗按二下 Form1.vb 開啟表單設計工具,選表單 Form1後,刪除【零錢單位:】的 Label 控制項和之後名為【txtUnit】的 TextBox控制項。

在空出的編輯區域新增 GroupBox 控制項,其【Text】屬性為【種類】後,

新增 3 個 RadioButton 控制項來選擇零錢種類有 50、10 和 5 元三種,如

下圖所示:

上述 3個 RadionButton控制項在「屬性」視窗更改的屬性值,如下表所示:

控制項種類 Name屬性 Text屬性 Checked屬性

選項按鈕 rdb50 50元 True

選項按鈕 rdb10 10元 False

選項按鈕 rdb5 5元 False

程式碼編輯器

在表單設計工具按二下名為【換零錢】的 Button 按鈕控制項,可以刪除

ShowPrompt() 程 序 , 和 修 改 Button1_Click() 事 件 處 理 程 序 和

ReturnChange()函數。

01: Function ReturnChange(ByVal Amount As Integer, _

ByVal Unit As Integer)

02: Dim Change As Integer = 0

03: Do While True ' 無窮迴圈

04: Amount = Amount - Unit

05: If Amount >= 0 Then

06: Change = Change + 1

07: Else

08: Return Change

GroupBox

Page 17: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-17

09: Exit Function ' 跳出函數

10: End If

11: Loop

12: End Function

13:

14: Private Sub Button1_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles Button1.Click

15: Dim Amount As Integer = CInt(txtAmount.Text)

16: Dim Change, Type As Integer

17: ' 選擇零錢種類

18: If rdb50.Checked Then

19: Change = ReturnChange(Amount, 50) ' 呼叫函數

20: Type = 50

21: End If

22: If rdb10.Checked Then

23: Change = ReturnChange(Amount, 10) ' 呼叫函數

24: Type = 10

25: End If

26: If rdb5.Checked Then

27: Change = ReturnChange(Amount, 5) ' 呼叫函數

28: Type = 5

29: End If

30: lblOutput.Text=Type & "元: " & Change & "個" & vbNewLine

31: ' 計算剩下多少錢

32: lblOutput.Text &="剩下: " & (Amount-Type*Change) & "元"

33: End Sub

程式碼解說

第 1~12 列:ReturnChange()函數可以計算兌換成幾個零錢,第 3~11 列是Do While/Loop 無窮迴圈,每執行一次迴圈,就在第 4 列將金額減去零錢單位,即換一個零錢,第 5~10列的 If Then/Else條件判斷是否兌換完,如果是,在第 9列使用 Exit Function跳出函數。

第 14~33 列:Button1_Click()事件處理程序在第 15 列取得兌換金額,第18~29列的 3個 If Then條件判斷兌換哪一種零錢,以便呼叫ReturnChange()函數計算兌換個數,在第 32列計算換剩下的金額。

Page 18: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-18

9-3 傳值或傳址呼叫

程序與函數不同的參數傳遞方式可以影響傳入參數的變數值。Visual Basic語言提供兩種參數傳遞方式,如下表所示:

呼叫方式 關鍵字 說明

傳值呼叫 ByVal 將變數的值傳入程序或函數,並不會變更原變數的值

傳址呼叫 ByRef 將變數實際記憶體儲存位址傳入,所以在程序與函數變更參

數的變數值,也會同時更改原變數值

在 Visual Basic程序與函數預設是使用傳值呼叫,如果沒有指明,VBE程式碼編輯器會自動加上 ByVal,如下所示:

Sub SubByVal(ByVal P As Integer)

…..

End Sub

事實上,只有傳址程序或函數才需要指名 ByRef,如下所示:

Sub SubByRef(ByRef P As Integer)

….

End Sub

範例專案 Ch9-3\換零錢機

這個 Windows 應用程式是修改第 9-2-3 節的【換零錢機】,只是將ReturnChange()函數改為使用整數除法和餘數來計算,並且使用傳址呼叫傳回剩下的金額,其執行結果如下圖所示:

Page 19: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-19

在上方輸入金額和選擇種類後,按【換零錢】鈕,可以在下方顯示共兌換

成幾個選擇種類的零錢和剩下多少錢。

表單設計工具

請建立Windows Form專案【換零錢機】,這是直接複製和貼上第 9-2-3節範例專案資料夾,其步驟如下所示:

請在「方案總管」視窗按二下 Form1.vb 開啟表單設計工具,如下圖所示:

程式碼編輯器

在表單設計工具按二下名為【換零錢】的 Button 按鈕控制項,可以修改

Button1_Click()事件處理程序和 ReturnChange()函數。

01: Function ReturnChange(ByRef Amount As Integer, _

ByVal Unit As Integer)

02: Dim Change As Integer

03: Change = Amount \ Unit ' 整數除法

04: Amount = Amount Mod Unit ' 餘數

05: Return Change

06: End Function

07:

08: Private Sub Button1_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles Button1.Click

09: Dim Amount As Integer = CInt(txtAmount.Text)

10: Dim Change As Integer

11: ' 選擇零錢種類

12: If rdb50.Checked Then

13: Change = ReturnChange(Amount, 50) ' 呼叫函數

14: lblOutput.Text = "50元"

Page 20: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-20

15: End If

16: If rdb10.Checked Then

17: Change = ReturnChange(Amount, 10) ' 呼叫函數

18: lblOutput.Text = "10元"

19: End If

20: If rdb5.Checked Then

21: Change = ReturnChange(Amount, 5) ' 呼叫函數

22: lblOutput.Text = "5元"

23: End If

24: lblOutput.Text &= Change & "個" & vbNewLine

25: lblOutput.Text &= "剩下: " & Amount & "元"

26: End Sub

程式碼解說

第 1~6列:ReturnChange()函數的第 1個參數是傳址呼叫;第 2個是傳值呼叫,在第 3~4列使用整數除法和餘數運算來兌換零錢。

第 8~26 列:Button1_Click()事件處理程序在第 9 列取得兌換金額,第 12~23列的 3個 If Then條件判斷兌換哪一種零錢,以便呼叫 ReturnChange()函數計算兌換個數,參數 Amount在呼叫後,就是剩下的金額。

9-4 程序與函數的變數範圍

Visual Basic程式檔案可以同時建立多個程序或函數,在不同位置宣告的變數都擁有不同的有效範圍,也就是在程式區塊的哪些程式碼可以存取這些變數。

「變數範圍」(Scope)是當程式執行時,變數可以讓程序與函數內或其他程式區塊存取的範圍。在 Visual Basic模組或類別中,變數依宣告位置擁有三種範圍,如下所示:

區塊範圍(Block Scope):在 If/End If、Select Case/End Case 和 Do While/Loop 等程式區塊內使用 Dim 宣告的變數,變數只能在區塊之內使用,區塊之外的程式碼並無法存取這些變數。

區域範圍(Local Scope):在程序與函數內使用 Dim宣告的變數,變數只能在程序或函數內使用,程序或函數外程式碼並無法存取此變數,稱為

「區域變數」(Local Variables)。

Page 21: 9-1 模組化程式設計 9-2 建立程序與函數 傳值或傳址呼叫 程序與函 …epaper.gotop.com.tw/pdf/AEL011700.pdf · Form1.vb),然後在表單設計工具新增Label、TextBox

9-21

全域範圍(Global Scope):變數如果是在模組/類別的Module/ End Module和 Class/End Class中,以 Dim或 Private宣告在程序和函數外,該模組/類別檔案的程序和函數都可以存取此變數,稱為「全域變數」(Global Variables)。

筆者已經將上述變數範圍整理成圖形表示,如下圖所示:

不只如此,全域變數如果使用 Public宣告,整個 Visual Basic專案的所有模組/類別檔案都可以存取此變數,屬於模組等級的全域變數。

範例專案 Ch9-4\換零錢機

這個 Windows 應用程式是修改和擴充第 9-3 節的【換零錢機】,改用CheckBox 控制項勾選想兌換的硬幣種類,程式可以計算可兌換成幾個 50 元硬幣、幾個 20元、幾個 10元、5元和 1元硬幣,其執行結果如下圖所示:

在上方輸入兌換金額,勾選需要兌換的硬幣種類後,按【換零錢】鈕,可

以在下方看到各種硬幣的兌換數量。