基于C++MFC的学生成绩管理系统

1.题目要求

学期末,班级要统计该学期考试成绩,计算每个人的学分绩点,并按照学分绩点、平均分进行排序。假设本学期开设的课程共有n门课程,每门课程均有名称、学分数;学生考试成绩的学分绩点根据考试成绩核对如下:
100分 5绩点;95-99分 4.5绩点;90-94分 4个绩点;
85-89分 3.5绩点 80-84分 3绩点,以此类推。

学生学期绩点计算方法如下:
∑(课程获取的绩点数 * 学分数)/∑学分数

提示:
1、学期所学课程的记录文件为lesson.txt,该文件共三列,第一列为课程编号,第二列为课程名称,第三列为课程学分;
2、考试成绩记录文件为grade.txt,该文件第一行为标题行,记录考生学号、姓名、考试课程;从第二行开始记录考生对应课程的考试成绩,形式如下:

请编写程序完成如下界面与功能:
基于C++MFC的学生成绩管理系统_第1张图片
1)读取课程时,对课程文件进行读取;
2)读取成绩时对成绩文件进行读取;
3)在课程信息列表中显示所有课程的基本信息;
4)在学生考试成绩信息列表中显示学生考试信息;
5)在学会考试信息列表中可对学生成绩进行修改,修改完成后,点击修改,则完成修改工作;点击保存时,将学生考试信息保存;
6)当点击查询时,对学生考试情况进行查询,弹出如下对话框
基于C++MFC的学生成绩管理系统_第2张图片
可以以学号或姓名查询,在学号或者姓名编辑框中输入学号或者姓名,点击查询,在下方的列表框中显示学生考试信息。

7)点击上个界面中的计算绩点按钮时,弹出如下界面
基于C++MFC的学生成绩管理系统_第3张图片
计算出每个学生的绩点;选择一种排序方法(生序排序或者降序排序),点击排序后,对列表中的数据进行排序;
点击保存按钮时,将排序后的结果输出到一个文件中,该文件中共有三列数据,如列表框中所示。

2.需求分析

用户利用此学生成绩管理系统,应得以实现以下主要功能:
(1)、“读取课程”:将既定lesson.txt中的课程信息读入系统,并在课程信息列表中显示出来;
(2)、“读取成绩”:将既定grade.txt中的学生成绩读入系统,并在学生考试信息列表中显示出来;
(3)、“修改”:对考试信息列表中学生成绩进行修改,并将改动保存至grade.txt;
(4)、“计算绩点”:对各学生平均绩点进行计算,在绩点统计列表中显示出来,并能根据需要,依照平均绩点进行升序或降序排列;
(5)、“查询”:能通过学生的姓名或学号,查询其各科考试成绩,并在信息查询列表中显示出来。

3.总体设计

为实现上述功能,应按照以下流程图构建系统:
基于C++MFC的学生成绩管理系统_第4张图片
主要的类:

(1)欢迎界面对话框的类

// WelcomeDlg 对话框

class WelcomeDlg : public CDialogEx
{
     
	DECLARE_DYNAMIC(WelcomeDlg)

public:
	WelcomeDlg(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~WelcomeDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum {
      IDD = IDD_DIALOG_WELCOME };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
};

(2)登录界面对话框的类

// LoginDlg 对话框

class LoginDlg : public CDialogEx
{
     
	DECLARE_DYNAMIC(LoginDlg)

public:
	LoginDlg(CWnd* pParent = nullptr);  // 标准构造函数
	virtual ~LoginDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum {
      IDD = IDD_DIALOG_LOGIN };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	CString m_szUsername;//Edit control控件值的变量,用于存储用户输入的“用户名”
	CString m_szPassward;//Edit control控件值的变量,用于存储用户输入的“密码”

(3)课程的类

class course
{
     
public:
	//cstr
	course() :code(""),cname(""), credit(0)
	{
     }
	course(CString _cname, CString _code, float _credit) :cname(_cname), code(_code), credit(_credit)
	{
     }
	//copy-cstr
	course(const course & c)
	{
     
		cname = c.cname;
		code = c.code;
		credit = c.credit;
	}
	//dstr
	virtual~course()
	{
     }
	//member of data
public:
	CString code; //课程编号
	CString cname; //课程名称
	float credit; //课程学分
};

(4)学生的类

class student
{
     
public:
	//cstr
	student() :sname(""), number(""), averpoint(0.0f), spoint(0.0f)
	{
     
		grade[3] = {
      0 };
	}
	student(CString _sname, CString _number, int _grade[3],float _averpoint, float _spoint) :sname(_sname), number(_number), averpoint(_averpoint), spoint(_spoint)
	{
     
		grade[0] = _grade[0];
		grade[1] = _grade[1];
		grade[2] = _grade[2];
	}
	//dstr
	virtual~student()
	{
     }
	//member of data
public:
	CString sname;//学生姓名
	CString number;//学生学号
	int grade[3];//假设共有三门考试科目,存储成绩的数组
	float averpoint;//学生的平均学分绩点GPA
	float spoint;//学生所有考试科目的总学分
};

(5)系统主界面对话框的类

// MainDlg 对话框

class MainDlg : public CDialogEx
{
     
