2012年10月29日 星期一

函數的介紹

今天來跟大家簡單介紹一下函數,函數的用途是什麼?通常我用它來做兩件事情。
1、會被重複使用的功能,獨立出來,做成函數。
2、當各種功能的程式碼都擠在同一個區塊的時候的時候,用函數將程式碼包起來,容易閱讀也比較好維護。

在開始寫程式碼之前,先講一下怎麼用函數。
函數與變數一樣,要使用前要先宣告,怎麼宣告?
基本的樣子就像這樣:【可見程度】【回傳型別】【變數名稱】小括弧中放【傳入的變數】後面加上大括弧放程式碼。
【可見程度】可以是【public】、【private】、【protected】。
【回傳型別】可以是任何一種【變數型態】,特別的是【void】,代表不回傳任何東西。
【傳入的變數】可以是任何一種變數型態,也可以不傳入參數。
【變數名稱】可以隨意取。

先來寫一個比數字大小的範例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UseFunction
{
    class Program
    {
        static void Main(string[] args)
        {
            string result = "";
            int[] SerialNumber = { 1, 2, 3 };
            int Max = 0;

            for (int i = 0; i < SerialNumber.Length; i++)
            {
                if (SerialNumber[i] > Max)
                    Max = SerialNumber[i];
            }
            result = "最大值:" + Max + "\r\n";
            Console.Write(result);
            Console.ReadKey();
        }
    }
}

上面的程式碼我們宣告了一個整數陣列,裡面放了一連串的數字,我想要得到這個數列的最大值,於是我另外宣告了一個整數變數【Max】來存放最大值,接著寫一個迴圈敘述來檢查每一個陣列裡面的元素,如果陣列裡面的元素比【Max】大,那麼就把【Max】的值換成陣列中的元素。

這邊有一個要注意的地方是整數變數【Max】的初始值,【Max】的初始值一定要比所有的陣列元素小,要不然這個判斷邏輯就失效了。

這時候你可能會問,又不一定每次都會知道所有元素的值,怎麼知道【Max】要設多少?不知道元素的話,保險的做法,就是把【Max】設為該型態的最小值,怎麼做?把【Max】的初始值換一下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UseFunction
{
    class Program
    {
        static void Main(string[] args)
        {
            string result = "";
            int[] SerialNumber = { 1, 2, 3 };
            int Max = int.MinValue;

            for (int i = 0; i < SerialNumber.Length; i++)
            {
                if (SerialNumber[i] > Max)
                    Max = SerialNumber[i];
            }
            result = "最大值:" + Max + "\r\n";
            Console.Write(result);
            Console.ReadKey();
        }
    }
}

好了,接下來我們再增加一個整數陣列,一樣要得到這個數列中的最大值,我們的程式碼可能會變成這樣。

 1
 2
 3
 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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UseFunction
{
    class Program
    {
        static void Main(string[] args)
        {
            string result = "";
            int[] SerialNumber = { 1, 2, 3 };
            int[] SerialNumber_1 = { 4, 5, 6, 7 };

            int Max = int.MinValue;
            for (int i = 0; i < SerialNumber.Length; i++)
            {
                if (SerialNumber[i] > Max)
                    Max = SerialNumber[i];
            }
            result = "最大值:" + Max + "\r\n";
            Console.Write(result);

            Max = int.MinValue;
            for (int i = 0; i < SerialNumber_1.Length; i++)
            {
                if (SerialNumber_1[i] > Max)
                    Max = SerialNumber_1[i];
            }
            result = "最大值:" + Max + "\r\n";
            Console.Write(result);
            
            Console.ReadKey();
        }
    }
}

大家有沒有發現,上面的程式碼有一部分是重複的,就是取得陣列元素中最大值的那段邏輯,只有陣列名稱換成【SerialNumber_1】,其他的都一樣,我們來把這段程式變成函數。

 1
 2
 3
 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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UseFunction
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] SerialNumber = { 1, 2, 3 };
            int[] SerialNumber_1 = { 4, 5, 6, 7 };

            GetMax(SerialNumber);
            GetMax(SerialNumber_1);
            Console.ReadKey();
        }

        private static void GetMax(int[] InputSerialNumber)
        {            
            string result = "";
            int Max = int.MinValue;
            for (int i = 0; i < InputSerialNumber.Length; i++)
            {
                if (InputSerialNumber[i] > Max)
                    Max = InputSerialNumber[i];
            }
            result = "最大值:" + Max + "\r\n";
            Console.Write(result);
        }
    }
}

我們宣告了一個函數,可見層級是【private】,【static】這個先照抄,這邊不解釋,回傳型態是【void】 表示這個函數不會回傳任何東西,接著是函數名稱我們取名為【GetMax】,小括弧裡面放 【int[] InputSerialNumber】,代表我們要傳遞一個整數陣列進去給函數使用,傳遞進去的陣列的名稱為【InputSerialNumber】,大括弧裡裡面放的程式碼就是如何取得數列最大值的邏輯。

