iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 3
2
Software Development

當我遊走在程式的初學路上-從入門到放棄系列 第 3

Project 1 - 自我介紹程式(3):看型別用Bug教工程師做人,它會決定程式的動盪與安逸

  • 分享至 

  • xImage
  •  

Project 1 - 自我介紹程式(2):如果你容易迷路,試著從需求的角度出發吧!
https://ithelp.ithome.com.tw/articles/10213512

複習第二天:寫程式需要了解這麼多技術和語法的原因

一、為了讓程式在「對的時間點」完成事情

1.如何讓程式開啟的過程中,產生視窗畫面與欄位 => 初始化(InitializeComponent() )
2.當程式開啟後,等待使用者輸入欄位、選擇大頭貼、按下自我介紹鈕 => 事件偵聽(Event Listener)
3.當使用者點擊兩下大頭貼框框,跳出一個視窗可以選擇圖片=> 觸發事件 (Event Function)
4.當使用者按下自我介紹按鈕,將姓名和家鄉存到程式當中做處理 => 變數 (Variable) 、流程控制(if,switch),迴圈(For,While,Do While),函式方法(Function)

二、為了讓程式處理「對的資料」,得到「對的資料」

1.資料可以透過使用者輸入、檔案、網路、資料庫、感測元件取得
2.取得資料後,透過資料結構適當的分類後存到變數、陣列、物件
3.資料處理的過程主要有「算數」、「編碼位元轉換」、「文字分析」等問題,也就是程式常見的三種基本型態:「數值(int,double)」、「文字(char,string)」、「位元(byte)」

第三天簡介:理解型別在程式的風水影響力

在第二天後半段,我們針對「如何在對的時間點完成一件事」嘗試完成了一部分的程式碼,今天我們將繼續完成計算年紀的程式碼,慢慢地將重點轉移到「如何處理並得到對的資料」。

從教學者與學習者看放棄程式的人

「資料型態」之所以是所有學程式的人必須經過的門檻與修練,是因為初學者無法只看資料型態的理論說明,體會型態的使用不當會帶來多少的災害,製造多少的蟲蟲(Bug)殘害程式開發者的美好時光。

型別使用不當為什麼會帶來災難?

如果不認識型別,可以參考官方的說明:
https://docs.microsoft.com/zh-tw/dotnet/csharp/tour-of-csharp/types-and-variables
覺得看不懂不必難過,這是正常的

接著參考另外一篇文章:
https://dotblogs.com.tw/rainbow/2018/07/24/141621
看完你會覺得型別很簡單,但事實上並非如此!為什麼?

1.你能不能用鉛筆盒裝一台24吋液晶螢幕?

不能,你塞不下

2.你能不能把出國行李廂當作錢包?

能,但是浪費空間

3.隔一天要停水,你會拿衣服來儲水還是拿水桶來儲水?

水桶。除非那件衣服具有儲水的用途

4.今天你想外訂飲料,如果你跟店員說,我要「泰D杯」飲料,甜度冰塊「天」糖「天」冰?

那麼直到店員理解「泰D杯」和「天糖天冰」之前,店員不會幫你外送飲料

5.指甲刀跟雙面膠,你會用哪一個剪指甲

指甲刀。我想知道怎麼用雙面膠剪指甲

6.假日很開心的跟準備和另一半開車出遊,結果發現鑰匙不見了,請問沒有鑰匙可以開車嗎?

不行。如果可以,你的車子應該很早就不見了

現實生活的每個東西,都有它的體積空間、用途。在平常生活當中,我們會透過數值,傳達一個可以被計算和量化的訊息。在程式裡面,就是所謂的型別。

從上面的例子轉換到程式語言,不當的使用型別常見的影響包括:

  1. 可以執行,但超過主記憶體給予的存放空間,導致溢位,得到錯誤的結果。
  2. 可以執行,但是主浪費記憶體空間。
  3. 不允許存放,造成編譯錯誤。
  4. 文字無法量化計算,造成編譯錯誤。
  5. 每種物件都有自己專屬的方法,好比雙面膠類的物件沒有動作可以剪下指甲,如果你強迫雙面膠剪指甲,造成編譯錯誤。
  6. 程式沒辦法幫你處理不存在的東西(空白字串、NULL)。