	DECLARE_DYNAMIC(MainDlg)

public:
	MainDlg(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~MainDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum {
      IDD = IDD_DIALOG_MAIN };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	CListCtrl CourseList;//课程信息列表Listctrl的控件变量
	CListCtrl GradeList;//学生考试信息列表Listctrl的控件变量
CEdit m_edit;//供成绩修改用的Edit control
protected:
	CalPointDlg*cdlg;
	SearchDlg*sdlg;
public:
virtual BOOL OnInitDialog();
	afx_msg void OnBnClickedButtonGetcourse();//按“读取课程”时的操作
	afx_msg void OnBnClickedButtonGetscore();//按“读取成绩”时的操作
	afx_msg void OnBnClickedButtonCalculatepoint();//按“计算绩点”时的操作
	afx_msg void OnBnClickedButtonSearch();//按“查询”时的操作
afx_msg void OnBnClickedButtonChange();//按“修改”时的操作
	afx_msg void OnBnClickedButtonSave();//按“保存”时的操作
	afx_msg void OnLvnItemchangedListDisplayscore(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnNMDblclkListDisplayscore(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnEnKillfocusEditChange();//使供成绩修改用的Edit control失焦的操作
};

(6)“计算绩点”子界面对话框的类

// CalPointDlg 对话框

class CalPointDlg : public CDialogEx
{
     
	DECLARE_DYNAMIC(CalPointDlg)

public:
	CalPointDlg(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~CalPointDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum {
      IDD = IDD_DIALOG_CALPOINT };
#endif

public:
	void calaverpoint();//计算学生平均学分绩点的函数
	float calgradepoint(int i);//计算单科绩点的函数
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	CListCtrl PointList;//绩点统计列表Listctrl的控件变量
	virtual BOOL OnInitDialog();
	afx_msg void OnBnClickedButtonSaverank();//按“保存”时的操作
	afx_msg void OnBnClickedRadioUp();//选择“升序排列”时的操作
	afx_msg void OnBnClickedRadioDown();//选择“降序排列”时的操作
	afx_msg void OnBnClickedButtonRamk();//按“排序”时的操作
};

(7)“查询”子界面对话框的类

// SearchDlg 对话框

class SearchDlg : public CDialogEx
{
     
	DECLARE_DYNAMIC(SearchDlg)

public:
	SearchDlg(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~SearchDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum {
      IDD = IDD_DIALOG_SEARCH };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	CListCtrl SearchList;//信息查询列表Listctrl的控件变量
	virtual BOOL OnInitDialog();
	afx_msg void OnBnClickedButtonSearch();//按“查询”时的操作
public:
	CString SearchNumber;//Edit control控件值的变量,用于存储待查询学生的“学号”
	CString SearchName;//Edit control控件值的变量,用于存储待查询学生的“姓名”
};

4.详细设计

具体函数代码:

(1)MFCApplication(学生成绩管理系统).cpp

BOOL CMFCApplication学生成绩管理系统App::InitInstance()
{
     
// 自己添加部分
	WelcomeDlg wdlg;//建一个欢迎对话框类的对象
	if (wdlg.DoModal() == IDOK)//程序运行时弹出对话框,选择“登录”时执行以下操作
	{
     
		LoginDlg ldlg;//建一个登录对话框类的对象
		if (ldlg.DoModal() != IDOK)return FALSE;程序运行时弹出对话框,选择“离开”时退出系统
		if (ldlg.m_szUsername != TEXT("Snoopy") || ldlg.m_szPassward != TEXT("981210"))
		{
     
			MessageBox(NULL, TEXT("用户名或密码错误"), TEXT("信息错误"), MB_OK | MB_ICONERROR);
			return FALSE;
		}//如用户名、密码均正确,按“登录”时执行以下操作
		MainDlg mdlg;//建一个主界面对话框的类
		MessageBox(NULL, TEXT("请先读取课程及成绩哦~"), TEXT("温馨提示"), MB_OK);
		mdlg.DoModal();//模态对话框,主界面弹出
		MessageBox(NULL, TEXT("欢迎您再次使用本系统!"), TEXT("THANKS"), MB_OK);
		return FALSE;
	}
	return FALSE;选择“退出”时,退出系统
}

(2)MainDlg.cpp//主界面对话框类中主要函数的具体实现

// MainDlg 对话框

IMPLEMENT_DYNAMIC(MainDlg, CDialogEx)

MainDlg::MainDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG_MAIN, pParent)
{
     
	cdlg = NULL;//初始时,将课程信息列表Listctrl的指针变量指向空
	sdlg = NULL;//初始时,将学生考试信息列表Listctrl的指针变量指向空
}

MainDlg::~MainDlg()
{
     
	if (cdlg)//析构时,释放课程信息列表Listctrl的指针指向空间
	{
     
		delete cdlg;
		cdlg = NULL;
	}
	if (sdlg)//析构时,释放学生考试信息列表Listctrl的指针指向空间
	{
     
		delete sdlg;
		sdlg = NULL;
	}
}

void MainDlg::DoDataExchange(CDataExchange* pDX)
{
     
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_DISPLAYCOURSE, CourseList);
	DDX_Control(pDX, IDC_LIST_DISPLAYSCORE, GradeList);
	DDX_Control(pDX, IDC_EDIT_CHANGEGRADE, m_edit);
}

BEGIN_MESSAGE_MAP(MainDlg, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON_GETCOURSE, &MainDlg::OnBnClickedButtonGetcourse)
	ON_BN_CLICKED(IDC_BUTTON_GETSCORE, &MainDlg::OnBnClickedButtonGetscore)
	ON_BN_CLICKED(IDC_BUTTON_CALCULATEPOINT, &MainDlg::OnBnClickedButtonCalculatepoint)
	ON_BN_CLICKED(IDC_BUTTON_SEARCH, &MainDlg::OnBnClickedButtonSearch)
	ON_BN_CLICKED(IDC_BUTTON_SAVE, &MainDlg::OnBnClickedButtonSave)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_DISPLAYSCORE, &MainDlg::OnLvnItemchangedListDisplayscore)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST_DISPLAYSCORE, &MainDlg::OnNMDblclkListDisplayscore)
	ON_EN_KILLFOCUS(IDC_EDIT_CHANGEGRADE, &MainDlg::OnEnKillfocusEditChange)
	ON_BN_CLICKED(IDC_BUTTON_CHANGE, &MainDlg::OnBnClickedButtonChange)
END_MESSAGE_MAP()

// MainDlg 消息处理程序

BOOL MainDlg::OnInitDialog()//主界面对话框初始化时的操作
{
     
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	m_edit.ShowWindow(SW_HIDE);

	CourseList.InsertColumn(0, _T("课程编号"));//课程信息列表显示的表头
	CourseList.SetColumnWidth(0, 80);
	CourseList.InsertColumn(1, _T("课程名称"));
	CourseList.SetColumnWidth(1, 80);
	CourseList.InsertColumn(2, _T("课程学分"));
	CourseList.SetColumnWidth(2, 80);

	CourseList.SetExtendedStyle(CourseList.GetExtendedStyle() | LVS_EX_GRIDLINES );//课程信息列表网格线风格

	GradeList.InsertColumn(0, _T("学号"));//学生考试信息列表显示的表头
	GradeList.SetColumnWidth(0, 70);
	GradeList.InsertColumn(1, _T("姓名"));
	GradeList.SetColumnWidth(1, 60);
	GradeList.InsertColumn(2, _T("C++成绩"));
	GradeList.SetColumnWidth(2, 70);
	GradeList.InsertColumn(3, _T("大学物理C1成绩"));
	GradeList.SetColumnWidth(3, 100);
	GradeList.InsertColumn(4, _T("高等数学A2成绩"));
	GradeList.SetColumnWidth(4, 100);

	GradeList.SetExtendedStyle(GradeList.GetExtendedStyle() | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);//学生考试信息列表网格线及选择后整行高亮风格

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

void MainDlg::OnBnClickedButtonGetcourse()//按“读取课程”时的操作
{
     
	lessonfile = "C:\\Users\\Lenovo\\Desktop\\C++\\MFCApplication(学生成绩管理系统)\\lesson.txt";
	if (lessonfile.empty())//如未能找到制定的lesson.txt文件
	{
     
		MessageBox(TEXT("课程文件读取过程有误"), TEXT("错误提示"), MB_OK);
	}
	ifstream infile;
	infile.open(lessonfile, ios::in);
	if (!infile)//如与lesson.txt建立联系失败
	{
     
		MessageBox(TEXT("课程文件读取过程有误"), TEXT("错误提示"), MB_OK);
	}
	char buffer[256];
	infile.getline(buffer, 256);//储存第一行的内容
	CourseList.RemoveAllGroups();
	veccourse.resize(3);
	string temcode, temcname;
	for (int i = 0; i<3; i++)
	{
     
		infile >>temcode >> temcname >> veccourse[i].credit;
		veccourse[i].code = temcode.c_str();//string类型转CString类型
		veccourse[i].cname = temcname.c_str();
	}
	infile.close();
	CourseList.DeleteAllItems();//先清除课程信息列表Listctrl中的内容
	for (int i = 0; i < 3; i++)//将课程信息显示在课程信息列表中
	{
     
		CourseList.InsertItem(i, _T(""));
		CourseList.SetItemText(i, 0, veccourse[i].code);
		CourseList.SetItemText(i, 1, veccourse[i].cname);
		CString str;
		str.Format(_T("%f"), veccourse[i].credit);//float类型转CString类型
		CourseList.SetItemText(i, 2, str);
	}
}

void MainDlg::OnBnClickedButtonGetscore()//按“读取成绩”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	gradefile = "C:\\Users\\Lenovo\\Desktop\\C++\\MFCApplication(学生成绩管理系统)\\grade.txt";
	if (gradefile.empty())
	{
     
		MessageBox(TEXT("课程文件读取过程有误"), TEXT("错误提示"), MB_OK);
	}
	ifstream infile;
	infile.open(gradefile, ios::in);
	if (!infile)
	{
     
		MessageBox(TEXT("课程文件读取过程有误"), TEXT("错误提示"), MB_OK);
	}
	char buffer[256];
	infile.getline(buffer, 256);
	GradeList.RemoveAllGroups();
	string temnumber, temsname;
	student st;
	vecstudent.clear();//每次执行“读取成绩”时,都先清除掉容器原有的学生信息
	while(!infile.eof())//一直从grade.txt中读入,直到文件尾
	{
     
		temnumber = "";
		infile >> temnumber >> temsname >> st.grade[0]>>st.grade[1]>>st.grade[2];
		st.number = temnumber.c_str();
		st.sname = temsname.c_str();
		if(temnumber!="")//避免光标在最后一行下一行初保存,造成的最后一行内容显示两次
		vecstudent.push_back(st);
	}
	infile.close();
	GradeList.DeleteAllItems();
	int n = vecstudent.size();
	for (int i = 0; i < n; i++)
	{
     
		GradeList.InsertItem(i, _T(""));
		GradeList.SetItemText(i, 0, vecstudent[i].number);
		GradeList.SetItemText(i, 1, vecstudent[i].sname);
		CString str;
		str.Format(_T("%d"), vecstudent[i].grade[0]);//int类型转CString类型
		GradeList.SetItemText(i, 2, str);
		str.Format(_T("%d"), vecstudent[i].grade[1]);
		GradeList.SetItemText(i, 3, str);
		str.Format(_T("%d"), vecstudent[i].grade[2]);
		GradeList.SetItemText(i, 4, str);
	}
}

void MainDlg::OnBnClickedButtonCalculatepoint()//按“计算绩点”时的操作

{
     
	// TODO: 在此添加控件通知处理程序代码
	if (cdlg == NULL)//非模态对话框,弹出“计算绩点”的子界面
	{
     
		cdlg = new CalPointDlg;
		cdlg->Create(IDD_DIALOG_CALPOINT);
		cdlg->ShowWindow(SW_SHOWNORMAL);
		cdlg->UpdateWindow();
	}
	else
	{
     
		cdlg->ShowWindow(SW_SHOWNORMAL);
		cdlg->UpdateWindow();
	}
}

void MainDlg::OnBnClickedButtonSearch()//按“查询”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	MessageBox(TEXT("请输入学号或姓名进行查询~"), TEXT("温馨提示"), MB_OK);
	if (sdlg == NULL)
	{
     
		sdlg = new SearchDlg;
		sdlg->Create(IDD_DIALOG_SEARCH);
		sdlg->ShowWindow(SW_SHOWNORMAL);
		sdlg->UpdateWindow();
	}
	else
	{
     
		sdlg->ShowWindow(SW_SHOWNORMAL);
		sdlg->UpdateWindow();
	}
}

void MainDlg::OnNMDblclkListDisplayscore(NMHDR *pNMHDR, LRESULT *pResult)//鼠标左键双击学生考试信息列表时的操作,对Listctrl中学生成绩进行修改
{
     
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	CRect rc;
	m_Row = pNMListView->iItem;//获得选中的行
	m_Col = pNMListView->iSubItem;//获得选中列

	if (pNMListView->iSubItem>1) //如果选择的是成绩子项;
	{
     
		GradeList.GetSubItemRect(m_Row, m_Col, LVIR_LABEL, rc);//获得子项的RECT;
		m_edit.SetParent(&GradeList);//转换坐标为列表框中的坐标
		m_edit.MoveWindow(rc);//移动Edit到RECT坐在的位置;
		m_edit.SetWindowText(GradeList.GetItemText(m_Row, m_Col));//将该子项中的值放在Edit控件中;
		m_edit.ShowWindow(SW_SHOW);//显示Edit控件;
		m_edit.SetFocus();//设置Edit焦点
		m_edit.ShowCaret();//显示光标
		m_edit.SetSel(-1);//将光标移动到最后
	}

	*pResult = 0;
}

void MainDlg::OnEnKillfocusEditChange()使供成绩修改用的Edit control失焦的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	CString tem;
	m_edit.GetWindowText(tem);    //得到用户输入的新的内容
	GradeList.SetItemText(m_Row, m_Col, tem);   //设置编辑框的新内容
	m_edit.ShowWindow(SW_HIDE);                //应藏编辑框
}

void MainDlg::OnBnClickedButtonChange()//按“修改”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	if(m_Row==-1&&m_Col==-1)
		MessageBox(TEXT("您未进行成绩修改"), TEXT("温馨提示"), MB_OK);
	else
	{
     
		int temgrade;
		temgrade = _ttoi(GradeList.GetItemText(m_Row, m_Col));//CString类型转int类型
		vecstudent[m_Row].grade[m_Col - 2] = temgrade;//将修改后的成绩存入容器中对应位置
		MessageBox(TEXT("修改成功"), TEXT("成功提示"), MB_OK);
	}
}