我們將取得數列最大值的邏輯獨立出來變成函數,要取得的最大值的數列只要呼叫【GetMax】函數,並把數列傳遞進去,函數會處理有關取得最大值的邏輯,看起來是不是簡潔許多,程式碼也比較方便閱讀與維護。

我們上面的範例改一下,示範一下有回傳資料的函數怎麼使用。

 1
 2
 3
 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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UseFunction
{
    class Program
    {
        static void Main(string[] args)
        {         
            int[] SerialNumber = { 1, 2, 3 };
            int[] SerialNumber_1 = { 4, 5, 6, 7 };

            string result = "";
            result = "最大值:" + GetMax(SerialNumber) + "\r\n";
            Console.Write(result);

            result = "最大值:" + GetMax(SerialNumber_1) +"\r\n";
            Console.Write(result);

            Console.ReadKey();
        }

        private static int GetMax(int[] InputSerialNumber)
        { 
            int Max = int.MinValue;
            for (int i = 0; i < InputSerialNumber.Length; i++)
            {
                if (InputSerialNumber[i] > Max)
                    Max = InputSerialNumber[i];
            }
            return Max;        
        }
    }
}

這邊我們修改了一點程式碼,本來回傳型態【void】改為【int】,並且在函數區塊的最後加上【return】代表要回傳【Max】這個變數的值。

提醒各位,函數可以選擇要回傳會者是不回傳,要回傳也只能回傳一個變數,但是總有些辦法變通的辦法。

如果你去水果行買東西,只剩下一隻手可以拿東西,老闆只能拿一個東西給你,如果你要買同種類的水果很多,老闆可能給你水果禮盒或一整箱未拆封水果,如果你要買梨子蘋果柳丁等都不一樣的水果,老闆會拿塑膠袋全部裝一起給你。

同一種水果很多個的水果禮盒就是List,而裝著各種不同水果的塑膠袋就是【類別】或【結構】,List前面文章介紹過了,這兩個東西說以後會介紹,今天就先到這,改天見。

2012年10月24日 星期三

Array與List

今天來跟大家簡單的介紹一下Array與List,這兩個東西可是程式設計師常用的東西之一,有甚麼用?要怎麼用?Array與List都是變數的一種,差異在於,Array和List可以放很多東西,而之前提過的變數只能放一個東西,不明白!沒關係,我們邊看程式碼邊解釋。

首先登場的是Array,怎麼宣告Array?我們開頭就先說明Array可以放很多東西,所以宣告的時候,就要先說明裡面要放很多【什麼型態】的東西,還有要放幾個。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Array_and_List
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] DayOfWeek = new string[7];
        }
    }
}

上面我們宣告了一個要放很多個【string】的Array,變數名稱是【DayOfWeek】,這個Array總共要放【7】個【string】型態的東西。 我們把Array變數【DayOfWeek】宣告好了,接下來要怎麼用?我們來把Array裡面要放的東西放進去。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Array_and_List
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] DayOfWeek = new string[7];
            DayOfWeek[0] = "星期一";
            DayOfWeek[1] = "星期二";
            DayOfWeek[2] = "星期三";
            DayOfWeek[3] = "星期四";
            DayOfWeek[4] = "星期五";
            DayOfWeek[5] = "星期六";
            DayOfWeek[6] = "星期日";
        }
    }
}

使用的方法就像上面的程式碼中看到的,變數名稱加上中括號[],中括號中的數字代表索引值,你就可以把資料放進你指定的位置。

上面的程式碼,指定【索引值0】的位置放入字串【星期一】,【索引值1】的位置放入字串【星期二】......直到【索引值6】的位置放入字串【星期日】。

當然,如果你一開始要宣告Array的時候就知道裡面要按照順序放什麼東西,你也可以這樣宣告。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Array_and_List
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] DayOfWeek = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };
        }
    }
}

那List勒,List怎麼宣告?怎麼用?我們先把Array那部份打上【註解】,表示程式不執行該行,接著我們增加一些程式碼,由於List也是可以放很多東西,於是我們一樣要先說明要放進去的【變數型態】,跟Array不一樣的是,List不需要指定放入的個數。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Array_and_List
{
    class Program
    {
        static void Main(string[] args)
        {
            //string[] DayOfWeek = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };
            List<string> DayOfWeek = new List<string>();
        }
    }
}