完成年齡的計算功能

以下是我們昨天完成的完整程式碼:

using System;
using System.Windows.Forms;

namespace Hello_World
{
    public partial class IntroductionForm : Form
    {
        // WinForm 產生畫面的初始化過程
        public IntroductionForm()
        {
            InitializeComponent();
        }
        
        // 視窗開啟後會彈出視窗跟使用者打聲招呼
        private void IntroductionForm_Load(object sender, EventArgs e)
        {
            MessageBox.Show("安安我想認識你,先做個自我介紹嗎");
        }
        
        // 按下自我介紹按鈕,依照輸入的姓名、家鄉、出生年月日,顯示一段自我介紹
        private void showIntroductionBtn_Click(object sender, EventArgs e)
        {
            // 宣告 字串 變數 name,存放姓名欄位當中的文字
            string name = nameTextBox.Text;

            // 宣告 字串 變數 name,存放家鄉欄位當中的文字
            string homeTown = hometownTextBox.Text;

            // 宣告三個 整數 變數,取得當下的日期 today_Year(年)、today_Month(月)、today_Day(日)
            int today_Year = DateTime.Today.Year;
            int today_Month = DateTime.Today.Month;
            int today_Day = DateTime.Today.Day;

            MessageBox.Show("大家好,我是 " + name + " ,我來自" + homeTown);
        }
    }
}

現在將焦點轉移到 「showIntroductionBtn_Click」函式上,我們還沒有把使用者的生日年、月、日存到變數
因為我們之後要將使用者輸入的「生日的年、月、日」做數值計算,所以要存到變數上面

    // 宣告三個 整數 變數,存放三個生日欄位的文字 
    int birthDate_Year = birthdate_YearBox.Text;
    int birthDate_Month = birthdate_MonthBox.Text;
    int birthDate_Day = birthdate_DayBox.Text;

這時候編輯器會送你三個錯誤訊息:
https://ithelp.ithome.com.tw/upload/images/20190904/201203316cLH8E5Nrh.png

原因很簡單,你宣告int型態的變數,但是TextBox.Text得到的資料型態是string,那麼我改用string宣告總可以了吧?

你以為你躲的掉嗎?等下它還是會回來找你的XD

現在我們嘗試宣告一個變數,用來放最後的年紀
接著將當下的年份 - 出生的年份,親眼見證另一個錯誤訊息:

    // 宣告年紀,並將年紀的變數值變成 當下年分 - 生日年分
    int yearOld;
    yearOld = today_Year - birthDate_Year; 

結果他真的回來找你了XDD

https://ithelp.ithome.com.tw/upload/images/20190904/201203317fZORXZQDi.png

為了做數值運算,你還是必須將生日的年月日的string文字轉成int整數,轉完後再放到int變數。
C#可以使用兩個函式方法將字串型態轉換為int

int.Parse(字串變數);
Convert.ToInt32(字串變數)

改完後的程式如下,錯誤訊息也順利地不見了

    // 宣告三個 整數 變數,存放三個生日欄位的文字 
    int birthDate_Year = int.Parse(birthdate_YearBox.Text);
    int birthDate_Month = int.Parse(birthdate_MonthBox.Text);
    int birthDate_Day = int.Parse(birthdate_DayBox.Text);

    // 宣告年紀,並將年紀的變數值變成 當下年分 - 生日年分
    int yearOld;
    yearOld = today_Year - birthDate_Year; 

https://ithelp.ithome.com.tw/upload/images/20190904/20120331du2Lsl7TxL.png

最後在下方寫一個邏輯判斷,如果目前的月分跟日期,還沒超過生日的月分和日期,未滿一年要再扣一年

    // today_Month < birthDate_Month:現在9月,生日在10月 (情況1)
    // today_Month == birthDate_Month && today_Day < birthDate_Day:今天9月4日,生日在9月10日 (情況2)
    if (today_Month < birthDate_Month || (today_Month == birthDate_Month && today_Day < birthDate_Day))
    {
        yearOld = yearOld - 1;
    }

實際來測試程式,看到預期的結果出現非常感動
https://ithelp.ithome.com.tw/upload/images/20190904/20120331JeXaSgdPvr.png