void MainDlg::OnBnClickedButtonSave()//按“保存”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	MessageBox(TEXT("此功能仅适用于修改后的保存~"), TEXT("温馨提示"), MB_OK);
	gradefile = "C:\\Users\\Lenovo\\Desktop\\C++\\MFCApplication(学生成绩管理系统)\\grade.txt";
	ofstream outfile;
	outfile.open(gradefile, ios::out);
	if (!outfile)
	{
     
		MessageBox(TEXT("文件保存过程有误"), TEXT("错误提示"), MB_OK);
	}
	outfile << "学号	姓名	C++成绩	大学物理C1成绩	高等数学A2成绩" << endl;
	size_t n = vecstudent.size();
	string temsname, temnumber;
	for (size_t i = 0; i<n; i++)
	{
     
		temsname = CT2A(vecstudent[i].sname);//CString类型转string类型
		temnumber = CT2A(vecstudent[i].number);
		outfile << temnumber << "	" << temsname <<"	" << vecstudent[i].grade[0] << setw(16) << vecstudent[i].grade[1] << setw(30) << vecstudent[i].grade[2]<< endl;
	}
	outfile.close();
	MessageBox(TEXT("文件保存成功"), TEXT("成功提示"), MB_OK);
}

(3)CalPointDlg.cpp//“计算绩点”子界面对话框类中主要函数的具体实现