上面我們宣告了一個List變數,變數名稱【DayOfWeek】,接著我們來將資料放入List中。

 1
 2
 3
 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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Array_and_List
{
    class Program
    {
        static void Main(string[] args)
        {
            //string[] DayOfWeek = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };        
            List<string> DayOfWeek = new List<string>();
            DayOfWeek.Add(null);
            DayOfWeek.Add(null);
            DayOfWeek.Add(null);
            DayOfWeek.Add(null);
            DayOfWeek.Add(null);
            DayOfWeek.Add(null);
            DayOfWeek.Add(null);

            DayOfWeek[0] = "星期一";
            DayOfWeek[1] = "星期二";
            DayOfWeek[2] = "星期三";
            DayOfWeek[3] = "星期四";
            DayOfWeek[4] = "星期五";
            DayOfWeek[5] = "星期六";
            DayOfWeek[6] = "星期日";       
        }
    }
}

我們看到上面的程式碼,List使用前必須要先透過【Add()】方式將資料加入List中,之後一樣可以透過變數名稱加中括弧[]與索引值來指定資料。

好了,看到這裡,你也許會有疑問,為什麼List要先加入東西之後才能用?其實是因為Array在宣告的時候,就自動幫你填入預設值,不需要你處理。

接著你就會開始疑惑,這兩個東西看起來差不多,到底差別在哪?

1、Array使用連續記憶體空間,List【不需要】使用連續記憶體空間。
連續記憶體空間是什麼意思?比方說你要蓋五棟房子,連續記憶體空間代表你要找一個塊夠大的地,可以讓你五棟房子都蓋在一起,在都市應該很難找,到鄉下比較有機會,不使用連續記憶體空間代表代表你只要找到五塊空地,就可以蓋五棟房子,並不要求一定要蓋在一起。

使用連續記憶體空間始有風險的,因為記憶體一直不斷的在存放資料刪除資料,記憶體空間看起來還不少,但很有可能都是零碎的記憶體空間,有時候在宣告比較大的Array的時候會失敗,因為連續記憶體空間不夠。

2、Array輪循速度比較快,List輪循速度比較慢。
以上面蓋房子的例子來說,Array要走過所有房子很快,因為都蓋在一起,但是List就不一樣了,因為房子不一定蓋在一起,所以要走過所有房子就要花比較多的時間。

3、Array無法新增或刪除其中的元素,List可以。
Array因為房子都蓋在一起,一開始就設計好了,沒辦法中間插進去一棟或者是敲掉其中一棟,再把其他棟移過來,但是List因為房子都沒有蓋在一起,所以要增加或減少房子都沒問題。

這邊只能簡單的介紹Array和List,其實他們各自都還有很多東西可以研究,比方說Atrray可以反轉,可以比較其中的元素是否相同......而今天介紹的List其實只是【集合】中的一員,這些之後都會陸陸續續出現,等不及的可以先到MSDN上查詢相關資料,有任何問題歡迎提出來討論,今天就到這了,改天見。

2012年10月22日 星期一

綜合練習-簡易提款機

我們今天來練習寫一個簡易提款機的程式,這個程式的程式碼稍多,不過不用擔心,我們一步一步來。

電腦說穿了其實只是運算速度飛快,它什麼都不會做,要怎麼做是你要教他做,你跟它說怎麼做它就照著做。

讓我們先來想想,我們平常怎麼操作提款機。先決條件是要有某個銀行帳戶,然後才能去提款機,輸入帳號密碼後選擇要提款、存款、轉帳還是繳卡費等等功能,執行完一個功能會問你是否要繼續操作,沒有要繼續操作的話就退出系統,我的印象跟大家應該沒有不一樣吧!

有了上述的操作經驗,現在我們來定義一下簡易提款機的重點。

必要條件:
銀行帳戶。

功能:
1查詢餘額 2提款
3存款
流程:
1進入系統
2選擇功能
3執行功能
4是否離開

有了這些重點,就讓我們開始打造程式吧!!

開一個新專案,先把必要條件寫上去。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
        }
    }
}

接下來是提款機的功能部分,在處理提款機功能之前,我們先定義一個字串變數【Message】來存放操作訊息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";
        }
    }
}

接著我們開始處理提款機功能的部分,首先是顯示選單的部分。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";

            //功能
            Message = "【查詢餘額】請按【1】" + "\r\n";
            Message += "【提款】請按【2】" + "\r\n";
            Message += "【存款】請按【3】" + "\r\n";
            Console.Write(Message);
            Console.ReadKey();
        }
    }
}

選單做好了,接下來要跟各位介紹一個大家很熟悉卻又很陌生的函數【Console.ReadKey()】,平常都用它來停住畫面,前面文章也介紹過它的功能是擷取鍵盤上任一個按下的按鍵,這邊他要正式登場囉,不再只是用來停住畫面。

【Console.ReadKey()】會擷取鍵盤上任一個按下的按鍵,並回傳給你究竟是哪個按鍵被按下去,要怎麼做到這件事情,繼續往下看。

 1
 2
 3
 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
