要求如下:
(1)问题描述
设计一个“学生成绩管理系统”。主要实现学生信息的录入、添加、修改、删除、排序和查看等基本功能。
(2)具体要求
编写一个学生成绩管理程序。学生成绩以一个学生一条记录的形式存储,每个学生记录包含的信息有序号、学号、姓名及5门功课的成绩。具体功能如下:
a. 获取学生成绩。可以从文件中读取成绩,也可直接录入。
查询学生成绩,输入学生学号或姓名等信息后,显示学生在成绩单中的位置及所有信息。
b. 添加学生成绩,在学生成绩单的指定位置添加学生成绩信息。
c. 修改学生成绩,在学生成绩单中,修改指定学生的成绩信息。
d. 删除学生成绩,在学生成绩单中,删除指定学生的成绩信息。
e. 保存文件。当学生成绩单发生添加、修改、删除等变化后,都要对最终结果进行保存。
(3)数据结构及算法分析
学生成绩可以用单链表存储,方便随时插入和删除学生成绩记录,实现动态管理。一个学生作为一个结点。
使用链表的基本算法实现学生成绩单的各项管理功能。
操作:
首先编译好自己的链表头文件和cpp文件(lianbiao.h,lianbiao.cpp),记住,只能在头文件中声明,不要定义,否则后面会出现头文件的重定义问题!参见http://m.xue163.com/19990/44531/445316870.html
新建MFC单文档应用程序,不选用Unicode库!在头文件里面把自己编辑的头文件添加进去,同样在源文件中再把自己编译的cpp文件添加进去,把stu.txt文件添加到代码里面去。
在资源视图中右击dialog,新建对话框,加上4个按钮:添加,修改,删除,查找,添加一个类CDlg
然后在menu中的mainmenu中添加一个菜单,操作,子菜单:学生管理系统,注意属性popup为false!右击学生管理系统为这个菜单项添加事件处理程序;记住,在头文件中添加你的主对话框的类#include"Dlg.h",菜单项对应的程序如下:
void Cstudent_adminView::On32771() //On32771为ID
{
CDlg studentadministrator;//主对话框类定义一个对象
studentadministrator.DoModal();//DoModal是打开这个对话框
}
而后,新建对话框:
查找:设计按两个静态文本,两个编辑框,两个按钮,实现能够按照学号查找或按照名字查找的功能
同样右击添加类CDlg_find,并为两个编辑框添加变量xuehao2,name2,双击主对话框中的查找按钮将这个对话框和CDlg_find建立的对话框连接起来,记住在头文件声明!#include"Dlg_find" 代码如下:
void CDlg::OnBnClickedButton2()
{
CDlg_find finddata;
finddata.DoModal();
}
双击子对话框中的两个按钮:按学号查找和按名字查找,分别编辑对应的程序,记住,编辑的时候把自己的编辑的链表类的头文件写上!代码如下
void CDlg_find::OnBnClickedButton1()
{
List DC;
DC.inputfile();
UpdateData(TRUE);
string a;
a=xuehao2.GetBuffer();
node *p=DC.Find1(a);
if(p==NULL)
MessageBox(_T("找不到对应学号的学生,请检查!"),_T("系统消息"),MB_ICONEXCLAMATION);
else
{CString num1,xuehao1,name1,chinese,math,english,physic,chemical;
num1=p->student.num.c_str();
xuehao1=p->student.xuehao.c_str();
name1=p->student.name.c_str();
chinese=p->student.chinese.c_str();
math=p->student.math.c_str();
english=p->student.english.c_str();
physic=p->student.physic.c_str();
chemical=p->student.chemical.c_str();
MessageBox(_T("序号:")+num1+_T('\n')
+_T("学号:")+xuehao1+_T('\n')
+_T("名字:")+name1+_T('\n')
+_T("语文:")+chinese+_T('\n')
+_T("数学:")+math+_T('\n')
+_T("英语:")+english+_T('\n')
+_T("物理:")+physic+_T('\n')
+_T("化学:")+chemical+_T('\n'),_T("系统消息"),MB_ICONASTERISK);
DC.MakeEmpty();}
// TODO: 在此添加控件通知处理程序代码
}
void CDlg_find::OnBnClickedButton4()
{
List DD;
DD.inputfile();
UpdateData(TRUE);
string a=name2.GetBuffer();
node *p=DD.Find2(a);
if(p==NULL)
MessageBox(_T("找不到对应的名字,请检查!"),_T("系统消息"),MB_ICONEXCLAMATION);
else{
CString num1,xuehao1,name1,chinese,math,english,physic,chemical;
num1=p->student.num.c_str();
xuehao1=p->student.xuehao.c_str();
name1=p->student.name.c_str();
chinese=p->student.chinese.c_str();
math=p->student.math.c_str();
english=p->student.english.c_str();
physic=p->student.physic.c_str();
chemical=p->student.chemical.c_str();
MessageBox(_T("序号:")+num1+_T('\n')
+_T("学号:")+xuehao1+_T('\n')
+_T("名字:")+name1+_T('\n')
+_T("语文:")+chinese+_T('\n')
+_T("数学:")+math+_T('\n')
+_T("英语:")+english+_T('\n')
+_T("物理:")+physic+_T('\n')
+_T("化学:")+chemical+_T('\n'),_T("系统消息"),MB_ICONASTERISK);
DD.MakeEmpty();}
// TODO: 在此添加控件通知处理程序代码
}
主要两点:CString和string类型的转换,string->CString:CString str; string b="dhaksjhkd" ; str=b.c_str();
MessageBox的使用规则,具体见上,不再赘述。
新建类CDlg_remove,两个变量xuehao1,name1;在主对话框中在查找按钮的对应的程序中将按钮和子对话框连接起来,同样记得包含头文件#include"Dlg_remove",代码如下:
void CDlg::OnBnClickedButton1()
{
CDlg_remove removedata;
removedata.DoModal();
// TODO: 在此添加控件通知处理程序代码
}
然后双击对话框两个按钮,按名字删除和按学号删除:代码如下
void CDlg_remove::OnBnClickedButton1()
{
UpdateData(TRUE);
string a=xuehao1.GetBuffer();
List DA;
DA.inputfile();
if(DA.Remove2(a))
{
MessageBox(_T("已删除!"),_T("系统消息"),MB_ICONASTERISK);
}
else
{
MessageBox(_T("无此人信息,请检查输入是否错误!"),_T("系统消息"),MB_ICONEXCLAMATION);
}
DA.exportfile();
DA.MakeEmpty();
// TODO: 在此添加控件通知处理程序代码
}
void CDlg_remove::OnBnClickedButton4()
{
UpdateData(TRUE);
string a =name1.GetBuffer();
List DB;
DB.inputfile();
if(DB.Remove1(a))
{
MessageBox(_T("已删除!"),_T("系统消息"),MB_ICONASTERISK);
}
else
{
MessageBox(_T("无此人信息,请检查输入是否错误!"),_T("系统消息"),MB_ICONEXCLAMATION);
}
DB.exportfile();
// TODO: 在此添加控件通知处理程序代码
}
类似的方法,下面只说结构和代码:
添加按钮:有序号,学号,名字,五门成绩还有位置9个编辑框,9个静态文本,一个按钮
添加类添加变量……等等等等,类似上面
void CDlg_adddata::OnBnClickedButton1()
{
UpdateData(TRUE);
List DE;
DE.inputfile();
stinfo A;
A.num=num3.GetBuffer();
A.name=name3.GetBuffer();
A.xuehao=xuehao3.GetBuffer();
A.chinese=chinese3.GetBuffer();
A.math=math3.GetBuffer();
A.english=english3.GetBuffer();
A.physic=physic3.GetBuffer();
A.chemical=chemical3.GetBuffer();
int a=_ttoi(position);
if(DE.Insert(A,a))
{MessageBox(_T("已添加到指定位置!"),_T("系统消息"),MB_ICONASTERISK);
}
else{
CString str;
str="已加到数据最后!";
MessageBox(_T("长度超过数据长度!")+str,_T("系统消息"),MB_ICONEXCLAMATION);}
DE.exportfile();
DE.MakeEmpty();
// TODO: 在此添加控件通知处理程序代码
}
最后修改按钮,输入学号,姓名,科目还有分数进行修改,四个编辑框,四个静态文本,一个按钮
void CDlg_changedata::OnBnClickedButton1()
{
UpdateData(TRUE);
List DF;
DF.inputfile();
string a=name4.GetBuffer();
string b=xuehao4.GetBuffer();
string c=subject.GetBuffer();
string d=grade.GetBuffer();
node *p=DF.Find1(b);
node *q=DF.Find2(a);
if(p==NULL||q==NULL)
MessageBox(_T("学号或姓名不存在,请检查!"),_T("系统消息"),MB_ICONEXCLAMATION);
else
{if(p->student.xuehao!=q->student.xuehao)
MessageBox(_T("姓名学号不是同一人,请检查"),_T("系统消息"),MB_ICONEXCLAMATION);
else
{
if(c=="语文")
{p->student.chinese=d;MessageBox(_T("已更改!"),_T("系统消息"),MB_ICONASTERISK);}
else if(c=="数学")
{p->student.math=d;MessageBox(_T("已更改!"),_T("系统消息"),MB_ICONASTERISK);}
else if(c=="英语")
{p->student.english=d;MessageBox(_T("已更改!"),_T("系统消息"),MB_ICONASTERISK);}
else if(c=="物理")
{p->student.physic=d;MessageBox(_T("已更改!"),_T("系统消息"),MB_ICONASTERISK);}
else if(c=="化学")
{p->student.chemical=d;MessageBox(_T("已更改!"),_T("系统消息"),MB_ICONASTERISK);}
else
MessageBox(_T("输入科目不存在,应为语文、数学、英语、物理和化学"),_T("系统消息"),MB_ICONEXCLAMATION);
DF.exportfile();
}
DF.MakeEmpty();}
// TODO: 在此添加控件通知处理程序代码
}
然后,顺便贴一下我自己编辑的链表类和对应的cpp文件代码:
//lianbiao.h
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct stinfo
{
string num;
string xuehao;
string name;
string chinese;
string math;
string english;
string physic;
string chemical;
};
//节点类的定义
class node
{
public:
node *next;
stinfo student;
node();
node(stinfo & A,node *p);
};
//线性表的定义
class List:public node
{
node *head;
int length;
public:
List(){head=new node;length=0;}
bool Insert(stinfo A,int i);
node *Find(int i);
node *Find1(string xuehao1);
node *Find2(string name);
bool Remove1(string name1);
bool Remove2(string xuehao1);
bool changegrade1(stinfo A);
void outputdata();
void output(node *p);
bool exportfile();
bool inputfile();
bool Remove3(string name,string xuehao);
void MakeEmpty();
};
//lianbiao.cpp
#include "stdafx.h"
#include "lianbiao.h"
node::node()
{
next=NULL;
}
node::node(stinfo & A,node *p)
{
next=p;
student.chemical=A.chemical;
student.chinese=A.chinese;
student.english=A.english;
student.math=A.math;
student.name=A.name;
student.physic=A.physic;
student.xuehao=A.xuehao;
student.num=A.num;
}
//删除函数3
bool List::Remove3(string name,string xuehao)
{
node *p=head,*q;
int a=0;
while(p->next!=NULL)
{
q=p;
p=p->next;
if(p->student.name==name&&p->student.xuehao==xuehao)
{a=1;break;}
}
if(a==0)
return false;
else
{
q->next=p->next;
delete p;
length--;
return true;
}
}
//在第i个位置增加结点
bool List::Insert(stinfo A,int i)
{
node *p=Find(i-1);
if (p==NULL)
{
node *p=head;
while(p->next!=NULL)
p=p->next;
node *newnode=new node(A,p->next);
p->next=newnode;
length++;
return false;}
else{
node *newnode=new node(A,p->next);
p->next=newnode;
length++;
return true;}
}
//找到第i个结点的位置
node* List::Find(int i)
{
if(i<0)return NULL;
if (i==0) return head;
node *p=head->next;
int j=1;
while(p!=NULL&&j<i)
{
p=p->next;
j++;
}
return p;
}
//找到对应学号的结点位置
node *List::Find1(string xuehao1)
{
node *p=head->next;
while(p!=NULL&&p->student.xuehao!=xuehao1)
{
p=p->next;
}
return p;
}
//找到对应名字的结点位置
node *List::Find2(string name)
{
node *p=head->next;
while(p!=NULL && p->student.name!=name)
{
p=p->next;
}
return p;
}
//根据学生名字消除信息
bool List::Remove1(string name)
{
node *p=head,*q;
int a=0;
while(p->next!=NULL)
{
if(p->next->student.name==name)
{
a=1;
break;
}
p=p->next;
}
if(a==0)
return false;
else
{
q=p->next;
p->next=q->next;
delete q;
length--;
return true;}
}
//根据学生学号消除信息
bool List::Remove2(string xuehao1)
{
node *p=head,*q;
int a=0;
while(p->next!=NULL)
{
if(p->next->student.xuehao==xuehao1)
{
a=1;
break;
}
p=p->next;
}
if(a==0)
return false;
else{
q=p->next;
p->next=q->next;
delete q;
length--;
return true;}
}
//输出所有的信息
void List::outputdata()
{
node *p=head;
while(p->next!=NULL)
{
p=p->next;
cout<<p->student.num<<" "<<p->student.xuehao<<" "<<p->student.name<<" "<<p->student.chinese<<" ";
cout<<p->student.math<<" "<<p->student.english<<" "<<p->student.physic<<" ";
cout<<p->student.chemical<<endl;
}
}
//输出某个结点的信息
void List::output(node *p)
{
cout<<p->student.num<<" "<<p->student.xuehao<<" "<<p->student.name<<" "<<p->student.chinese<<" ";
cout<<p->student.math<<" "<<p->student.english<<" "<<p->student.physic<<" ";
cout<<p->student.chemical<<endl;
}
//输出数据到文件
bool List::exportfile()
{
node *p=head;
ofstream outfile("stu.txt");
if(!outfile)
{
cerr<<"open error"<<endl;
abort();
}
while(p->next!=NULL)
{
p=p->next;
outfile<<p->student.num<<" "<<p->student.xuehao<<" "<<p->student.name<<" "<<p->student.chinese<<" ";
outfile<<p->student.math<<" "<<p->student.english<<" "<<p->student.physic<<" ";
if(p->next!=NULL)
outfile<<p->student.chemical<<endl;
else
outfile<<p->student.chemical;
}
outfile.close();
return true;
}
//输入数据到链表
bool List::inputfile()
{
node *p=head;
char ch;
fstream infile;
infile.open("stu.txt");
if(!infile)
{
cerr<<"open error"<<endl;
abort();
}
while(infile)
{
node *q=new node;
p->next=q;
p=p->next;
infile>>p->student.num>>p->student.xuehao>>p->student.name>>p->student.chinese;
infile>>p->student.math>>p->student.english>>p->student.physic;
infile>>p->student.chemical;
infile.get(ch);
}
infile.close();
return true;
}
//修改学生成绩
bool List::changegrade1(stinfo A)
{
node *p=head;
node *q;
q=Find2(A.name);
int i=0;
while(p->next!=NULL)
{
p=p->next;i++;
if(p->student.name==A.name)
break;
}
Remove2(A.xuehao);
Insert(A,i);
return true;
}
//清空函数
void List::MakeEmpty()
{
node *p=head->next;
int i=1;
while(i++<length)
{
head->next=p->next;
delete p;
}
length=0;
}