extern vector<student> vecstudent;
extern vector<course> veccourse;
string rankfile;
int ranktype = 0;//用于判断依据绩点排序类型(升序排列、降序排列)的变量

// CalPointDlg 对话框

IMPLEMENT_DYNAMIC(CalPointDlg, CDialogEx)

CalPointDlg::CalPointDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG_CALPOINT, pParent)
{
     
}

CalPointDlg::~CalPointDlg()
{
     
}

void CalPointDlg::DoDataExchange(CDataExchange* pDX)
{
     
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_POINT, PointList);
}

BEGIN_MESSAGE_MAP(CalPointDlg, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON_SAVERANK, &CalPointDlg::OnBnClickedButtonSaverank)
	ON_BN_CLICKED(IDC_RADIO_UP, &CalPointDlg::OnBnClickedRadioUp)
	ON_BN_CLICKED(IDC_RADIO_DOWN, &CalPointDlg::OnBnClickedRadioDown)
	ON_BN_CLICKED(IDC_BUTTON_RAMK, &CalPointDlg::OnBnClickedButtonRamk)
END_MESSAGE_MAP()

// CalPointDlg 消息处理程序
float CalPointDlg::calgradepoint(int i)//计算单科绩点的函数
{
     
	if (i == 100)
		return 5.0;
	else if (i >= 95)
		return 4.5;
	else if (i >= 90)
		return 4.0;
	else if (i >= 85)
		return 3.5;
	else if (i >= 80)
		return 3.0;
	else if (i >= 75)
		return 2.5;
	else if (i >= 70)
		return 2.0;
	else if (i >= 65)
		return 1.5;
	else if (i >= 60)
		return 1.0;
	else
		return 0.0;
}

