Download presentation
Presentation is loading. Please wait.
1
第7章 C#函數與.NET Framework類別函數庫
7-1 模組化程式設計 7-2 建立C#函數 7-3 函數的變數範圍 7-4 遞迴函數 7-5 NET Framework類別函數庫 7-6 DateTime日期時間類別 7-7 Math數學與Random亂數類別
2
7-1 模組化程式設計 7-1-1 模組的基礎 7-1-2 函數是一個黑盒子
3
7-1-1 模組的基礎 模組化是把大型功能切割成無數子功能,至於如何切割成一個個子功能的模組,屬於結構化分析的範疇,我們最常使用的是由上而下設計方法。 模組化程式設計是將大程式切割成一個個小程式。以C#語言來說,模組化的基本單位是函數,因為模組可大可小,可能只擁有單一程序或函數,也可能是整個子功能的函數庫。 不過,每一個函數都可以解決一個小問題,等到所以小問題都解決了,使用程序與函數堆積成的軟體系統或應用程式也就開發完成。
4
7-1-2 函數是一個黑盒子-說明 「函數」(Functions)就是將程式中常用的共同程式碼獨立成區塊,以便能夠重複呼叫這些函數的程式碼。一般來說,函數都有傳回值,如果函數沒有傳回值,稱為「程序」(Procedures)。 簡單的說,函數是一個程式區塊,執行函數稱為函數呼叫(Functions Call)。在呼叫函數時,我們並不需要了解函數內部實際的程式碼,事實上,也不需要知道其細節。函數如同是一個「黑盒子」(Black Box),只要告訴我們如何使用黑盒子的「使用介面」(Interface)即可。
5
7-1-2 函數是一個黑盒子-圖例 程式碼只知道呼叫程序/函數時,需要傳入的參數和取得傳回值。它是程序/函數和外部溝通的使用介面,一個對外的邊界,實際程式碼內容是隱藏在使用介面後,我們將程序/函數實際內容的程式碼撰寫稱為「實作」(Implementation)。
6
7-1-2 函數是一個黑盒子-撰寫規則 在使用程式語言撰寫程序/函數時,有一些規則可供參考,如下所示:
程序/函數的使用介面需要直接、良好定義和容易了解。 在呼叫程序/函數時,並不需要知道任何有關內部實作的問題,唯一需要知道的是如何使用它的使用介面。 在實作程序/函數時,並不用考量或知道到底是誰需要使用它,只需滿足使用介面定義的輸入參數和傳回值即可。
7
7-1-2 函數是一個黑盒子-語法與語意 程序/函數的「語法」(Syntax)是說明程序/函數需要傳入何種資料型態的「參數」(Parameters)和傳回值。 「語意」(Semantic)是指出程序/函數可以作什麼事?換句話說,在撰寫程序/函數時,需要了解其語法規則,而在使用程序/函數時需要了解其語意規則,如此才能正確呼叫函數。
8
7-2 建立C#函數 7-2-1 建立與呼叫函數 7-2-2 函數的參數列與傳回值 7-2-3 函數的參數傳遞方式
ViLLE – 4.1 建立與呼叫函數 7-2-2 函數的參數列與傳回值 ViLLE – 4.2 函數的參數列與傳回值 7-2-3 函數的參數傳遞方式 7-2-4 具名參數與選擇性參數
9
7-2 建立C#函數 C#函數是一個可以重複執行的程式區塊,在C#語言屬於類別的成員,稱為「方法」(Methods)。對於Windows應用程式來說,我們主要使用C#函數來建立控制項的事件處理程序和自訂功能的函數,其說明如下所示: 事件處理程序:事件處理程序是處理指定事件的程序(沒有傳回值的函數),在本章前的Windows應用程式已經使用Click事件處理程序。 自訂功能的函數:將程式區塊使用一個函數名稱來代替,以便呼叫函數來執行特定功能。
10
7-2-1 建立與呼叫函數-語法 C#函數是由函數名稱(或稱為方法名稱)和括號括起的程式碼區塊所組成,其語法如下所示:
修飾子 void 函數名稱() { 程式敘述; } 在上述函數宣告最前面的「修飾子」(Modifiers)可以宣告函數的存取範圍,其說明如下所示: public:指出函數可以在整個Visual C#專案的任何地方進行呼叫,甚至是其他類別,在第16章有進一步說明。 private:指出函數只能在宣告的同一個類別內進行呼叫。
11
7-2-1 建立與呼叫函數-範例 因為此函數並沒有傳回值,所以是void,在函數名稱後的括號可以定義傳入的參數列,如果函數沒有參數,就是空括號。例如:在標籤控制項顯示訊息文字的C#函數,如下所示: public void printTitle() { string msg; msg = "C#程式設計"; lblOutput.Text = msg + "\r\n"; }
12
7-2-1 建立與呼叫函數-呼叫函數 C#語言的函數呼叫需要使用函數名稱,其基本語法如下所示: 函數名稱();
因為printTitle()函數沒有傳回值和參數列,所以呼叫函數只需使用函數名稱和空括號,如下所示: printTitle();
13
7-2-1 建立與呼叫函數-Visual C#專案
Visual C#專案:Ch7_2_1 在Windows應用程式建立printTitle()和printAuthor()函數後,在事件處理程序呼叫這2個函數,如下圖所示:
14
7-2-1 建立與呼叫函數-函數的執行過程 C#程式是如何執行函數,以本節範例程式為例,程式是在button1_Click()事件處理程序的第3列呼叫printTitle()函數,此時程式碼執行順序就跳到printTitle()函數的第1列,在執行完第6列後返回呼叫點,如下圖所示:
15
ViLLE – 4.1 建立與呼叫函數 請啟動ViLLE,在【四. 函數】目錄下,選【1. 建立與呼叫函數】,按【Run】鈕模擬執行此範例程式,如下圖所示:
16
7-2-2 函數的參數列與傳回值- 函數的參數列(語法)
函數如果擁有參數列,在呼叫時就可以指定不同的參數值,換句話說,相同的函數可以得到不同的執行結果,其語法如下所示: [public | private] void 函數名稱(參數1, 參數2, …) { 程式敘述; } 上述函數括號內的參數稱為「正式參數」(Formal Parameters)或「假的參數」(Dummy Parameters),如果不只一個,請使用逗號分隔。正式參數是識別字,其角色如同變數,需要指定資料型態,而且可以在函數的程式區塊中使用。
17
7-2-2 函數的參數列與傳回值- 函數的參數列(範例)
例如:顯示重複訊息的函數,如下所示: public void printRepeatMsgs(string msg, int times) { int i; for (i = 1; i <= times; i++) { lblOutput.Text += msg + "\r\n"; } 上述函數擁有2個參數,因為參數不只一個,所以使用「,」符號分隔。
18
7-2-2 函數的參數列與傳回值- 函數的傳回值(語法)
C#函數開頭宣告的傳回值型別如果不是void,而是其他資料型別時,表示函數擁有傳回值,其基本語法如下所示: [public | private] 傳回值型別 函數名稱(參數1, 參數2, …) { 程式敘述; return 值 | 運算式; } 上述函數需要使用return關鍵字傳回一個值或運算式的運算結果,函數就是執行至return關鍵字為止。
19
7-2-2 函數的參數列與傳回值- 函數的傳回值(範例)
例如:溫度轉換函數,如下所示: public float convertTemperature(int c) { float f; f = (9.0F * c) / 5.0F F; return f; } 上述函數擁有1個參數c,可以將參數的攝氏溫度轉成華氏溫度,使用return關鍵字傳回華氏溫度。
20
7-2-2 函數的參數列與傳回值- 呼叫擁有參數和傳回值的函數(語法)
函數如果擁有參數,在呼叫時就需要指定參數列的參數值,其語法如下所示: 函數名稱( 參數列 ); 上述呼叫參數稱為「實際參數」(Actual Parameters),即參數值,它需要和正式參數定義的資料型態相同。換句話說,每一個正式參數都需對應相同型態的實際參數。
21
7-2-2 函數的參數列與傳回值- 呼叫擁有參數和傳回值的函數(範例)
例如:擁有參數的printRepeatMsgs()函數呼叫,如下所示: printRepeatMsgs("擁有參數的函數", 2); 上述函數呼叫傳入2個使用「,」符號分隔的參數字串和整數,可以顯示2次第1個參數msg的值。 函數如果擁有傳回值,在呼叫時就可以使用指定敘述來取得傳回值,如下所示: float temp; temp = convertTemperature(100);
22
7-2-2 函數的參數列與傳回值- Visual C#專案
Visual C#專案:Ch7_2_2 在Windows應用程式輸入顯示的字串和攝氏溫度後,按下按鈕,可以顯示多次重複字串和轉換的華氏溫度,如下圖所示:
23
ViLLE – 4.2 函數的參數列與傳回值 請啟動ViLLE,在【四. 函數】目錄下,選【2. 函數的參數列與傳回值】,按【Run】鈕模擬執行此範例程式,如下圖所示:
24
7-2-3 函數的參數傳遞方式-說明 函數的參數傳遞方式會影響到傳入參數值是否能夠變更,在C#函數共提供三種參數傳遞方式,如下表所示:
25
7-2-3 函數的參數傳遞方式- 範例(傳值呼叫)
C#函數預設使用傳值呼叫(Call by Value),所以並不需要特別宣告,如下所示: void byVal(int v) { ……… } 上述函數是傳值參數的byVal()函數。
26
7-2-3 函數的參數傳遞方式- 範例(傳址呼叫)
傳址呼叫的byRef()函數在宣告時,參數需要特別指名ref關鍵字,如下所示: void byRef(ref int v) { ………. } 上述函數是傳址呼叫(Call by Reference)的函數,所以參數使用ref來宣告。在呼叫傳址函數時,參數也需要指名ref關鍵字,如下所示: byRef(ref value);
27
7-2-3 函數的參數傳遞方式- 範例(傳出呼叫)
傳出呼叫的byOut()函數在宣告時,參數需要特別指名out關鍵字,如下所示: void byOut(out int v) { ………. } 上述函數是傳出呼叫(Call by Output)的函數,所以參數使用out來宣告。在呼叫傳址函數時,參數也需要指名out關鍵字,如下所示: byOut(out value);
28
7-2-3 函數的參數傳遞方式- Visual C#專案
Visual C#專案:Ch7_2_3 在Windows應用程式建立byVal()傳值、byRef()傳址和byOut()傳出三個函數,然後分別將參數值加1,按下按鈕測試呼叫byVal()、byRef()和byOut()後參數值的變化,如下圖所示:
29
7-2-4 具名參數與選擇性參數- 說明 「具名參數」(Named Parameters)可以替函數呼叫的參數取一個名稱,如此在傳遞參數時可以使用參數名稱來傳遞,而不需依據定義的參數順序。 「選擇性參數」(Optional Parameters)可以指定預設參數值,換句話說,如果在函數呼叫時沒有指定參數值,就是使用預設參數值。
30
7-2-4 具名參數與選擇性參數- 具名參數(範例)
例如:將3個參數加總的sum()函數,如下所示: public int sum(int a, int b, int c) { return a + b + c; } 上述函數擁有3個參數,如果使用具名參數,就可以先傳b,再傳c,最後傳入k,如下所示: result = sum(b: 2, c: 3, a: 1);
31
7-2-4 具名參數與選擇性參數- 選擇性參數(範例)
例如:計算盒子體積的volume()函數,如下所示: public int volume(int length, int width = 2, int height = 3) { return length * width * height; } volume()函數呼叫時沒有指定寬和高的參數,預設值就是2和3,只有長是一定需要的參數,函數呼叫如下所示: txtOutput.Text += "盒子體積: " + volume(l, w, h) + "\r\n"; txtOutput.Text += "盒子體積: " + volume(l, w) + "\r\n"; txtOutput.Text += "盒子體積: " + volume(l) + "\r\n";
32
7-2-4 具名參數與選擇性參數-Visual C#專案
Visual C#專案:Ch7_2_4 在Windows應用程式建立sum()和volume()二個函數,volume()函數的參數擁有預設值,然後使用具名參數呼叫sum()函數,和選擇性參數呼叫volume()函數,如下圖所示:
33
7-3 函數的變數範圍 7-3-1 變數範圍 7-3-2 全域變數的應用
34
7-3-1 變數範圍-說明 「變數範圍」(Scope)是當程式執行時,變數可以讓函數內或其他程式區塊存取的範圍。在C#函數宣告變數的有效範圍,也就是程式碼可以存取此變數的範圍,如下所示: 區域變數範圍(Local Scope):在函數內宣告的變數,只能在函數中使用,稱為區域變數。 全域變數範圍(Global Scope):如果變數是在函數外宣告,程式中的各函數都可以使用此變數,稱為全域變數。
35
7-3-1 變數範圍-Visual C#專案 Visual C#專案:Ch7_3_1
在Windows應用程式宣告全域和區域變數a、b,funcA()和funcB()函數都是將變數a設為3,變數b設為4,按下按鈕可以測試函數的變數範圍,如下圖所示:
36
7-3-2 全域變數的應用-說明 C#語言的全域變數可以儲存跨不同函數間的共享資料,或是在重複執行函數時保留一些所需的資料。
37
7-3-2 全域變數的應用-Visual C#專案
Visual C#專案:Ch7_3_2 在Windows應用程式建立熱門手機品牌的票選系統,只需選取選項按鈕後,按下按鈕即可參與票選,程式會記錄總投票人數和各手機廠牌的票數,如右圖所示:
38
7-4 遞迴函數 7-4-1 遞迴函數的基礎 7-4-2 遞迴的階層函數
39
7-4-1 遞迴函數的基礎 遞迴是由上而下分析方法的一種特殊的情況,使用遞迴觀念建立的函數稱為遞迴函數,其基本定義如下所示:
一個問題的內涵是由本身所定義的話,稱之為遞迴。 因為遞迴問題在分析時,其子問題本身和原來問題擁有相同特性,只是範圍改變,範圍逐漸縮小到終止條件,所以我們可以歸納出遞迴函數的兩個特性,如下所示: 遞迴函數在每次呼叫時,都可以使問題範圍逐漸縮小。 函數需要擁有終止條件,以便結束遞迴函數的執行。
40
7-4-2 遞迴的階層函數-說明 遞迴可以用來計算階層函數的值,階層函數N!,如下所示:
41
7-4-2 遞迴的階層函數-範例1 例如:計算4!階層函數的值,如下所示:
4!=4*3*2*1=24 因為階層函數本身擁有遞迴特性。我們可以將4!的計算分解成子問題,如下所示: 4!=4*(4-1)!=4*3! 現在3!的計算成為一個新的子問題,必須先計算出3!值後,才能處理上述的乘法。
42
7-4-2 遞迴的階層函數-範例2 同理將子問題3!繼續分解,如下所示: 最後我們知道1!的值為1,接著向上可以計算出2!~4!,如下所示:
3! = 3*(3-1)! = 3*2! 2! = 2*(2-1)! = 2*1! 1! = 1*(1-1)! = 1*0! = 1*1 = 1 最後我們知道1!的值為1,接著向上可以計算出2!~4!,如下所示: 2! = 2*(2-1)! = 2*1! = 2 3! = 3*(3-1)! = 3*2! = 3*2 = 6 4! = 4*(4-1)! = 4*3! = 24 上述階層函數中一層層的子問題都是一個階層函數,只是範圍改變逐漸縮小到終止條件。以階層函數為例是N=0。等到到達終止條件,階層函數值也就計算出來。
43
7-4-2 遞迴的階層函數-factorial(int n) 函數
public int factorial(int n) { if (n == 1) return 1; else return n * factorial(n - 1); }
44
7-4-2 遞迴的階層函數-Visual C#專案
Visual C#專案:Ch7_4_2 在Windows應用程式建立遞迴階層函數,只需輸入階層數,按下按鈕,可以計算指定階層數的階層函數值,如下圖所示:
45
7-5 .NET Framework類別函數庫 7-5-1 .NET Framework類別函數庫的基礎
7-5-2 Visual C#專案預設匯入的命名空間
46
7-5-1 .NET Framework類別函數庫的基礎-說明
「.NET Framework類別函數庫」(.NET Framework Class Library)提供很多功能強大的類別,我們可以直接在C#程式使用這個類別函數庫來輕鬆擴充程式的功能。 .NET Framework類別函數庫是一個龐大且良好組織架構的函數庫,各種.NET Framework支援的程式語言都可以使用相同的.NET Framework類別函數庫。例如:C#或Visual Basic 2010程式語言。
47
7-5-1 .NET Framework類別函數庫的基礎-圖例
.NET Framework類別函數庫的類別架構是使用稱為「命名空間」(Namespaces)的階層類別架構,System是最基礎的命名空間,其下擁有基本資料型態的System.Int32、System.Byte、System.Single和System.String等命名空間。
48
7-5-2 Visual C#專案預設匯入的命名空間- 主控台應用程式
在Visual C# Express建立專案時,專案預設會匯入一些命名空間,例如:System、System.Text和System.Collections.Generic等。請切換至Visual C#專案的程式碼視窗,可以在最上方看到使用using關鍵字匯入的命名空間,如下所示: using System; using System.Collections.Generic; using System.Linq; using System.Text;
49
7-5-2 Visual C#專案預設匯入的命名空間-Windows應用程式
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; 換句話說,為什麼我們可以在Visual C#專案建立圖形使用介面的控制項,就是因為匯入System.Windows.Forms命名空間。而Windows應用程式可以繪圖是因為匯入System.Drawing命名空間。
50
7-5-2 Visual C#專案預設匯入的命名空間- 自行匯入
對於專案預設匯入的命名空間,我們可以直接在C#程式碼使用此命名空間的類別,如果不屬於預設匯入的命名空間,就需要自行在程式碼以using關鍵字匯入所需的命名空間,如下所示: using 命名空間; 上述程式碼可以匯入指定的命名空間,如此在程式碼就可以使用此命名空間的類別。
51
7-6 DateTime日期時間類別-說明 .NET Framework的System.DateTime類別屬於System命名空間,此類別的方法與屬性可以取得電腦系統的日期與時間,和處理轉換成所需的日期與時間資料,如下所示: DateTime dt = new DateTime(2010,12,30,22,35,25); 上述程式碼使用DateTime()建構子(詳細說明請參閱第16章)和new運算子建立DateTime物件,參數依序是年、月、日、小時(24制)、分、千分之一秒。
52
7-6 DateTime日期時間類別-取得日期和時間
53
7-6 DateTime日期時間類別-調整日期與時間
54
7-6 DateTime日期時間類別-輸出日期與時間
DateTime物件提供的方法可以將DateTime物件轉換成完整、短日期、長日期、短時間和長時間的字串,相關方法如下表所示:
55
7-6 DateTime日期時間類別-Visual C#專案
Visual C#專案:Ch7_6 在Windows應用程式測試DateTime日期時間類別的相關方法與屬性,如下圖所示:
56
7-7 Math數學與Random亂數類別- System.Math數學類別(說明)
在.NET Framework的System命名空間提供數學常數、數學函數和亂數函數的Math和Random類別,可以讓我們在C#程式直接使用這些數學方法和產生亂數。 System.Math數學類別提供數學常數和各種數學函數的類別方法,因為是類別方法,所以在C#程式是直接使用類別名稱Math來呼叫方法(並不需要使用new運算子和建構子來建立物件),如下所示: Math.Sqrt(x); 上述Sqrt()方法可以計算平方根。
57
7-7 Math數學與Random亂數類別- System.Math數學類別(常數)
58
7-7 Math數學與Random亂數類別- System.Math數學類別(方法)
59
7-7 Math數學與Random亂數類別- System.Math數學類別(方法說明)
三角函數的參數單位是徑度(Radian),如果是角度(Degree),請乘以π/180將角度轉換成徑度,如下所示: double deg = 60.0; double rad = deg*Math.PI/180.0; 上述程式碼是將角度60轉換成徑度。
60
7-7 Math數學與Random亂數類別- System.Random亂數類別(說明)
在C#程式可以使用.NET Framework的System.Random類別來產生亂數。首先使用建構子來建立Random物件,如下所示: Random rd = new Random(); 上述程式碼使用建構子(詳細說明請參閱第16章)和new運算子建立Random物件後,就可以使用相關方法來產生亂數。
61
7-7 Math數學與Random亂數類別- System.Random亂數類別(方法)
62
7-7 Math數學與Random亂數類別- System.Random亂數類別(範例)
依序產生double值亂數和指定範圍的整數亂數,如下所示: o = "亂數值: " + rd.NextDouble() + "\r\n"; o += "亂數值1~50: " + rd.Next(1,50) + "\r\n"; o += "亂數值50~100: "+ rd.Next(50,100) +"\r\n";
63
7-7 Math數學與Random亂數類別- Visual C#專案
Visual C#專案:Ch7_7 在Windows應用程式測試Random亂數和Math類別的數學方法,如下圖所示:
64
End
Similar presentations