自我介紹按鈕 click事件 完整程式碼:

private void showIntroductionBtn_Click(object sender, EventArgs e)
{
    // 宣告 字串 變數 name,存放姓名欄位當中的文字
    string name = nameTextBox.Text;

    // 宣告 字串 變數 name,存放家鄉欄位當中的文字
    string homeTown = hometownTextBox.Text;

    // 宣告三個 整數 變數,取得當下的日期 today_Year(年)、today_Month(月)、today_Day(日)
    int today_Year = DateTime.Today.Year;
    int today_Month = DateTime.Today.Month;
    int today_Day = DateTime.Today.Day;

    // 宣告三個 整數 變數,存放三個生日欄位的文字 
    int birthDate_Year = int.Parse(birthdate_YearBox.Text);
    int birthDate_Month = int.Parse(birthdate_MonthBox.Text);
    int birthDate_Day = int.Parse(birthdate_DayBox.Text);

    int yearOld;
    yearOld = today_Year - birthDate_Year;

    if (today_Month < birthDate_Month || (today_Month == birthDate_Month && today_Day < birthDate_Day))
    {
        yearOld = yearOld - 1;
    }

    MessageBox.Show("大家好,我是 " + name + " ,我來自" + homeTown + ",今年 " + yearOld + "歲");
}

看看型態怎麼教程式設計師做人

情況一:如果我的生日的年月日輸入英文字呢? => Type Error

https://ithelp.ithome.com.tw/upload/images/20190904/201203315gVRhmjtuP.png

程式表示:請問XDDD怎麼轉成數字?

https://ithelp.ithome.com.tw/upload/images/20190904/20120331lZfRbibvL9.png

情況二:如果我的生日輸入非常非常大呢? => 溢位

https://ithelp.ithome.com.tw/upload/images/20190904/20120331nOwAi7cwgB.png

程式表示:你的數字超出int的最大值 2,147,483,647 ,出現溢位

https://ithelp.ithome.com.tw/upload/images/20190904/20120331rck06UgeVS.png

情況三:如果我不輸入數字呢 => 空字串或NULL

https://ithelp.ithome.com.tw/upload/images/20190904/201203317tyfNWXTAG.png

程式表示:空白字串("") 怎麼轉成數字

https://ithelp.ithome.com.tw/upload/images/20190904/20120331mpsailJGqH.png

情況四:如果我拿昨天選擇相片的程式碼,用Excel當作大頭貼會發生什麼事情? => 無法轉換

private void photoBox_DoubleClick(object sender, EventArgs e)
{
    OpenFileDialog fileDialog = new OpenFileDialog();

    if (fileDialog.ShowDialog() == DialogResult.OK && fileDialog.FileName != "" && fileDialog != null)
    {
        photoBox.Image = Image.FromFile(fileDialog.FileName);
    }
}

https://ithelp.ithome.com.tw/upload/images/20190904/20120331JT2f1EC9KV.png

https://ithelp.ithome.com.tw/upload/images/20190904/20120331GjSiWBwvgM.png

程式表示:xls 格式不是圖片 轉換會出現問題

https://ithelp.ithome.com.tw/upload/images/20190904/20120331Qi2THPA4NK.png

往明天邁進 OR 放棄?:動態語言、靜態語言遲早都需要被型態告訴怎麼做人

今天以自我介紹程式的程式碼,有別於理論敘述的方式,以真實Bug的角度,讓學習者可以親眼見證型態對程式風水的影響力。你會好奇:「只要不要出現錯誤訊息,是不是就能安心了?」

舉例來說,動態語言雖然幫我們處理的型態的問題,卻也容易造成其他的問題。例如Javascript透過AJAX得到一個變數abc,叫做"1000",如果直接使用abc + 50 會得到 100050,因為+號在Javascript跟C#都代表兩個字串文字合併。

至於怎麼避免或處理型態帶來的風水問題,就讓我們繼續看下去!


上一篇
Project 1 - 自我介紹程式(2):如果你容易迷路,試著從需求的角度出發吧!
下一篇
Project 1 - 自我介紹程式(4):活用「語法、邏輯、資料結構、型態函式庫」-確保正確的資料進到程式當中
系列文
當我遊走在程式的初學路上-從入門到放棄9
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言