void CalPointDlg::calaverpoint() //计算学生平均学分绩点的函数
{
     
	float scredit = veccourse[0].credit + veccourse[1].credit + veccourse[2].credit;
	size_t n = vecstudent.size();
	for (size_t t = 0; t<n; t++)
	{
     
		for (int i = 0; i < 3; i++)
		{
     
			vecstudent[t].spoint += calgradepoint(vecstudent[t].grade[i])* veccourse[i].credit;
		}
		vecstudent[t].averpoint = vecstudent[t].spoint / scredit;
		vecstudent[t].averpoint = ((float)((int)(vecstudent[t].averpoint * 100))) / 100;//使平均绩点只保留小数点后两位
	}
}

BOOL CalPointDlg::OnInitDialog()
{
     
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化

	PointList.InsertColumn(0, _T("学号"));//绩点统计列表显示的表头
	PointList.SetColumnWidth(0, 70);
	PointList.InsertColumn(1, _T("姓名"));
	PointList.SetColumnWidth(1, 60);
	PointList.InsertColumn(2, _T("绩点"));
	PointList.SetColumnWidth(2, 70);

	PointList.SetExtendedStyle(PointList.GetExtendedStyle() | LVS_EX_GRIDLINES);

	calaverpoint();//计算所有学生各自的平均绩点

	PointList.DeleteAllItems();
	int n = vecstudent.size();//获取总学生数
	for (int i = 0; i < n; i++)
	{
     
		PointList.InsertItem(i, _T(""));
		PointList.SetItemText(i, 0, vecstudent[i].number);
		PointList.SetItemText(i, 1, vecstudent[i].sname);
		CString str;
		str.Format(_T("%f"), vecstudent[i].averpoint);
		PointList.SetItemText(i, 2, str);
	}

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

void CalPointDlg::OnBnClickedRadioUp()选择“升序排列”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	ranktype = 1;
}

