C#實現簡單成績管理系統的完整步驟
前言
這周跟C#打了一週的交道(本週是學校安排的實驗周,然後用到了C#實現想要的程式和功能)
一共七個實驗,選擇三個,我就選擇我進步最大的一個來分析一下吧。
效果
先來看一下效果吧
從txt文字中讀取資料後展示出來
點選目標後選中,然後點選“修改”,彈出修改介面,然後進行編輯即可
點選“統計”按鈕,彈出視窗顯示各分數段的資訊
點選“查詢”後,彈出介面,輸入後,點選“確定”即可顯示資訊
實現
一、準備工作
在寫方法之前,首先就是先把介面規劃好,就是通過新增按鈕和輸入框或顯示框組成一個符合要求的視窗或多個視窗
在這個程式中我們用到的主要是這幾個元件
對檔案進行操作要進行引用的宣告,即“using”
我們新增的是這兩行
然後我們還要寫一些程式碼來實現其他功能
public Form1() { InitializeComponent(); this.listView1.Columns.Add("學號",100,HorizontalAlignment.Center); this.listView1.Columns.Add("姓名",HorizontalAlignment.Center); this.listView1.Columns.Add("數學",HorizontalAlignment.Center); this.listView1.Columns.Add("英語",HorizontalAlignment.Center); this.listView1.Columns.Add("政治",HorizontalAlignment.Center); this.listView1.Columns.Add("總分",HorizontalAlignment.Center); this.listView1.Columns.Add("平均分",HorizontalAlignment.Center); this.listView1.Columns.Add("名次",HorizontalAlignment.Center); this.listView1.View = System.Windows.Forms.View.Details; this.listView1.FullRowSelect = true;//是否可以選擇行 }
“listview1”就是按鈕上方實現顯示的控制元件,“this”指的就是Form1這個視窗,“Columns”指的是“欄”,也就是上方的內容,“add”指的是把後面的內容作為“Columns”的內容,後面的“100”等都是“Columns”的屬性,可以通過修改它的屬性來修改它的大小和位置,還有一種生成“Column”的方法是通過屬性欄來新增。
點選listview一次選中它,然後右鍵單擊一次,點選屬性,會發現有“Column”這個屬性,點進去後就可以進行編輯和修改了。
不得不說確實挺方便的,不過實驗報告手冊中給了部分必須的原始碼,再加上自己第一次接觸C#,所以就沒使用後面的方法,不過在後面的操作中使用了一下,確實挺爽。
二、讀取操作
這裡的“讀取”按鈕讀取的是統計之後的內容,並非成績等資訊,雙擊“讀取”按鈕後即可進行編輯(在按鈕的屬性中我修改了name屬性為load,所以此處的方法名為“load_Click”)
private void load_Click(object sender,EventArgs e) { this.load_data(); }
此處呼叫了“load_data()”這個方法
public void load_data() { string file = File.ReadAllText("Score.txt",UTF8Encoding.Default); //把txt檔案中按行儲存的資訊利用regex.Split按行存入string陣列中 string[] records = Regex.Split(file,"\r\n"); //開始更新檢視 this.listView1.BeginUpdate(); //清空原有檢視 this.listView1.Items.Clear(); // records.Length為陣列的元素個數 for (int index = 0; index < records.Length; index++) { //分割每行記錄的各個欄位 string[] components = Regex.Split(records[index]," "); //生成listview的一行 ListViewItem lvi = new ListViewItem(components); //新增背景色 lvi.SubItems[0].BackColor = Color.Red; //把新生成的行加入到listview中 this.listView1.Items.Add(lvi); } //檢視更新結束 this.listView1.EndUpdate(); }
這個方法就是以“/r/n”為分界線定義一個數組1,然後再以空格為分界線定義一個數組2,同時生成一個 ListViewItem 來顯示陣列2,然後再設定一下背景色,此處設定的為紅色
//生成listview的一行 ListViewItem lvi = new ListViewItem(components); //新增背景色 lvi.SubItems[0].BackColor = Color.Red;
lvi是新生成的listview的命名
三、查詢操作
private void Search_Click(object sender,EventArgs e) { Form3 f3 = new Form3(); f3.Show(); }
在查詢的方法中我們呼叫了一個視窗Form3,同Form1一樣,先規劃好視窗的格局,然後再寫方法
private void go_Click(object sender,EventArgs e) { string file = File.ReadAllText("Score.txt","\r\n"); //開始更新檢視 this.listView1.BeginUpdate(); //清空原有檢視 this.listView1.Items.Clear(); // records.Length為陣列的元素個數 for (int index = 0; index < records.Length; index++) { //分割每行記錄的各個欄位 string[] components = Regex.Split(records[index]," "); Regex r = new Regex(this.textBox1.Text); // 定義一個Regex物件例項 Match m = r.Match(components[0]); // 在字串中匹配 if (m.Success) { //生成listview的一行 ListViewItem lvi = new ListViewItem(components); //新增背景色 lvi.SubItems[0].BackColor = Color.White; //把新生成的行加入到listview中 this.listView1.Items.Add(lvi); } else if (components.Length > 1) { Match n = r.Match(components[1]); if (n.Success) { //生成listview的一行 ListViewItem lvi = new ListViewItem(components); //新增背景色 lvi.SubItems[0].BackColor = Color.White; //把新生成的行加入到listview中 this.listView1.Items.Add(lvi); } } } //檢視更新結束 this.listView1.EndUpdate(); }
主要的方法,甚至是唯一的方法,就是上方的“go_Click()”方法,“Score.txt”是存放成績等資訊的,在姓名和學號之中匹配,匹配到了就新建一個listview的item展示資訊
這裡的查詢用到了匹配的函式Match() ,在此給出官方的連結
Match()
四、刪除
刪除的思想就是選中要刪除的那一行,之後從檔案讀取所有內容,新建string陣列存放每一行,一行一行的遍歷,直到遇見選中的那一行,從陣列中移除,然後把剩餘的陣列元素寫入文字中,WriteAllLines()方法定義中呼叫了replace()方法,因此省去了我們刪除檔案原有內容的操作
private void Delate_Click(object sender,EventArgs e)//刪除 { foreach (ListViewItem lvi in listView1.SelectedItems) { //把txt檔案內容讀入到file中,然後對string物件file進行相關處理 string file = File.ReadAllText("Score.txt",UTF8Encoding.Default); List<string> lines = new List<string>(Regex.Split(file,"\r\n")); lines.RemoveAt(lvi.Index); File.WriteAllLines("Score.txt",lines.ToArray(),UTF8Encoding.Default); } this.load_data(); }
五、錄入
private void Input_Click(object sender,EventArgs e)//錄入 { Form2 f = new Form2(this); f.Show(); }
這裡的錄入方法呼叫了一個新的視窗Form2,與之前不同的是,這裡給Form2傳了一個引數“this”,即Form1這個視窗,因為之後我們要在Form2的方法中呼叫Form1的方法。
再來看一下Form2的介面和方法
1、接收引數
private Form1 form; public Form2() { InitializeComponent(); } public Form2(Form1 form){ this.form = form; InitializeComponent(); }
首先進行定義,然後進行賦值,這樣的話在之後就可以用定義時使用的名稱進行Form1的方法的呼叫了。
2、儲存資訊
在點選“儲存”按鈕後,我們要實現文字的寫入以及介面的更新,文字的寫入我們要寫新的方法,介面的更新我們可以呼叫Form1的方法。
if (this.textBox1.Text != string.Empty && this.textBox2.Text != string.Empty && this.textBox3.Text != string.Empty && this.textBox4.Text != string.Empty && this.textBox5.Text != string.Empty) { //利用string的加法操作構造新紀錄,作為一行,寫入txt檔案中 string newrecord = this.textBox1.Text + " " + this.textBox2.Text + " " + this.textBox3.Text + " " + this.textBox4.Text + " " + this.textBox5.Text + "\r\n" ; File.AppendAllText("Score.txt",newrecord,UTF8Encoding.Default); //結束form2的呼叫 this.Dispose(false); //呼叫Form1載入介面的方法 this.form.load_data(); } else { Form5 f5 = new Form5(); f5.Show(); }
首先判空,如果都不為空,定義新的字串,賦值,寫入文字,為了保證程式的嚴謹性,加一個Form5視窗進行錯誤的提示
(由於時間的限制,這裡也不算很完善,有能力的可以考慮進行各個條件的判斷,例如“學號”為空,則彈出的視窗顯示“學號不能為空”)
值得注意的是,這裡呼叫的Form1中的方法必須是公有的,即“public”。
六、運算
private void operate_Click(object sender,EventArgs e) { //把txt檔案內容讀入到file中,然後對string物件file進行相關處理 string file = File.ReadAllText("Score.txt","\r\n"); //開始更新檢視 this.listView1.BeginUpdate(); //清空原有檢視 this.listView1.Items.Clear(); System.IO.File.WriteAllText("Score.txt",string.Empty); double[] score1 = new double[records.Length]; double[] score2 = new double[records.Length]; int num = 0; // records.Length為陣列的元素個數 for (int index = 0; index < records.Length; index++) { if (records[index].Length != 0) { //分割每行記錄的各個欄位 string[] components = Regex.Split(records[index]," "); score1[index] = Convert.ToDouble(components[2]) + Convert.ToDouble(components[3]) + Convert.ToDouble(components[4]); score2[index] = (Convert.ToDouble(components[2]) + Convert.ToDouble(components[3]) + Convert.ToDouble(components[4])) / 3.0; num++; } else break; } //冒泡法排序 int temp; for (int i = 0; i < num; i++) { temp = i; for (int j = i + 1; j < num; j++) { if (score1[j] > score1[temp]) temp = j; } double t = score1[temp]; score1[temp] = score1[i]; score1[i] = t; } for (int index = 0; index < records.Length; index++) { if (records[index].Length != 0) { //分割每行記錄的各個欄位 string[] components = Regex.Split(records[index]," "); for (int i = 1; i <= num; i++) { if (score1[i - 1] == Convert.ToDouble(components[2]) + Convert.ToDouble(components[3]) + Convert.ToDouble(components[4])) { //利用string的加法操作構造新紀錄,作為一行,寫入txt檔案中 string newrecord = components[0] + " " + components[1] + " " + components[2] + " " + components[3] + " " + components[4] + " " + score1[i - 1] + " " + score2[index] + " " + i + "\r\n"; File.AppendAllText("Score.txt",UTF8Encoding.Default); } } } else break; } //檢視更新結束 this.listView1.EndUpdate(); //重新整理介面 this.load_data(); }
題目的要求是計算各學生總分、平均分以及排名,思想就是,先讀取檔案,儲存資料,清空檔案,定義總成績和平均成績兩個陣列,分別計算每個人的總成績與平均成績,然後用冒泡法對總成績進行排序,得到排名,然後構造新陣列拼接這些內容,再把陣列寫入文字,更新檢視即可。
七、修改
修改的思想很簡單,雖說實現了想要的功能,但是也有缺陷,也沒想到特別好的解決辦法,先來說一下思路吧,首先選中,然後點選“修改”,彈窗,在這裡尤其注意得是,彈窗裡對應位置要顯示選中的內容
在這個圖中,我選中的是第二行,那麼我就要把它對應的資料顯示上去,在實驗過程中很多人所謂的修改就是輸入新的資料,裡面所有的內容都得再寫一遍,這樣的系統,自己用著指定難受。
(說到這我想插上一件事,吐槽一下最近使用的二課系統吧,是一個微信小程式,這是學校某個團隊開發的,總體上還是可以的,最大的不足就是每次開啟都得登入,也就是說每次使用都得重新輸入賬號和密碼,使用者的體驗真的挺差的,但是也不能因為它有不足就否認它,總體上也算挺方便的,值得去學習)
因為以前參與過專案的開發,而且專案的受眾就是我們自己,也知道什麼樣的效果更能使使用者滿意,所以對修改這個功能也算是有所瞭解,在實驗中,絕大多數人的“修改”功能都沒能達到滿意的效果,所以說經驗積累絕對不是毫無用處的。
繼續回到我們的功能實現中來,點選“確定”後,寫入文字,那麼我們肯定要把之前的資料刪掉,在傳參後立即刪除資料,當然這也就產生了瑕疵,使用者不修改資料,那怎麼辦,先來看程式碼吧,看完就知道了。
private void modify_Click(object sender,EventArgs e)//修改 { if (listView1.SelectedItems.Count != 0 ) { ListViewItem all = this.listView1.SelectedItems[0]; Form6 f6 = new Form6(all,this); f6.Show(); //把資料傳輸過去之後立即刪除資料 foreach (ListViewItem lvi in listView1.SelectedItems) { //把txt檔案內容讀入到file中,然後對string物件file進行相關處理 string file = File.ReadAllText("Score.txt",UTF8Encoding.Default); List<string> lines = new List<string>(Regex.Split(file,"\r\n")); lines.RemoveAt(lvi.Index); File.WriteAllLines("Score.txt",UTF8Encoding.Default); } } else { Form4 f4 = new Form4(); f4.Show(); } }
如果選中的內容不為空,那就把它的資料存到ListViewItem型別的陣列中,然後傳給Form6(修改資料視窗的類),同時再把Form1這個類傳過去,以便呼叫它的方法,然後使用一個刪除方法,如果內容為空,彈出Form4,提示錯誤。
同樣的,在Form6這邊先定義,然後接收引數,賦值
private void Form6_Load(object sender,EventArgs e) { this.textBox1.Text = this.content.SubItems[0].Text; this.textBox2.Text = this.content.SubItems[1].Text; this.textBox3.Text = this.content.SubItems[2].Text; this.textBox4.Text = this.content.SubItems[3].Text; this.textBox5.Text = this.content.SubItems[4].Text; }
在載入方法中為textBox賦值,以此來顯示資料,修改後點選“確定”,確定的方法和“錄入”功能的“確定”的方法相同,說白了就是寫入,如果“取消”怎麼辦,資料已經刪除了,既然textBox裡本來就有資料,那麼就把那些資料再寫入文字,這樣雖然實現了我的功能,但是有瑕疵,就是無論修改資料與否,重新載入後資料都會顯示在最後一行。
“確定”方法
private void Determine_Click(object sender,EventArgs e) { if (this.textBox1.Text != string.Empty && this.textBox2.Text != string.Empty && this.textBox3.Text != string.Empty && this.textBox4.Text != string.Empty && this.textBox5.Text != string.Empty) { //利用string的加法操作構造新紀錄,作為一行,寫入txt檔案中 string newrecord = this.textBox1.Text + " " + this.textBox2.Text + " " + this.textBox3.Text + " " + this.textBox4.Text + " " + this.textBox5.Text + "\r\n"; File.AppendAllText("Score.txt",UTF8Encoding.Default); var lines = File.ReadAllLines("Score.txt").Where(arg => !string.IsNullOrWhiteSpace(arg)); File.WriteAllLines("Score.txt",lines); //結束form6的呼叫 this.Dispose(false); } this.form.load_data(); }
八、統計
所謂的統計就是計算各科各分數段人數以及各科平均分
private void Sta_Click(object sender,EventArgs e)//統計 { this.Output(); Form7 f7 = new Form7(); f7.Show(); }
呼叫一個output()方法,用Form7顯示資料
public string Output()//寫入資料 { string add = string.Empty; add += "統計情況:" + "\r\n" + "分數段" + "," + "數學" + "," + "英語" + "," + "政治" + "\r\n"; add += "<60" + "," + GetGradeSection(1,59).ToString() + "," + GetGradeSection(2," + GetGradeSection(3,59).ToString() + "\r\n"; add += "60~69" + ",60,69).ToString() + ",69).ToString() + "\r\n"; add += "70~79" + ",70,79).ToString() + ",79).ToString() + "\r\n"; add += "80~89" + ",80,89).ToString() + ",89).ToString() + "\r\n"; add += "90~100" + ",90,100).ToString() + ",100).ToString() + "\r\n"; add += "平均分" + "," + GetAve(1).ToString() + "," + GetAve(2).ToString() + "," + GetAve(3).ToString() + "\r\n"; System.IO.File.WriteAllText("List.txt",string.Empty); File.AppendAllText("List.txt",add,UTF8Encoding.Default); return add; }
Output方法呼叫了GetGradeSection()和 GetAve() 兩個方法,先生成並定義字串陣列,然後把兩個方法返回的資料與原有的資訊拼接到陣列中,再寫入即可。
public double GetGradeSection(int m,int low,int high)//分數段 { int count = 0; string file = File.ReadAllText("Score.txt","\r\n"); //開始更新檢視 this.listView1.BeginUpdate(); //清空原有檢視 this.listView1.Items.Clear(); // records.Length為陣列的元素個數 for (int index = 0; index < records.Length; index++) { //分割每行記錄的各個欄位 if (records[index].Length != 0) { string[] components = Regex.Split(records[index]," "); if (m == 1)//數學 { if (Convert.ToDouble(components[2]) >= low && Convert.ToDouble(components[2]) <= high) { count++; } } if (m == 2)//英語 { if (Convert.ToDouble(components[3]) >= low && Convert.ToDouble(components[3]) <= high) { count++; } } if (m == 3)//政治 { if (Convert.ToDouble(components[4]) >= low && Convert.ToDouble(components[4]) <= high) { count++; } } } else break; } return count; }
先迴圈,然後進行判斷,如果在分數段內就把count值加一,最後返回到Output()方法中
public double GetAve(int m)//平均分 { double ave = 0; string file = File.ReadAllText("Score.txt","\r\n"); int length = records.Length; //開始更新檢視 this.listView1.BeginUpdate(); //清空原有檢視 this.listView1.Items.Clear(); // records.Length為陣列的元素個數 for (int index = 0; index < records.Length; index++) { if (records[index].Length != 0) { //分割每行記錄的各個欄位 string[] components = Regex.Split(records[index]," "); if (m == 1) { ave += double.Parse(components[2]); } if (m == 2) { ave += double.Parse(components[3]); } if (m == 3) { ave += double.Parse(components[4]); } } else break; } return ave/length; }
把各科對應的所有的分數加在一起,然後除以總人數,即為平均分,返回到Output()方法中
拼接好的字串陣列寫入List.txt文字中,在Form7中讀取,在Listview中顯示即可
九、清除
清除就是清空所有的文字資料,然後就把空字元寫入覆蓋即可
private void ClearAll_Click(object sender,EventArgs e) { System.IO.File.WriteAllText("Score.txt",string.Empty); System.IO.File.WriteAllText("List.txt",string.Empty); this.load_data(); }
總結
由於之前沒接觸過C#,所以也不知道怎麼搞,總結下來就是這一週的收穫並不是很大,畢竟整天忙得不可開交,吃飯、睡覺、敲程式碼,最後一總結髮現並沒有學到什麼真切的知識,畢竟一點都沒學,上來就用,這種方式真的難以理解,在此我想說的是,只要敢鑽研,肯鑽研,再難的問題也有解決的辦法,最後補充一句,忙點真的挺好的,每天都很充實,加油,奮鬥在路
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對我們的支援。