Project 1 - 自我介紹程式(3):看型別用Bug教工程師做人,它會決定程式的動盪與安逸
https://ithelp.ithome.com.tw/articles/10213621
延續昨天在型別的介紹與實例展示,今天我們來思考,該如何透過程式碼,從哪些方向撰寫程式碼,處理型別可能帶來的程式錯誤,這個過程就是所謂的「卡控」或「校驗」。
對於一個大型的資訊系統,包括金融系統、商業系統、校務系統、工程系統,每天必須長時間不間段的處理大量資料,如果在資料的接收過程中產生的程式錯誤,將會接連造成後續的資料錯誤,最後的資料流失或資料錯誤,對使用者產生的損失和影響大到難以估計。
然而要做好資料的卡控和校驗,需要對「語法、邏輯、資料結構、型態函式庫」的四個觀念和「資料本身」有一定的了解和敏銳度。除了演算法和資料結構解題的練習之外,還需要有專案開發和維護系統,從面對真實的功能需求當中學習。
每次做任何處理資料前,最一開始要檢查的有沒有資料,避免NULL和空字串造成程式錯誤。
//檢查是否所有欄位都有被輸入
TextBox[] allTextBox = new TextBox[] { nameTextBox, homeTownTextBox,
birthdate_YearBox, birthdate_MonthBox,
birthdate_DayBox };
string[] allTextBoxName = new string[]{"姓名", "家鄉", "出生年", "出生月", "出生日" }; // 也可以放在TextBox的Tag屬性
StringBuilder errorMsg = new StringBuilder();
for (int i = 0; i < allTextBox.GetLength(0); i++)
{
if (allTextBox[i].Text == null || allTextBox[i].Text == "")
{
errorMsg.AppendLine(string.Format(@"請輸入 「{0}」", allTextBoxName[i]));
}
}
if (errorMsg.ToString() != "")
{
MessageBox.Show(errorMsg.ToString());
return;
}
有沒有輸入文字的條件判斷,在C#可使用 string 函式庫 的 IsNullOrEmpty 函式
if(string.IsNullOrEmpty(allTextBox[i].Text))
{
errorMsg.AppendLine(string.Format(@"請輸入 「{0}」", allTextBoxName[i]));
}
我們經常需要判斷的狀況有「是不是數值」、「英文字母」,生日的年月日都只能是數字
解決方向1: 從源頭解決,替換UI欄位
把生日旁邊三個可以輸入任何文字的TextBox,改換成C#的DateTimePicker,讓使用者只能以日期的形式輸入資料
在程式碼透過DateTimePicker的Value屬性當中的Year、Month、Day,得到數字型態的日期資料
int birthDate_Year = birthDate_Picker.Value.Year;
int birthDate_Month = birthDate_Picker.Value.Month;
int birthDate_Day = birthDate_Picker.Value.Day;
解決方向2: 撰寫鍵盤事件,讓使用者只能按下數字鍵或控制類按鍵(BackSpace)
使用者如果只能輸入數字,使用Convert.ToInt32或int.Parse就可以確保不會出現問題
我們可以根據使用者按下鍵盤的按鍵字元,判斷輸入的文字是不是數字
char (字元型態) 只能有「一個文字」的變數,string (字串) 可以有「一個或一個以上」的文字。
private void birthdate_YearBox_KeyPress(object sender, KeyPressEventArgs e)
{
//取得使用者每次輸入鍵盤當下的文字
char inputChar = e.KeyChar;
// 使用者只能輸入數字(char.IsDigit(inputChar))、控制類按鍵(char.IsControl(e.KeyChar))
// 在keyPress 設定e.Handled = true,文字就無法輸入進去
e.Handled = ! (char.IsDigit(inputChar) || char.IsControl(e.KeyChar));
}
解決方向3: 在存到變數前檢查
只要在存到變數之前,發現三個輸入欄位的文字不是數字,就不要繼續往下執行
避免輸入的文字經過int.Parse()或Convrt.ToInt32 處理時發生問題
【自行撰寫判斷函式】
你可以寫成一個函式方法 stringIsInt,透過參數num帶入要檢查的字串變數,如果可以成功轉換成 int (try),最後回傳 true,如果轉換出現錯誤(Catch),不是 int 最後回傳 false
private bool stringIsInt(string num)
{
try
{
int tryParse = int.Parse(num);
return true;
}
catch (Exception)
{
return false;
}
}
經過簡化後,等同下方的程式碼
private bool stringIsInt(string num)
{
int tryParse;
return int.TryParse(num, out tryParse);
}
在按下自我介紹的Click程式碼,放到 if 的條件當中,檢查生日年月日輸入的文字
if (!stringIsInt(birthdate_YearBox.Text) || !stringIsInt(birthdate_MonthBox.Text) || !stringIsInt(birthdate_DayBox.Text))
{
MessageBox.Show("出生年月日請輸入數字");
return;
}
【正規表達式】
正規表達式可以做到非常複雜的格式判斷,包括電話號碼、email、URL網址、IP
可以參考下方兩個網址,深入了解正規表達式
https://dotblogs.com.tw/kinanson/2013/05/23/104772
透過Regex.IsMatch函式方法判斷,如果符合格式會回傳True。
並搭配 if 校驗和卡控
// Regex.IsMatch(要判斷的資料,判斷是不是符合這個格式)
if (!Regex.IsMatch(birthdate_YearBox.Text, @"\d") ||
!Regex.IsMatch(birthdate_MonthBox.Text, @"\d") ||
!Regex.IsMatch(birthdate_DayBox.Text, @"\d"))
{
MessageBox.Show("出生年月日請輸入數字");
return;
}
1.檢查你有沒有選擇圖片,若沒有選擇照片,得到的照片資料會是NULL,出現錯誤
2.檢查選完照片是不是按下確定,如果按下取消,得到的照片資料會是NULL,出現錯誤
3.檢查你的檔案格式是不是符合常見的圖片格式,如果不符合,無法轉換
private void photoBox_DoubleClick(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
if (fileDialog.ShowDialog() == DialogResult.OK && fileDialog.FileName != "")
{
photoBox.Image = Image.FromFile(fileDialog.FileName);
}
}
1.出生年、月、日不能超過今天,例如今天是2019/09/05,結果生日輸入2019/12/10
2.生日年、月、日不能是負數
3.月份是1~12月,日期根據輸入的月份判斷是否在1~最大天數
只要其中一個不吻合,回傳False
private bool isValidBirthDate(string year, string month, string day)
{
/*
撰寫這支副程式的邏輯,根據傳入的年月日判斷是不是有效的生日日期
例如: isValidBirthDate("2018", "02", "30") => false, 因為2018年沒有2月30日
isValidBirthDate("2018", "01", "31") => true
isValidBirthDate("201D", "10", "10") => false, "傳入的年不是純正整數"
isValidBirthDate("2019", "12", "10") => false, "生日超過今天的日期 (今天是2019/9/05)"
*/
// 有效的生日日期,最後回傳true
return true;
}
你會發現看似直覺簡單的卡控和校驗判斷,當中參雜許多陌生的觀念和語法。所以如果你是一個初學者來看這篇,多多少少會感覺到排斥和壓力。慢慢的練習解題、寫Side Project、接觸開發專案(開源或工作),相信能在放棄程式之前的某一天,對資料的敏感度越來越強。