void CalPointDlg::OnBnClickedRadioDown()选择“降序排列”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	ranktype = 2;
}

void CalPointDlg::OnBnClickedButtonRamk()//按“排序”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	size_t n = vecstudent.size();
	for (size_t t = 0; t<n - 1; t++)
	{
     
		for (int i = 0; i < n - t - 1; i++)
		{
     
			if (ranktype == 1)//依据平均绩点升序排列并使存储学生信息的容器同步更新
			{
     
				if (vecstudent[i].averpoint < vecstudent[i + 1].averpoint)
				{
     
					student s = vecstudent[i];;
					vecstudent[i] = vecstudent[i + 1];
					vecstudent[i + 1] = s;
				}
			}
			else if (ranktype == 2)//依据平均绩点降序排列并使存储学生信息的容器同步更新
			{
     
				if (vecstudent[i].averpoint > vecstudent[i + 1].averpoint)
				{
     
					student s = vecstudent[i];;
					vecstudent[i] = vecstudent[i + 1];
					vecstudent[i + 1] = s;
				}
			}
		}
	}
	PointList.DeleteAllItems();//清除绩点统计列表中原有内容
	for (int i = 0; i < n; i++)//在绩点统计列表中显示出排序后的各学生平均绩点信息
	{
     
		PointList.InsertItem(i, _T(""));
		PointList.SetItemText(i, 0, vecstudent[i].number);
		PointList.SetItemText(i, 1, vecstudent[i].sname);
		CString str;
		str.Format(_T("%f"), vecstudent[i].averpoint);
		PointList.SetItemText(i, 2, str);
	}
}