38
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";

            //功能
            Message = "【查詢餘額】請按【1】" + "\r\n";
            Message += "【提款】請按【2】" + "\r\n";
            Message += "【存款】請按【3】" + "\r\n";
            Console.Write(Message);
            switch (Console.ReadKey().Key)
            {
                case ConsoleKey.D1:
                    { }
                    break;
                case ConsoleKey.D2:
                    { }
                    break;
                case ConsoleKey.D3:
                    { }
                    break;
                default:
                    { }
                    break;
            }
        }
    }
}

這邊用了【switch...case】來做為判斷,因為提款機的功能有很多,為了簡化程式我這邊只列出三項功能,其他的功能你可以自己試著加進去。

另外,【ConsoleKey】這裡面放了所有鍵盤的對應碼,所以【ConsoleKey.D1】意味著式鍵盤上的【1】,你可以把滑鼠移到【ConsoleKey.D1】停留一下就會看到說明,後面的【ConsoleKey.D2】以及【ConsoleKey.D3】應該就不難理解了吧!

由於上面的程式碼case裡面的的程式碼區塊是空的,意味著你按下任何按鍵都不會有任何作用,接著程式就關閉,為了測試程式是否有正確擷取到按鍵,我們在【case】的區塊中填入一些測試程式碼。

 1
 2
 3
 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
38
39
40
41
42
43
44
45
46
47
48
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";

            //功能
            Message = "【查詢餘額】請按【1】" + "\r\n";
            Message += "【提款】請按【2】" + "\r\n";
            Message += "【存款】請按【3】" + "\r\n";
            Console.Write(Message);
            switch (Console.ReadKey().Key)
            {
                case ConsoleKey.D1:
                    {
                        Message = "這是按鍵1" + "\r\n";
                    }
                    break;
                case ConsoleKey.D2:
                    {
                        Message = "這是按鍵2" + "\r\n";
                    }
                    break;
                case ConsoleKey.D3:
                    {
                        Message = "這是按鍵3" + "\r\n";
                    }
                    break;
                default:
                    {
                        Message = "你按的按鍵是123以外的按鍵" + "\r\n";
                    }
                    break;
            }
            Console.Write(Message);
            Console.ReadKey();
        }
    }
}

到這邊你可以【重新編譯】一下並執行【開始偵錯】跑跑看程式是不是有如預期的行為,按下123或其他按鍵應該都會得到程式的回應。

接下來我們開始一一補齊各功能的程式碼,首先是【餘額查詢】,還記得我們在一開始就宣告了帳戶金額的變數嗎?這邊只要把帳戶金額變數顯示在畫面上就行了。

 1
 2
 3
 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
38
39
40
41
42
43
44
45
46
47
48
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";

            //功能
            Message = "【查詢餘額】請按【1】" + "\r\n";
            Message += "【提款】請按【2】" + "\r\n";
            Message += "【存款】請按【3】" + "\r\n";
            Console.Write(Message);
            switch (Console.ReadKey().Key)
            {
                case ConsoleKey.D1:
                    {
                        Message = "您的帳戶餘額為【" + AccountMoneny + "】元" + "\r\n";
                    }
                    break;
                case ConsoleKey.D2:
                    {
                        Message = "這是按鍵2" + "\r\n";
                    }
                    break;
                case ConsoleKey.D3:
                    {
                        Message = "這是按鍵3" + "\r\n";
                    }
                    break;
                default:
                    {
                        Message = "你按的按鍵是123以外的按鍵" + "\r\n";
                    }
                    break;
            }
            Console.Write(Message);
            Console.ReadKey();
        }
    }
}

【餘額查詢】就這麼簡單,接著要處理的功能是【提款】,我們操作提款機的時候,首先是輸入提款金額,如果餘額足夠,那就會順利領到錢,如果餘額不足,系統會跟你說餘額不足,讓我們把這個功能實踐在這個程式裡面。

這邊另外會看到兩個新東西,一個是【Convert】,另一個是【Console.ReadLine()】。

【Convert】以後也是經常使用的東西,用來處理型態轉換,比方說字串變數轉整數型態,字串變數轉浮點數型態......。

而【Console.ReadLine()】則是與【 Console.ReadKey()】的功能相近,差別在於使用【Console.ReadLine()】可以輸入一整行的資料,直到你按下【enter】按鍵才開始截取按下【enter】以前輸入的所有資料,而【 Console.ReadKey()】是擷取你當下按的按鍵。

