新觀念的VB6教本ch092. 副程式與函數副程式與函數
副程式副程式 (Subprogram)(Subprogram) 與函數與函數 (Function)(Function) ,,
是用來封裝敘述區塊的程式單元,而被是用來封裝敘述區塊的程式單元,而被
封裝在副程式及函數裡的敘述區塊,並封裝在副程式及函數裡的敘述區塊,並
不屬於任何敘述,是個別獨立的,但這不屬於任何敘述,是個別獨立的,但這
些獨立的程式單元卻可以給其他程式單些獨立的程式單元卻可以給其他程式單
元使用。元使用。
因此我們會把經常重複撰寫的敘述區塊因此我們會把經常重複撰寫的敘述區塊
寫成副程式或函數,以節省程式開發的寫成副程式或函數,以節省程式開發的
時間。時間。
11. 呼叫副程式的格式二呼叫副程式的格式二 (1)(1)
為了在閱讀上與為了在閱讀上與 VBVB 的敘述有所區分,的敘述有所區分,
我們通常用另一種格式來執行副程式:我們通常用另一種格式來執行副程式:
Call MySubCall MySub 的 作 用 與 不 含的 作 用 與 不 含 CallCall 的的
MySubMySub 敘述完全相同,敘述完全相同, CallCall 是是 呼叫呼叫 的的
意思,所以在習慣上我們通常說意思,所以在習慣上我們通常說呼叫呼叫副副
程式程式,而不說,而不說執行執行副程式。副程式。
Call MySub
14. 參數及參數傳遞的觀念參數及參數傳遞的觀念 (2)(2)
我們前面所寫的我們前面所寫的 MySubMySub 副程式,每次執行的副程式,每次執行的
結果都一成不變,就像非插卡式的電動玩具一結果都一成不變,就像非插卡式的電動玩具一
樣,價 比較低。值樣,價 比較低。值
為了增加副程式的實用性,為了增加副程式的實用性, VBVB 讓副程式可以讓副程式可以
接受呼叫者所插入的資料。接受呼叫者所插入的資料。
在術語上,插入資料到副程式的動作叫做在術語上,插入資料到副程式的動作叫做參數參數
傳遞傳遞,而每一筆插入的資料則稱為,而每一筆插入的資料則稱為參數參數
(parameter)(parameter) 。。
16. 參數及參數傳遞的觀念參數及參數傳遞的觀念 (4)(4)
例如:例如:
在這兩個副程式裡,我們可以發現參數在副程在這兩個副程式裡,我們可以發現參數在副程
式裡面的用法就跟變數一樣。式裡面的用法就跟變數一樣。
Sub Increment( I ) ' 含有一個參數
的副程式
I = I + 1
Debug.Print "I ="; I
End Sub
Sub Add_Three( A, B, C ) ' 含有三個參數
的副程式
Debug.Print A+B+C
End Sub
17. 呼叫含有參數的副程式呼叫含有參數的副程式
如何呼叫含有參數的副程式 ?首先來呢如何呼叫含有參數的副程式 ?首先來呢
看個實例:看個實例:
它的意思是分別以它的意思是分別以 1010 、、 2020 、、 3030 替代替代
AA 、、 BB 、、 CC 的 ,相當於把值的 ,相當於把值 1010 、、 2020 、、
3030 分別指定給分別指定給 AA 、、 BB 、、 CC ,所以將來,所以將來
執行到執行到 Add_ThreeAdd_Three 副程式裡的副程式裡的
Debug.Print A+B+CDebug.Print A+B+C 時,即會印出時,即會印出 6060
的結果。的結果。
Call Add_Three( A:=10, B:=20, C:=30 )
19. 形式參數與實際參數形式參數與實際參數 (1)(1)
上 述 例 子 , 出 現 在 呼 叫 敘 述 中 的上 述 例 子 , 出 現 在 呼 叫 敘 述 中 的
1010 、、 2020 、、 3030 三個參數,叫做三個參數,叫做實際參數實際參數
(actual parameter)(actual parameter) 。。
出現在出現在 SubSub 敘述中的敘述中的 A, B, CA, B, C 三個參數三個參數
,叫做,叫做形式參數形式參數 (formal parameter)(formal parameter) 。。
22. 形式參數的意義形式參數的意義
當我們定義當我們定義 (( 即撰寫即撰寫 )) 副程式時,例如前面的副程式時,例如前面的
Sub Add_Three( A, B, C )Sub Add_Three( A, B, C ) ,由於我們並不知道,由於我們並不知道
將來呼叫者會傳入 些資料作為參數,因此只哪將來呼叫者會傳入 些資料作為參數,因此只哪
好給這些參數好給這些參數取個暫時性的名稱。取個暫時性的名稱。
如本例的如本例的 AA 、、 BB 、、 CC ,而將來副程式被呼叫,而將來副程式被呼叫
時它們才會被真正的資料時它們才會被真正的資料 (( 常數 或變數值常數 或變數值 )) 所所
取代,所以取代,所以副程式定義中的參數都只是形式上副程式定義中的參數都只是形式上
的,故稱為「的,故稱為「形式參數形式參數」」。。
25. 以變數為實際參數以變數為實際參數 (1)(1)
呼叫時的實際參數也可以是變數,例如呼叫時的實際參數也可以是變數,例如
::
這個呼叫敘述會以實際參數這個呼叫敘述會以實際參數 II 、、 JJ 、、 KK
替代形式參數替代形式參數 AA 、、 BB 、、 CC ,使得執行,使得執行
Debug.Print A+B+CDebug.Print A+B+C 相當於執行相當於執行
Debug.Print I+J+KDebug.Print I+J+K ,所以印出的結果是,所以印出的結果是
600600 。。
I = 100 : J = 200 : K = 300
Call Add_Three( A:=I, B:=J, C:=K ) ' 以變數 I 、 J 、 K
為實際參數
26. 以變數為實際參數以變數為實際參數 (2)(2)
雖然實際參數可以是常數 或是變數,值雖然實際參數可以是常數 或是變數,值
但但 VBVB 在替代形式參數的作法上卻有所在替代形式參數的作法上卻有所
不同。不同。
如果實際參數是常數,則替代指的是替如果實際參數是常數,則替代指的是替
代形式參數的「代形式參數的「值值」。」。
如果實際參數是變數,則替代即是以實如果實際參數是變數,則替代即是以實
際參數中的變數替代形式參數。際參數中的變數替代形式參數。
28. 以變數為實際參數的例子以變數為實際參數的例子 (2)(2)
其中其中 Call Increment( I:=X )Call Increment( I:=X ) 將以變數將以變數 XX
替代替代 II ,所以副程式的執行變成:,所以副程式的執行變成:
印出結果等於印出結果等於 1111 ,而,而 XX 的 也由值的 也由值 1010
變成變成 1111 。。
X = X + 1
Debug.Print "I ="; X
29. 以變數為實際參數的例子以變數為實際參數的例子 (3)(3)
至於至於 Call Increment( I:=10 )Call Increment( I:=10 ) 則是以則是以 1010
替代替代 II 的 ,不是替代值的 ,不是替代值 II 本身,所以副本身,所以副
程式的執行還是維持:程式的執行還是維持:
而由於而由於 II 的 已經被替代成值的 已經被替代成值 1010 ,所以也,所以也
會印出會印出 1111 的結果。的結果。
I = I + 1
Debug.Print "I ="; I
30. 以變數為實際參數以變數為實際參數 ---- 問題思問題思
考考
為什麼為什麼 Call Increment( I:=10 )Call Increment( I:=10 ) 的參數傳的參數傳
遞中,是以遞中,是以 1010 替代替代 II 的「 」,而不是值的「 」,而不是值
直接以直接以 1010 替代替代 II 「本身」 ?呢「本身」 ?呢
如果是這樣,副程式的執行將會變成:如果是這樣,副程式的執行將會變成:
10 = 10 + 1 ' 產生錯誤
Debug.Print "I ="; 10
31. 變數的傳 呼叫值變數的傳 呼叫值 (1)(1)
呼叫副程式還有一種格式,是在實際參呼叫副程式還有一種格式,是在實際參
數前後加上左右括弧,如下:數前後加上左右括弧,如下:
雖然只是多個括弧,但呼叫後的效應卻雖然只是多個括弧,但呼叫後的效應卻
有所不同。有所不同。
Call 副程式名 ( ( 實際參數 1), ( 實際參數
2), …)
32. 變數的傳 呼叫值變數的傳 呼叫值 (2)(2)
以前面的以前面的 IncrementIncrement 副程式為例,以下分別是副程式為例,以下分別是
實際參數前後不加實際參數前後不加 ( )( ) 及加及加 ( )( ) 兩種呼叫的方兩種呼叫的方
式及執行結果:式及執行結果:
實際參數前後不加實際參數前後不加 ()() 的呼的呼
叫叫
實際參數前後加實際參數前後加 ()() 的呼的呼
叫叫X = 10X = 10 X = 10X = 10
Call Increment( I:=X )Call Increment( I:=X ) Call Increment( I:=(X) )Call Increment( I:=(X) )
Debug.Print "X ="; XDebug.Print "X ="; X Debug.Print "X ="; XDebug.Print "X ="; X
結果:結果: 結果:結果:
I = 11I = 11 I = 11I = 11
X = 11X = 11 X = 10X = 10
33. 變數的傳 呼叫值變數的傳 呼叫值 (3)(3)
其中其中 Call Increment( (X) )Call Increment( (X) ) 的呼叫中,的呼叫中, (X)(X) 表示「取變表示「取變
數數 XX 的 」,所以它相當於值的 」,所以它相當於值 CallCall
Increment( I:=10 )Increment( I:=10 ) 。因此這兩種呼叫在副程式裡面的執。因此這兩種呼叫在副程式裡面的執
行分別是:行分別是:
所以所以 XX 才會得到兩種不同的結果。才會得到兩種不同的結果。
Call Increment( I:=X )Call Increment( I:=X ) Call Increment( I:=(X) )Call Increment( I:=(X) )
以以 XX 替代替代 II 取取 XX 的 替代值的 替代值 II 的值的值
X = X + 1X = X + 1 I = I + 1I = I + 1
Debug.Print "I ="; XDebug.Print "I ="; X Debug.Print "I ="; IDebug.Print "I ="; I
執行之後執行之後 XX 的 改變值的 改變值
了了
執行時並未改變執行時並未改變 XX 的的
值值
34. 變數的傳 呼叫意義值變數的傳 呼叫意義值
呼叫時在變數前後加上左右括弧,使替呼叫時在變數前後加上左右括弧,使替
代形式參數的是實際參數的 ,而不是值代形式參數的是實際參數的 ,而不是值
實際參數本身的方式,叫做實際參數本身的方式,叫做傳 呼叫值傳 呼叫值
(call by value)(call by value) 。。
36. ByValByVal 保留字的作用保留字的作用
ByValByVal 的作用是傳 呼叫。值的作用是傳 呼叫。值
加了加了 ByValByVal 之後,將來的呼叫不管是之後,將來的呼叫不管是
Call Increment( I:=X )Call Increment( I:=X ) 或是或是
Call Increment( I:=(X) )Call Increment( I:=(X) ) ,其代表的意義,其代表的意義
都是取變數都是取變數 XX 的 取代參數值的 取代參數值 II 的 ,值的 ,值
所以呼叫之後所以呼叫之後 XX 的 都不會改變。值的 都不會改變。值
40. 形式參數的型別比較例一形式參數的型別比較例一 (2)(2)
執行後分別印出:執行後分別印出: 8.18.1 及及 99 。這兩個副程式都。這兩個副程式都
可以細解成:可以細解成:
但但 Add_Three_IntAdd_Three_Int 副程式把副程式把 AA 、、 BB 、、 CC 都宣都宣
告成整數了,所以告成整數了,所以 1.61.6 、、 2.72.7 、、 3.83.8 指定給指定給
AA 、、 BB 、、 CC 時,必須轉換成整數,而變成時,必須轉換成整數,而變成
22 、、 33 、、 44 ,所以執行結果等於,所以執行結果等於 99 。。
A = 1.6
B = 2.7
C = 3.8
Debug.Print A+B+C
42. 形式參數的型別比較例二形式參數的型別比較例二 (2)(2)
結果分別印出結果分別印出 6060 及及 102030102030 。。
其中第一個呼叫敘述,由於形式參數其中第一個呼叫敘述,由於形式參數 AA 、、 BB 、、
CC 都宣告成整數,所以實際參數的都宣告成整數,所以實際參數的
““ 10”10” 、“、“ 20”20” 、“、“ 30”30” 會被轉換成會被轉換成
1010 、、 2020 、、 3030 ,所以得到,所以得到 6060 的結果。的結果。
而第二個呼叫敘述,由於形式參數而第二個呼叫敘述,由於形式參數 AA 、、 BB 、、 CC
都未宣告型別,所以實際參數都未宣告型別,所以實際參數
"10""10" 、、 "20""20" 、、 "30""30" 都維持原來的字串特性,而都維持原來的字串特性,而
'+''+' 對字串來說表示串接運算,所以得到對字串來說表示串接運算,所以得到
"102030" 的結果。
Call Add_Three_Int( A:="10", B:="20", C:="30" )
Call Add_Three( A:="10", B:="20", C:="30" )
43. 形式參數的型別 – 注意事項形式參數的型別 – 注意事項 (1)(1)
若形式參數宣告了型別,而呼叫時的實若形式參數宣告了型別,而呼叫時的實
際參數是變數,則實際參數與形式參數際參數是變數,則實際參數與形式參數
的型別必須相同才行,例如:的型別必須相同才行,例如:
P# = 1.6 : Q# = 2.7 : R# = 3.8
Call Add_Three_Int( A:=P#, B:=Q#, C:=R# ) ' 錯誤
!
44. 形式參數的型別 – 注意事項形式參數的型別 – 注意事項 (2)(2)
為什麼會產生錯誤 ?因為例子中的實呢為什麼會產生錯誤 ?因為例子中的實呢
際參數際參數 P#P# 、、 Q#Q# 、、 R#R# 都是倍精準度型都是倍精準度型
別,而形式參數別,而形式參數 AA 、、 BB 、、 CC 則都是整則都是整
數型別,它們不管所佔空間或資料儲存數型別,它們不管所佔空間或資料儲存
方式均不同,所以不能替代。方式均不同,所以不能替代。
45. 形式參數的型別 – 問題思考形式參數的型別 – 問題思考 11
如果把上面的呼叫修改如下,是不是就如果把上面的呼叫修改如下,是不是就
會為會為 VBVB 所接受,為什麼?所接受,為什麼?
Call Add_Three_Int( A:=(P#), B:=(Q#), C:=(R#) )
46. 形式參數的型別 – 問題思考形式參數的型別 – 問題思考 22
如 果 定 義如 果 定 義 Add_Three_IntAdd_Three_Int 副 程 式 時 , 在 參 數副 程 式 時 , 在 參 數
AA 、、 BB 、、 CC 前面都加上前面都加上 ByValByVal 保留字,變成保留字,變成
::
則呼叫:則呼叫:
是不是就會為是不是就會為 VBVB 所接受,為什麼?所接受,為什麼?
Sub Add_Three_Int(ByVal A As Integer,ByVal B As Integer,ByVal C As
Integer )
Call Add_Three_Int( A:=(P#), B:=(Q#), C:=(R#) )
47. 形式參數的型別 – 問題說明形式參數的型別 – 問題說明
兩者都為兩者都為 VBVB 所接受。所接受。
在以上兩個問題中,雖然形式參數與實在以上兩個問題中,雖然形式參數與實
際參數的型別並不相同,但由於兩者都際參數的型別並不相同,但由於兩者都
屬於傳 呼叫,因此不受型別不同的限值屬於傳 呼叫,因此不受型別不同的限值
制。制。
53. 如何處理函數的傳回值如何處理函數的傳回值 (2)(2)
例如:例如:
A = TypeName("VB") ' 把 TypeName 函數的傳回值指定給變數 A
Print Asc("1") ' 把 Asc 函數的傳回值當成 Print 敘述的資料
Call Increment(Asc("A")) ' 以 Asc 函數的傳回值作為 Increment 副程式的參
數
X = TypeName(Asc("P6")) ' 以 Asc 函數的傳回值作為 TypeName 函數的參
數
54. 自定函數自定函數 VSVS 自定副程式自定副程式
自定函數的方法也跟自定副程式的方法自定函數的方法也跟自定副程式的方法
十分相似,以下是針對差異之處的說明十分相似,以下是針對差異之處的說明
::
定義函數的保留字 Funct i on
Funct i on 函數名( 形式參數串列 )
End Funct i on
利用這個運算式來
設定函數的傳回值
1.
2.
:
:
函數名 = 運算式
55. 自定函數自定函數 VSVS 自定副程式自定副程式
1.1. 定義副程式的保留字是定義副程式的保留字是 SubSub ,定義函,定義函
數則是數則是 FunctionFunction 。。
2.2. 由於函數最後要傳回一個 ,才算完成值由於函數最後要傳回一個 ,才算完成值
函數的任務,而敘述「函數的任務,而敘述「函數名函數名 == 運算運算
式式」的作用就是以」的作用就是以運算式運算式的結果作為函的結果作為函
數的傳回 。值數的傳回 。值
56. 自定函數自定函數 ---- 實例練習實例練習
寫一寫一 f(x) = X^2+2*x+1f(x) = X^2+2*x+1 的函數。的函數。
若呼叫的敘述如下:若呼叫的敘述如下:
結果印出結果印出 1616 。。
Function f(X)
f = X^2+2*X+1 ' 把 X^2+2*x+1 的運算結果指定給函數名
f ,
End Function ' 其作用就是把運算結果當作函數的傳回值。
V = f(3) ' 將會傳回 3^2+2*3+1 的結果
Debug.Print V
57. 函數的型別函數的型別
宣告函數傳回 的型別,格式有:值宣告函數傳回 的型別,格式有:值
例:例:
Function 函數名 ( 形式參數串列 ) As 型別名稱
或
Function 函數名 + 型別宣告符號 ( 形式參數串列
)
Funct i on 將 f ( x) 的傳回值宣告成長整數型別
Funct i on f &( X)
f ( X) As Long
利用&型別宣告符號,將 f ( x)
的傳回值宣告成長整數型別
58. 函數的型別函數的型別 ---- 實例練習實例練習 p.278p.278
(1)(1)
寫一寫一 Sum(N)=1+2+…+NSum(N)=1+2+…+N 的函數。的函數。
Function Sum#(N) ' 利用整數型別宣告符號 '#' 將 Sum
Sum = 0 ' 的傳回值宣告成倍精準度型別
For I = 1 To N
Sum = Sum + I ' 函數名 Sum 也可以當成正常的變數
Next I ' 使用,而它最後的值會變成傳回值
End Function
59. 函數的型別函數的型別 ---- 實例練習實例練習 p.278p.278
(2)(2)
這個函數中有一點 得注意:函數名稱值這個函數中有一點 得注意:函數名稱值
SumSum 在函數裡面的功用就跟變數一樣,在函數裡面的功用就跟變數一樣,
我們可以把它當成一般的變數來使用,我們可以把它當成一般的變數來使用,
而最後當函數返回時,這個變數的 就值而最後當函數返回時,這個變數的 就值
會成為函數的傳回 。值會成為函數的傳回 。值
60. 函數的好處函數的好處
記得我們在第記得我們在第 77 章所寫過的「章所寫過的「 Sum = 1 +Sum = 1 +
2 + ... + 202 + ... + 20 」程式 ?嗎」程式 ?嗎
有了以上的有了以上的 Sum(N)Sum(N) 函數之後,不管是函數之後,不管是
1 + 2 + ... + 201 + 2 + ... + 20 或是或是 1 + 2 + ... + 10001 + 2 + ... + 1000 ,,
只要分別以只要分別以 Sum(20)Sum(20) 及及 Sum(1000)Sum(1000) 來來
呼叫呼叫 Sum(N)Sum(N) 函數就可以得到答案,而不函數就可以得到答案,而不
必為必為 1 + 2 + ... + 201 + 2 + ... + 20 及及 1 + 2 + ... + 10001 + 2 + ... + 1000
各自寫一段程式,這就是函數的好處之各自寫一段程式,這就是函數的好處之
一。一。
62. 函數型別的陷阱函數型別的陷阱 ---- 比較例一比較例一
Function Mul(A%, B%) ' 將形式參數的型別宣告成整
數
Mul = A% * B%
End Function
? Mul(3.4, 5.9) ' 由於形式參數 A% 、 B% 都是整數
型別,
18 ' 所以 3.4 及 5.9 必須先將轉成整數,
' 再指定給 A% 、 B% 做運算,所以
3*6=18
63. 函數型別的陷阱函數型別的陷阱 ---- 比較例二比較例二
註註 :: MulMul 與與 Mul%Mul% 對對 VBVB 來說,是相同的名稱來說,是相同的名稱
,所以不能同時存在,因此當 要測試第二個您,所以不能同時存在,因此當 要測試第二個您
Mul%Mul% 函數時,請先把第一個函數時,請先把第一個 MulMul 函數刪除掉函數刪除掉
。。
Function Mul%(A, B) ' 將傳回值的型別宣告成整數
Mul = A * B
End Function
? Mul(3.4, 5.9) ' 直接將 3.4 及 5.9 指定給
A 、 B ,運算
20 ' 結果為 3.4*5.9=20.06 ,但傳回值為
整
' 數,所以須將 20.06 轉成整數再傳
回
64. 函數的型別函數的型別 ---- 實例練習實例練習 p.279p.279
寫一函數傳入寫一函數傳入 11 ~~ 1212 ,然後傳回對應的中文,然後傳回對應的中文
月份,例如傳入月份,例如傳入 88 即傳回 “八月”。即傳回 “八月”。
在以上函數中,如果傳入的參數不在在以上函數中,如果傳入的參數不在 11 ~~ 1212
的範圍內,則函數會傳回空字串的範圍內,則函數會傳回空字串 ("")("") 。。
Function ChineseMonthName(X) As String
ChineseMonthName = “”
M = Array(“ 一月” , “ 二月” , “ 三月” , “ 四月” , “ 五月 ", " 六月 ",
_ " 七月 ", " 八月 ", " 九月 ", " 十月 ", " 十一月 ", " 十二
月 ")
If X >= 1 And X <= 12 Then ChineseMonthName = M(X - 1)
End Function
68. 函數實例一函數實例一 (2)(2)
Year, Month,Year, Month, 及及 DayDay 函數函數
由於由於 PrintPrint 所印出的日期格式是所印出的日期格式是 1997/9/281997/9/28 ,親,親
和力較差,我們想把它印成中文格式。這時候和力較差,我們想把它印成中文格式。這時候
必須藉助必須藉助 VBVB 提供的三個日期函數:提供的三個日期函數:
函 數函 數 格 式格 式 功 用功 用
YearYear V=Year(D)V=Year(D) 傳入一日期傳入一日期 DD ,傳回「西元年」的,傳回「西元年」的
數值數值
MonthMonth V=Month(D)V=Month(D) 傳入一日期傳入一日期 DD ,傳回「月」數值,傳回「月」數值
DayDay V=Day(D)V=Day(D) 傳入一日期傳入一日期 DD ,傳回「日」數值,傳回「日」數值
69. 函數實例一函數實例一 (3)(3)
Year, Month,Year, Month, 及及 DayDay 函數的使函數的使
用用
這個幾函數的使用例如下:這個幾函數的使用例如下:
Dt = #9/28/97#
Y = Year(Dt)
M = Month(Dt)
D = Day(Dt)
Print Y ' 結果 =1997
Print M ' 結果 =9
Print D ' 結果 =28
70. 函數實例一函數實例一 (4)(4)
ChineseDateChineseDate 函數的撰寫函數的撰寫
瞭解瞭解 YearYear 、、 MonthMonth 、及、及 DayDay 函數的用法之函數的用法之
後,我們先寫一函數其功能是傳入日期資料,後,我們先寫一函數其功能是傳入日期資料,
傳回中文格式的日期:傳回中文格式的日期:
Function ChineseDate(Dt) As String
Y = Year(Dt)
M = Month(Dt)
D = Day(Dt)
If Y > 1911 Then
ChineseDate = " 民國 " & Y-1911 & " 年 " & M & " 月 " & D & " 日 "
Else
ChineseDate = " 民國前 " & 1911-Y+1 & " 年 " & M & " 月 " & D &
" 日 "
End If
End Function
72. 函數實例二函數實例二 (1)(1)
將字串將字串 "Windows""Windows" 印成:印成:
每次都將最左邊的字元移到最右邊
Wi ndows
i ndowsW
sWi ndow
wsWi ndo
owsWi nd
dowsWi n
ndowsWi
73. 函數實例二函數實例二 (2)(2)
Len, Left, RightLen, Left, Right 函數函數
這樣的程式會用到以下三個字串類的函數這樣的程式會用到以下三個字串類的函數
::
函函
數數
格 式格 式 功 用功 用
LenLen V=Len(S)V=Len(S) 傳回字串傳回字串 SS 的長度的長度
LeftLeft V=Left(S,n)V=Left(S,n) 傳回字串傳回字串 SS 左邊左邊 nn 個個
字元字元
RightRight V=Right(S,n)V=Right(S,n) 傳回字串傳回字串 SS 右邊右邊 nn 個個
字元字元
74. 函數實例二函數實例二 (3)(3)
Len, Left, RightLen, Left, Right 函數使用例函數使用例
例如以下是利用即時運算視窗執行的結果:例如以下是利用即時運算視窗執行的結果:
Print Len("Windows") ' 取長度
7
Print Left("Windows", 3) ' 取左邊 3 個
字元
Win
Print Right("Windows", 4) ' 取右邊 4 個
字元
dows
75. 函數實例二函數實例二 (4) --(4) -- 程式的寫法程式的寫法
而本程式的寫法是:而本程式的寫法是:
S = "Windows"
L = Len(S)
For I = 1 To L
Print S
' 以下敘述每次都將最左邊的字元移到最右
邊
S = Right(S, L-1) + Left(S, 1)
Next I
81. 遞迴呼叫的出口遞迴呼叫的出口 (2)(2)
這個副程式中的這個副程式中的 Exit SubExit Sub 敘述,功用和敘述,功用和 End SubEnd Sub 相同相同
,會執行返回動作,若執行,會執行返回動作,若執行 Call Recur(1)Call Recur(1) ,則印出,則印出 11 ,,
22 之後即可正常返回。之後即可正常返回。
以下以圖形來表示上述的遞迴流程:以下以圖形來表示上述的遞迴流程:
Sub Recur ( N )
I f N > 2 Then
Exi t Sub
End I f
Pr i nt N
Cal l Recur ( N+1)
End Sub
Sub Recur ( N )
I f N > 2 Then
Exi t Sub
End I f
Pr i nt N
Cal l Recur ( N+1)
End Sub
Sub Recur ( N )
I f N > 2 Then
Exi t Sub
End I f
Pr i nt N
Cal l Recur ( N+1)
End Sub
Cal l Recur ( 1)
N=1 N=2 N=3
呼叫
遞迴呼叫 遞迴呼叫
返回 返回
82. 遞迴呼叫的出口遞迴呼叫的出口 (3)(3)
如果遞迴呼叫中沒有如果遞迴呼叫中沒有 Exit SubExit Sub 的出口,但增的出口,但增
加 ‘是否遞迴呼叫的條件式’,也可以避免無窮加 ‘是否遞迴呼叫的條件式’,也可以避免無窮
盡的遞迴呼叫。盡的遞迴呼叫。
例如將上面的例子修改如下,也會得到相同的例如將上面的例子修改如下,也會得到相同的
結果:結果:
Sub Recur( N )
If N <= 2 Then ' 是否遞迴呼叫的條件式,
若
Debug.Print N ' 條件不成立,會跳
過 If 區
Call Recur(N+1) ' 塊,執行到 End
Sub 。
85. 遞迴函數二遞迴函數二 (1)(1)
寫一寫一 InverseInverse 函數將字串函數將字串 XX 顛倒過來,例顛倒過來,例
如將如將 "Hello""Hello" 顛倒成顛倒成 "olleH""olleH" ::
H e l l o
o H e l l+
Ri ght ( X, 1)Lef t ( X, Len( X) - 1)
殘餘部份,再遞迴 I nver se
86. 遞迴函數二遞迴函數二 (2)(2)
所以:所以:
當 Len( X) ≦ 1 時,I nver se( X) =
當 Len( X) >1 時,I nver se( X) =
X
Ri ght ( X, 1) +
I nver se( Lef t ( X, Len( X) - 1) )
對殘餘的部份再 I nver se 殘餘的部份