void CalPointDlg::OnBnClickedButtonSaverank()//按“排序”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	rankfile = "C:\\Users\\Lenovo\\Desktop\\C++\\MFCApplication(学生成绩管理系统)\\rank.txt";//将按已选择的排序方式排列后的学生信息输出至rank.txt
	ofstream outfile;
	outfile.open(rankfile, ios::out);
	if (!outfile)
	{
     
		MessageBox(TEXT("文件保存过程有误"), TEXT("错误提示"), MB_OK);
	}
	outfile << "姓名	学号	平均绩点" << endl;
	size_t n = vecstudent.size();
	string temsname, temnumber;
	for (size_t i = 0; i<n; i++)
	{
     
		temsname=CT2A(vecstudent[i].sname);
		temnumber=CT2A(vecstudent[i].number);
		outfile << temsname << "	" << temnumber << setw(11) << vecstudent[i].averpoint << endl;
	}
	outfile.close();
	MessageBox(TEXT("文件保存成功"), TEXT("成功提示"), MB_OK);
}

(4)SearchDlg.cpp//“查询”子界面对话框类中主要函数的具体实现

extern vector<student> vecstudent;

// SearchDlg 对话框

IMPLEMENT_DYNAMIC(SearchDlg, CDialogEx)

SearchDlg::SearchDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG_SEARCH, pParent)
	, SearchNumber(_T(""))//初始时,待查询学生的“学号”置为空
	, SearchName(_T(""))//初始时,待查询学生的“姓名”置为空
{
     
}

SearchDlg::~SearchDlg()
{
     
}

void SearchDlg::DoDataExchange(CDataExchange* pDX)
{
     
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_SEARCH, SearchList);
	DDX_Text(pDX, IDC_EDIT_NUMBERSEARCH, SearchNumber);
	DDX_Text(pDX, IDC_EDIT_NAMESEARCH, SearchName);
}

BEGIN_MESSAGE_MAP(SearchDlg, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON_SEARCH, &SearchDlg::OnBnClickedButtonSearch)
END_MESSAGE_MAP()

// SearchDlg 消息处理程序