讓我們來看看【提款】這段程式碼長的什麼樣子。

 1
 2
 3
 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";

            //功能
            Message = "【查詢餘額】請按【1】" + "\r\n";
            Message += "【提款】請按【2】" + "\r\n";
            Message += "【存款】請按【3】" + "\r\n";
            Console.Write(Message);
            switch (Console.ReadKey().Key)
            {
                case ConsoleKey.D1:
                    {
                        //餘額查詢
                        Message = "您的帳戶餘額為【" + AccountMoneny + "】元" + "\r\n";
                    }
                    break;
                case ConsoleKey.D2:
                    {
                        //提款
                        Message = "請輸入提款金額:";
                        Console.Write(Message);
                        int Input = Convert.ToInt32(Console.ReadLine());
                        if (AccountMoneny - Input >= 0)
                        {
                            AccountMoneny = AccountMoneny - Input;
                        }
                        else
                        {
                            Message = "餘額不足" + "\r\n";
                        }                       
                    }
                    break;
                case ConsoleKey.D3:
                    {
                        Message = "這是按鍵3" + "\r\n";
                    }
                    break;
                default:
                    {
                        Message = "你按的按鍵是123以外的按鍵" + "\r\n";
                    }
                    break;
            }
            Console.Write(Message);
            Console.ReadKey();
        }
    }
}

我們透過【Console.ReadLine()】得到一串金額的文字,經過【Convert.ToInt32()】函數將金額的文字轉換成整數存放到變數【Input】裡面,再與帳戶金額做運算,如果帳戶金額扣掉變數【Input】大於等於0,意味著帳戶餘額足夠,如果帳戶金額扣掉變數【Input】小於0,則意味著帳戶餘額不夠。

剩下還沒處理的功能是【存款】,實踐【存款】功能的程式碼就簡單的多,只要把帳戶金額加上輸入的數字就搞定了。

 1
 2
 3
 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
38
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";

            //功能
            Message = "【查詢餘額】請按【1】" + "\r\n";
            Message += "【提款】請按【2】" + "\r\n";
            Message += "【存款】請按【3】" + "\r\n";
            Console.Write(Message);
            switch (Console.ReadKey().Key)
            {
                case ConsoleKey.D1:
                    {
                        //餘額查詢
                        Message = "您的帳戶餘額為【" + AccountMoneny + "】元" + "\r\n";
                    }
                    break;
                case ConsoleKey.D2:
                    {
                        //提款
                        Message = "請輸入提款金額:";
                        Console.Write(Message);
                        int Input = Convert.ToInt32(Console.ReadLine());
                        if (AccountMoneny - Input >= 0)
                        {
                            AccountMoneny = AccountMoneny - Input;
                        }
                        else
                        {
                            Message = "餘額不足" + "\r\n";
                        }                       
                    }
                    break;
                case ConsoleKey.D3:
                    {
                        //存款
                        Message = "請輸入存款金額:";
                        Console.Write(Message);
                        int Input = Convert.ToInt32(Console.ReadLine());
                        AccountMoneny = AccountMoneny + Input;
                    }
                    break;
                default:
                    {
                        Message = "你按的按鍵是123以外的按鍵" + "\r\n";
                    }
                    break;
            }
            Console.Write(Message);
            Console.ReadKey();
        }
    }
}

最後還有一個地方需要補齊一下程式碼,就是不是按下123鍵的處理,我們修改一下顯示內容就好了。

 1
 2
 3
 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
38
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";

            //功能
            Message = "【查詢餘額】請按【1】" + "\r\n";
            Message += "【提款】請按【2】" + "\r\n";
            Message += "【存款】請按【3】" + "\r\n";
            Console.Write(Message);
            switch (Console.ReadKey().Key)
            {
                case ConsoleKey.D1:
                    {
                        //餘額查詢
                        Message = "您的帳戶餘額為【" + AccountMoneny + "】元" + "\r\n";
                    }
                    break;
                case ConsoleKey.D2:
                    {
                        //提款
                        Message = "請輸入提款金額:";
                        Console.Write(Message);
                        int Input = Convert.ToInt32(Console.ReadLine());
                        if (AccountMoneny - Input >= 0)
                        {
                            AccountMoneny = AccountMoneny - Input;
                        }
                        else
                        {
                            Message = "餘額不足" + "\r\n";
                        }                       
                    }
                    break;
                case ConsoleKey.D3:
                    {
                        //存款
                        Message = "請輸入存款金額:";
                        Console.Write(Message);
                        int Input = Convert.ToInt32(Console.ReadLine());
                        AccountMoneny = AccountMoneny + Input;
                    }
                    break;
                default:
                    {
                        Message = "本提款機沒有此功能選項" + "\r\n";
                    }
                    break;
            }
            Console.Write(Message);
            Console.ReadKey();
        }
    }
}

好了,到這邊目前為止功能大致上都完成了,剩下一個功能,就是【是否離開】這個功能,我們在操作提款機的時候,如果你提款完成都會問你是否要繼續操作,如果要繼續操作,就會又回到估能選單,怎麼實踐這個功能?那就要用到我們之前講過的迴圈敘述【while】。

