C#实现简单成绩管理系统的完整步骤
前言
这周跟C#打了一周的交道(本周是学校安排的实验周,然后用到了C#实现想要的程序和功能)
一共七个实验,选择三个,我就选择我进步最大的一个来分析一下吧。
效果
先来看一下效果吧
从txt文本中读取数据后展示出来
点击目标后选中,然后点击“修改”,弹出修改界面,然后进行编辑即可
点击“统计”按钮,弹出窗口显示各分数段的信息
点击“查询”后,弹出界面,输入后,点击“确定”即可显示信息
实现
一、准备工作
在写方法之前,首先就是先把界面规划好,就是通过添加按钮和输入框或显示框组成一个符合要求的窗口或多个窗口
在这个程序中我们用到的主要是这几个组件
对文件进行操作要进行引用的声明,即“using”
我们添加的是这两行
然后我们还要写一些代码来实现其他功能
public Form1() { InitializeComponent(); this.listView1.Columns.Add("学号", 100, HorizontalAlignment.Center); this.listView1.Columns.Add("姓名", 100, HorizontalAlignment.Center); this.listView1.Columns.Add("数学", 100, HorizontalAlignment.Center); this.listView1.Columns.Add("英语", 100, HorizontalAlignment.Center); this.listView1.Columns.Add("政治", 100, HorizontalAlignment.Center); this.listView1.Columns.Add("总分", 100, HorizontalAlignment.Center); this.listView1.Columns.Add("平均分", 100, HorizontalAlignment.Center); this.listView1.Columns.Add("名次", 100, 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", 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], " "); 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", UTF8Encoding.Default); //把txt文件中按行存储的信息利用regex.Split按行存入string数组中 string[] records = Regex.Split(file, "\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", newrecord, 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", lines.ToArray(), 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", newrecord, 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, 0, 59).ToString() + "," + GetGradeSection(2, 0, 59).ToString() + "," + GetGradeSection(3, 0, 59).ToString() + "\r\n"; add += "60~69" + "," + GetGradeSection(1, 60, 69).ToString() + "," + GetGradeSection(2, 60, 69).ToString() + "," + GetGradeSection(3, 60, 69).ToString() + "\r\n"; add += "70~79" + "," + GetGradeSection(1, 70, 79).ToString() + "," + GetGradeSection(2, 70, 79).ToString() + "," + GetGradeSection(3, 70, 79).ToString() + "\r\n"; add += "80~89" + "," + GetGradeSection(1, 80, 89).ToString() + "," + GetGradeSection(2, 80, 89).ToString() + "," + GetGradeSection(3, 80, 89).ToString() + "\r\n"; add += "90~100" + "," + GetGradeSection(1, 90, 100).ToString() + "," + GetGradeSection(2, 90, 100).ToString() + "," + GetGradeSection(3, 90, 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", 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++) { //分割每行记录的各个字段 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", UTF8Encoding.Default); //把txt文件中按行存储的信息利用regex.Split按行存入string数组中 string[] records = Regex.Split(file, "\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#,所以也不知道怎么搞,总结下来就是这一周的收获并不是很大,毕竟整天忙得不可开交,吃饭、睡觉、敲代码,最后一总结发现并没有学到什么真切的知识,毕竟一点都没学,上来就用,这种方式真的难以理解,在此我想说的是,只要敢钻研,肯钻研,再难的问题也有解决的办法,最后补充一句,忙点真的挺好的,每天都很充实,加油,奋斗在路
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对猪先飞的支持。
相关文章
- 我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
- 这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
- 这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
- 本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
- 这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)
这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
- 这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
- 最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
- 这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
- 本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
- 轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
- 这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
- 这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
- 这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
- 下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25