BOOL SearchDlg::OnInitDialog()
{
     
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化

	SearchList.InsertColumn(0, _T("考试科目"));//信息查询列表显示的表头
	SearchList.SetColumnWidth(0, 80);
	SearchList.InsertColumn(1, _T("成绩"));
	SearchList.SetColumnWidth(1, 80);

	SearchList.SetExtendedStyle(SearchList.GetExtendedStyle() | LVS_EX_GRIDLINES);

	SearchList.InsertItem(0, _T("C++"));//信息查询列表第一列显示的内容
	SearchList.InsertItem(1, _T("大学物理C1"));
	SearchList.InsertItem(2, _T("高等数学A2"));

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

void SearchDlg::OnBnClickedButtonSearch()//按“查询”时的操作
{
     
	// TODO: 在此添加控件通知处理程序代码
	int searchednumber = -1;//用于记录待查找学生是容器中第几个的变量
	UpdateData(TRUE);//将Edit control中的值随时更新到对应变量中
	int n = vecstudent.size();
	if (SearchNumber != ""&& SearchName == "")//如果只输入了“学号”
	{
     
		for (int i = 0; i < n; i++)
		{
     
			if (SearchNumber == vecstudent[i].number) searchednumber = i;
		}
	}
	else if (SearchNumber == "" && SearchName != "")//如果只输入了“姓名”
	{
     
		for (int i = 0; i < n; i++)
		{
     
			if (SearchName == vecstudent[i].sname) searchednumber = i;
		}
	}
	else if (SearchNumber != ""&& SearchName != "")//如果“学号”和“姓名”都输入了
	{
     
		searchednumber = -2;
		for (int i = 0; i < n; i++)
		{
     
			if (SearchNumber == vecstudent[i].number)
			{
     
				if (SearchName == vecstudent[i].sname) searchednumber = i;
			}
		}
	}
	if (searchednumber == -1)
		MessageBox(TEXT("您要找的学生不存在"), TEXT("错误提示"), MB_OK);
	else if (searchednumber == -2)
		MessageBox(TEXT("您输入的学号与姓名不匹配"), TEXT("错误提示"), MB_OK);
	Else//将查找到的学生各科考试成绩信息显示到信息查询列表中
	{
     
		CString str;
		str.Format(_T("%d"), vecstudent[searchednumber].grade[0]);
		SearchList.SetItemText(0, 1, str);
		str.Format(_T("%d"), vecstudent[searchednumber].grade[1]);
		SearchList.SetItemText(1, 1, str);
		str.Format(_T("%d"), vecstudent[searchednumber].grade[2]);
		SearchList.SetItemText(2, 1, str);
	}
}

5.上机操作

(1)、程序运行,弹出欢迎界面
基于C++MFC的学生成绩管理系统_第5张图片
(2)、按“登录”键,弹出登录界面
基于C++MFC的学生成绩管理系统_第6张图片
(3)、正确输入用户名、密码后,按“登录”进入系统(用户这部分我没有做过多拓展,仅提供了一个用户用于测试,可以根据实际需要再完善鸭)
基于C++MFC的学生成绩管理系统_第7张图片
点击“确定”后,弹出主界面
基于C++MFC的学生成绩管理系统_第8张图片
(4)、按“读取课程”,lesson.txt中的课程信息在右侧列表中显示
基于C++MFC的学生成绩管理系统_第9张图片基于C++MFC的学生成绩管理系统_第10张图片
(5)、按“读取成绩”,grade.txt中的课程信息在下方列表中显示
基于C++MFC的学生成绩管理系统_第11张图片基于C++MFC的学生成绩管理系统_第12张图片
(6)、选择“计算绩点”,子界面弹出
基于C++MFC的学生成绩管理系统_第13张图片
选择“升序排列”或“降序排列”后,按“排序”,列表中信息按排序后的顺序显示
基于C++MFC的学生成绩管理系统_第14张图片基于C++MFC的学生成绩管理系统_第15张图片
排序后,按“保存”(以升序排列为例),提示保存成功
基于C++MFC的学生成绩管理系统_第16张图片
此时打开rank.txt,发现信息已存入
基于C++MFC的学生成绩管理系统_第17张图片
(7)、选择“查询”,出现温馨提示
基于C++MFC的学生成绩管理系统_第18张图片
点击“确定”,子界面弹出
基于C++MFC的学生成绩管理系统_第19张图片
输入学生学号或姓名,按“查询”,此学生成绩在下方列表中显示
基于C++MFC的学生成绩管理系统_第20张图片基于C++MFC的学生成绩管理系统_第21张图片
(8)、双击要修改的成绩,弹出编辑框进行修改
基于C++MFC的学生成绩管理系统_第22张图片
修改后单击其它地方,列表中学生成绩信息更新
基于C++MFC的学生成绩管理系统_第23张图片
按“修改”,弹出成功提示
基于C++MFC的学生成绩管理系统_第24张图片
(9)、按“保存”,弹出温馨提示、成功提示
基于C++MFC的学生成绩管理系统_第25张图片基于C++MFC的学生成绩管理系统_第26张图片
再次打开grade.txt,发现信息已同步修改
基于C++MFC的学生成绩管理系统_第27张图片
(10)、按“退出”,退出系统
基于C++MFC的学生成绩管理系统_第28张图片
(画外音:测试数据都是自己编哒,然后数据量比较小hhh,可以自行多搞些数据康康效果~)

参考博文:
[1]:CSDN 《VC 双击编辑ListControl中的数据》 :原文地址

你可能感兴趣的:(c++,mfc)