要怎麼做?先試試看寫一個【while】敘述,並把實踐提款機功能的那些程式碼搬進【while】敘述裡面,然後【while】的判斷式不寫,只填入【true】,什麼!!判斷式可以不寫,而且為蝦米要填入【true】?這個稍後解釋,先看程式碼。

 1
 2
 3
 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
38
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";

            while (true)
            {
                //功能
                Message = "【查詢餘額】請按【1】" + "\r\n";
                Message += "【提款】請按【2】" + "\r\n";
                Message += "【存款】請按【3】" + "\r\n";
                Console.Write(Message);
                switch (Console.ReadKey().Key)
                {
                    case ConsoleKey.D1:
                        {
                            //餘額查詢
                            Message = "您的帳戶餘額為【" + AccountMoneny + "】元" + "\r\n";
                        }
                        break;
                    case ConsoleKey.D2:
                        {
                            //提款
                            Message = "請輸入提款金額:";
                            Console.Write(Message);
                            int Input = Convert.ToInt32(Console.ReadLine());
                            if (AccountMoneny - Input >= 0)
                            {
                                AccountMoneny = AccountMoneny - Input;
                            }
                            else
                            {
                                Message = "餘額不足" + "\r\n";
                            }
                        }
                        break;
                    case ConsoleKey.D3:
                        {
                            //存款
                            Message = "請輸入存款金額:";
                            Console.Write(Message);
                            int Input = Convert.ToInt32(Console.ReadLine());
                            AccountMoneny = AccountMoneny + Input;
                        }
                        break;
                    default:
                        {
                            Message = "本提款機沒有此功能選項" + "\r\n";
                        }
                        break;
                }
                Console.Write(Message);
                Console.ReadKey();
            }          
        }
    }
}

【重新編譯】一下程式碼執行看看,原本執行程式碼跑完一次流程就結束了,要重新進入選單就要重新執行一次程式,現在不用重執行程式碼就可以重新跑整個提款機流程,但是問題來了,怎麼結束程式?好像不管按蝦米按鍵都沒辦法結束程式,妳只好先按右上角的X強制結束程式,怎麼會這樣?

我來解釋一下,關鍵在於【while】敘述的判斷式,我們沒有填入任何判斷式,只填入【true】,造成【無限迴圈】的現象,什麼是【無限迴圈】意思就是迴圈沒有終止條件,會一直執行下去。所以,現在【while】迴圈解決了重複跑提款機流程的問題,卻產生無法結束的問題?怎麼辦!!

讓我們來修改一下【while】迴圈的判斷式,要怎麼修改?想法是這樣的,當我們按下某一個特定的按鍵,就讓【while】迴圈終止,怎麼做?繼續往下看。

 1
 2
 3
 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
38
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";
            bool Exist = false;

            while (!Exist)
            {
                //功能
                Message = "【查詢餘額】請按【1】" + "\r\n";
                Message += "【提款】請按【2】" + "\r\n";
                Message += "【存款】請按【3】" + "\r\n";
                Console.Write(Message);
                switch (Console.ReadKey().Key)
                {
                    case ConsoleKey.D1:
                        {
                            //餘額查詢
                            Message = "您的帳戶餘額為【" + AccountMoneny + "】元" + "\r\n";
                        }
                        break;
                    case ConsoleKey.D2:
                        {
                            //提款
                            Message = "請輸入提款金額:";
                            Console.Write(Message);
                            int Input = Convert.ToInt32(Console.ReadLine());
                            if (AccountMoneny - Input >= 0)
                            {
                                AccountMoneny = AccountMoneny - Input;
                            }
                            else
                            {
                                Message = "餘額不足" + "\r\n";
                            }
                        }
                        break;
                    case ConsoleKey.D3:
                        {
                            //存款
                            Message = "請輸入存款金額:";
                            Console.Write(Message);
                            int Input = Convert.ToInt32(Console.ReadLine());
                            AccountMoneny = AccountMoneny + Input;
                        }
                        break;
                    default:
                        {
                            Message = "本提款機沒有此功能選項" + "\r\n";
                        }
                        break;
                }
                Console.Write(Message);
                Message = "你是否要離開此系統?(y/n):";
                Console.Write(Message);
                if (Console.ReadKey().Key == ConsoleKey.Y)
                    Exist = true;
            }          
        }
    }
}

我們修改了一些程式碼,在必要條件那邊另外宣告一個布林變數【Exist】,初始值設定為【false】,由他控制【while】迴圈是否要終止,另外,【while】敘述的【判斷式】由【true】改為【!Exist】,最後是在提款機功能結束後加入訊息詢問使用者是否要離開系統,並由【Console.ReadKey()】擷取使用者輸入的按鍵判斷是否要離開系統。

好了,簡易提款機終於完成了,美中不足的是,每次重新跑流程的時候,顯示的訊息都會跟之前的訊息混在同一行,怎麼解決?聰明的你應該知道吧!

 1
 2
 3
 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
38
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_2
{
    class Program
    {
        static void Main(string[] args)
        {
            //必要條件
            int AccountMoneny = 0;
            string Message = "";
            bool Exist = false;

            while (!Exist)
            {
                Console.Clear();
                //功能
                Message = "【查詢餘額】請按【1】" + "\r\n";
                Message += "【提款】請按【2】" + "\r\n";
                Message += "【存款】請按【3】" + "\r\n";
                Console.Write(Message);
                switch (Console.ReadKey().Key)
                {
                    case ConsoleKey.D1:
                        {
                            //餘額查詢
                            Message = "您的帳戶餘額為【" + AccountMoneny + "】元" + "\r\n";
                        }
                        break;
                    case ConsoleKey.D2:
                        {
                            //提款
                            Message = "請輸入提款金額:";
                            Console.Write(Message);
                            int Input = Convert.ToInt32(Console.ReadLine());
                            if (AccountMoneny - Input >= 0)
                            {
                                AccountMoneny = AccountMoneny - Input;
                            }
                            else
                            {
                                Message = "餘額不足" + "\r\n";
                            }
                        }
                        break;
                    case ConsoleKey.D3:
                        {
                            //存款
                            Message = "請輸入存款金額:";
                            Console.Write(Message);
                            int Input = Convert.ToInt32(Console.ReadLine());
                            AccountMoneny = AccountMoneny + Input;
                        }
                        break;
                    default:
                        {
                            Message = "本提款機沒有此功能選項" + "\r\n";
                        }
                        break;
                }
                Console.Write(Message);
                Message = "你是否要離開此系統?(y/n):";
                Console.Write(Message);
                if (Console.ReadKey().Key == ConsoleKey.Y)
                    Exist = true;
            }          
        }
    }
}

什麼??做法跟你想的不一樣,這是一定的,因為畢竟資歷比你深一點點,今天最後要介紹的是【 Console.Clear()】,這個函數是用來清除畫面資料的,我把它寫在【while】敘述第一行,意味著每次【while】迴圈重新執行的時候,都會先把畫面清除,再開始顯示功能選單,於式介面就變得乾乾淨淨囉,今天就到這裡了,改天見。

2012年10月18日 星期四

綜合練習-九九乘法

這幾天一直想要找怎麼把圖片貼到部落格上的方法,找了好久感覺都不方便,暫時放棄貼圖的想法,先寫一篇九九乘法的範例吧。

之前幾篇文章談論了有關變數宣告、邏輯判斷與迴圈敘述,今天就來練習一下怎麼寫九九乘法的程式。

讓我們先開一個新專案,接著回想一下小時後背的九九乘法表:
2 x 1 = 2
2 x 2 = 4
.
.
.
.
.
9 x 8 = 72
9 x 9 = 81
以2開頭系列為例,第一個數字是固定的2,第二個數字是變動的,要怎麼用迴圈達到效果呢?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_1
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 1; i <= 9; i++)
            {
                string result = "2" + " x " + i + " = " + 2 * i;
                Console.Write(result + "\r\n");
            }
            Console.ReadKey();
        }
    }
}

用迴圈敘述顯示出2開頭系列是不是很容易!那麼接下來3系列、4系列.......9系列,應該知道怎麼做了吧!

 1
 2
 3
 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
38
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_1
{
    class Program
    {
        static void Main(string[] args)
        {
            //2開頭
            for (int i = 1; i <= 9; i++)
            {
                string result = "2" + " x " + i + " = " + 2 * i;
                Console.Write(result + "\r\n");
            }
            //3開頭
            for (int i = 1; i <= 9; i++)
            {
                string result = "3" + " x " + i + " = " + 3 * i;
                Console.Write(result + "\r\n");
            }
            //4開頭
            for (int i = 1; i <= 9; i++)
            {
                string result = "4" + " x " + i + " = " + 4 * i;
                Console.Write(result + "\r\n");
            }
            //5開頭
            for (int i = 1; i <= 9; i++)
            {
                string result = "5" + " x " + i + " = " + 5 * i;
                Console.Write(result + "\r\n");
            }
            //6開頭
            for (int i = 1; i <= 9; i++)
            {
                string result = "6" + " x " + i + " = " + 6 * i;
                Console.Write(result + "\r\n");
            }
            //7開頭
            for (int i = 1; i <= 9; i++)
            {
                string result = "7" + " x " + i + " = " + 7 * i;
                Console.Write(result + "\r\n");
            }
            //8開頭
            for (int i = 1; i <= 9; i++)
            {
                string result = "8" + " x " + i + " = " + 8 * i;
                Console.Write(result + "\r\n");
            }
            //9開頭
            for (int i = 1; i <= 9; i++)
            {
                string result = "9" + " x " + i + " = " + 9 * i;
                Console.Write(result + "\r\n");
            }
            Console.ReadKey();
        }
    }
}


是不是很容易,我們今天的目的,九九乘法表就完成了。但是,從程式設計的原則來看,還有進步的空間,怎麼說?

第一點,重複的程式法太多了,怎麼修改?
注意看這些程式碼你會發現兩件事情,第一件事情是每段程式碼【差別只有一個字串與一個整數】,第二件事情是差別的部分竟然是【有規則的數列】,於是開始想,是不是有可能再用一個迴圈來替代【有規則的數列】的這件事情,讓我們來試試看。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_1
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int j = 2; j <= 9; j++)
            {
                //2開頭
                for (int i = 1; i <= 9; i++)
                {
                    string result = j + " x " + i + " = " + j * i;
                    Console.Write(result + "\r\n");
                }
            }
            Console.ReadKey();
        }
    }
}

修改了一下程式碼,增加了一個迴圈在2開頭程式碼的外面,把差異的兩個部分字串【"2"】與整數【2】替換成最外面迴圈宣告的變數【j】,運行結果與之前程式碼相同,程式碼是不是簡潔許多。

在這邊如果龜毛一點的人或許會覺得,這個排版醜死了,我想要漂亮一點的,至少要像這樣:
2 x 1 = 2 3 x 1 = 3 4 x 1 = 4.......
2 x 2 = 4 3 x 2 = 6 4 x 2 = 8.......
.
.
.
.
.
.
2 x 8 = 16 3 x 8 = 24 4 x 8 = 32.......
2 x 9 = 18 3 x 9 = 27 4 x 9 = 36.......
怎麼辦,這就要靠一些小技巧了,記得我說過【Console.Write()】這個函數比較彈性這句話嗎,這邊要來展現他的彈性了,我們把上面的程式碼稍微修改一下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_1
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int j = 2; j <= 9; j++)
            {
                //2開頭
                for (int i = 1; i <= 9; i++)
                {
                    string result = j + " x " + i + " = " + j * i + "  ";
                    Console.Write(result);
                }
                Console.Write("\r\n");
            }
            Console.ReadKey();
        }
    }
}

上面的程式只做了點小修改:
1、在字串變數【result】最後加上" ",作用是區隔開前面的字串。
2、把換行符號【\r\n】移到內迴圈執行完才作用。

讓我們從頭到尾看一次程式碼邏輯。

Step1、進入外迴圈,並宣告變數【j】,給予初始值2,【判斷式】【j<=9】,變動規則為【j+1】。
這個外迴圈控制的是九九乘法中第一個數字,所以由2開始。

Step2、檢查【判斷式】【j<=9】是否【成立】,【成立】則執行Step3,【不成立】則跳到Step10。

Step3、進入內迴圈,並宣告變數【i】,給予初始值1,【判斷式】【i<=9】,變動規則為【i+1】。
這個外迴圈控制的是九九乘法中第二個數字,所以由1開始。

Step4、檢查【判斷式】【i<=9】是否【成立】,【成立】則執行Step5,【不成立】則跳到Step8。

Step5、宣告字串函數【result】存放組合字串,內容是【j】x 【i】 = 【j*i】再加上【" "】區隔字串。

Step6、顯示出字串函數【result】。

Step7、i+1,因為變數【i】的值改變了,需要重新檢查【判斷式】,回到Step4。

Step8、換行。

Step9、j+1,因為變數【j】的值改變了,需要重新檢查【判斷式】,回到Step2。

Step10、結束。

這邊還有一個小瑕疵,就是還是沒有對齊,原因是因為有的積(相乘的結果)是一位數,有的是兩位數,如果真的很介意這件事情,那就把【i * j】換成【(j * i).ToString("00")】,就真的很整齊。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_1
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int j = 2; j <= 9; j++)
            {
                //2開頭
                for (int i = 1; i <= 9; i++)
                {
                    string result = j + " x " + i + " = " + (j * i).ToString("00") + "  ";
                    Console.Write(result);
                }
                Console.Write("\r\n");
            }
            Console.ReadKey();
        }
    }
}

【(j * i).ToString("00")】這是蝦米意思?意思是說,把 j 和 i 相乘的結果轉換為2位數字串,不懂,比方說2 x 1 = 2 就會變成 2 x 1 = 02,就這麼簡單。

小弟我能想到最好的解釋大概就寫在上面了,不過好像有解釋等於沒解釋,我盡力了,有問題歡迎大家提出來討論,今天就到這裡了,改天見。

P.S 如果你程式碼的結果和我說的不一樣,那也許是因為你的命令提示視窗不夠寬,更改一下視窗框度就可以看到正常的結果了。滑鼠移到視窗標題,滑鼠右鍵,內容,視窗大小調整到140,確定,就可以了。