应用MFC应用程序实现学生信息管理系统
(1)、设计一个学生类Student,包括数据成员:姓名、学号、二门课程(面向对象程序设计、高等数学)的成绩。
(2)、创建一个管理学生的类Management,包括实现学生的数据的增加、删除、修改、按课程成绩排序、保存学生数据到文件及加载文件中的数据等功能。
(3)、创建一个基于对话框的MFC应用程序,程序窗口的标题上有你姓名、学号和应用程序名称。使用(1)和(2)中的类,实现对学生信息和成绩的输入和管理。
(4)、创建一个单文档的MFC应用程序,读取(3)中保存的文件中的学生成绩,分别用直方图和折线方式显示所有学生某课程的成绩分布图。
// Student Information Management SystemDlg.h: 头文件
#pragma once
// CStudentInformationManagementSystemDlg 对话框
class CStudentInformationManagementSystemDlg : public CDialogEx
{
// 构造
public:
CStudentInformationManagementSystemDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_STUDENTINFORMATIONMANAGEMENTSYSTEM_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedAddButton();
afx_msg void OnBnClickedDeleteButton();
afx_msg void OnBnClickedChangeButton();
afx_msg void OnBnClickedDataButton();
afx_msg void OnBnClickedFileSaveButton();
afx_msg void OnBnClickedFileLoadButton();
afx_msg void OnBnClickedSearchButton();
afx_msg void OnBnClickedSortButton();
CListCtrl m_List;
// 排序选择
CComboBox m_Combo;
friend class Management;
};
// Student Information Management SystemDlg.cpp: 实现文件
#include "pch.h"
#include "framework.h"
#include "Student Information Management System.h"
#include "Student Information Management SystemDlg.h"
#include "afxdialogex.h"
#include "CAddStudentDlg.h"
#include "Student.h"
#include
#include
#include
#include
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CStudentInformationManagementSystemDlg 对话框
CStudentInformationManagementSystemDlg::CStudentInformationManagementSystemDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_STUDENTINFORMATIONMANAGEMENTSYSTEM_DIALOG, pParent)
{
//m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);//设置图标
}
void CStudentInformationManagementSystemDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST, m_List);
DDX_Control(pDX, IDC_SORT_COMBO, m_Combo);
}
BEGIN_MESSAGE_MAP(CStudentInformationManagementSystemDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_ADD_BUTTON, &CStudentInformationManagementSystemDlg::OnBnClickedAddButton)
ON_BN_CLICKED(IDC_DELETE_BUTTON, &CStudentInformationManagementSystemDlg::OnBnClickedDeleteButton)
ON_BN_CLICKED(IDC_CHANGE_BUTTON, &CStudentInformationManagementSystemDlg::OnBnClickedChangeButton)
ON_BN_CLICKED(IDC_DATA_BUTTON, &CStudentInformationManagementSystemDlg::OnBnClickedDataButton)
ON_BN_CLICKED(IDC_FILE_SAVE_BUTTON, &CStudentInformationManagementSystemDlg::OnBnClickedFileSaveButton)
ON_BN_CLICKED(IDC_FILE_LOAD_BUTTON, &CStudentInformationManagementSystemDlg::OnBnClickedFileLoadButton)
ON_BN_CLICKED(IDC_SEARCH_BUTTON, &CStudentInformationManagementSystemDlg::OnBnClickedSearchButton)
ON_BN_CLICKED(IDC_SORT_BUTTON, &CStudentInformationManagementSystemDlg::OnBnClickedSortButton)
END_MESSAGE_MAP()
// CStudentInformationManagementSystemDlg 消息处理程序
BOOL CStudentInformationManagementSystemDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
//在窗口左上角设置自己的姓名和学号(课设要求)
CString str = "学生信息管理系统";
SetWindowText(str);
//设置数据显示区
m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);//整行选择、网格线
m_List.InsertColumn(0, "姓名", LVCFMT_CENTER, 100);
m_List.InsertColumn(1, "性别", LVCFMT_CENTER, 100);
m_List.InsertColumn(2, "学号", LVCFMT_CENTER, 100);
m_List.InsertColumn(3, "高等数学", LVCFMT_CENTER, 100);
m_List.InsertColumn(4, "课程设计", LVCFMT_CENTER, 100);
m_List.InsertColumn(5, "总分", LVCFMT_CENTER, 100);
//排序函数
//读取文件函数
theApp.m_Management.LoadFile(&m_List);
//设置排序选择按钮
m_Combo.AddString(_T("总分"));
m_Combo.AddString(_T("课设"));
m_Combo.AddString(_T("高数"));
m_Combo.AddString(_T("学号"));
m_Combo.SetCurSel(2);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CStudentInformationManagementSystemDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CStudentInformationManagementSystemDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
//添加数据按钮
void CStudentInformationManagementSystemDlg::OnBnClickedAddButton()
{
// TODO: 在此添加控件通知处理程序代码
theApp.m_Management.AddStudent(&m_List);
}
//删除数据按钮
void CStudentInformationManagementSystemDlg::OnBnClickedDeleteButton()
{
theApp.m_Management.DeleteStudent(&m_List);
}
//修改数据按钮
void CStudentInformationManagementSystemDlg::OnBnClickedChangeButton()
{
// TODO: 在此添加控件通知处理程序代码
POSITION pos = m_List.GetFirstSelectedItemPosition();//找到当前选中行
if (pos == NULL)
{
MessageBox(_T("请选择要修改的数据!"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
else
{
//将当前选中行数据写入临时变量
Student temp;
int nItem = m_List.GetNextSelectedItem(pos);
char tempgender[20];
m_List.GetItemText(nItem, 0, temp.name, sizeof(temp.name));
m_List.GetItemText(nItem, 1, tempgender, sizeof(tempgender));
m_List.GetItemText(nItem, 2, temp.ID, sizeof(temp.ID));
m_List.GetItemText(nItem, 3, temp.math, sizeof(temp.math));
m_List.GetItemText(nItem, 4, temp.program, sizeof(temp.program));
if (strcmp(tempgender,"女"))
{
temp.gender = true;
}
else
{
temp.gender = false;
}
//将临时变量写入全局变量m_student方便CAddStudentDlg调用
theApp.m_student=temp;
theApp.Tell = true;//CAddStudentDlg区分添加信息还是修改信息的关键
theApp.m_Management.ChangeStudent(&m_List);//
theApp.Tell = false;//还原默认值(默认为添加数据)
}
}
//数据分析按钮
void CStudentInformationManagementSystemDlg::OnBnClickedDataButton()
{
// TODO: 在此添加控件通知处理程序代码
ShellExecute(NULL, "open", "C:\\Users\\17810\\source\\repos\\课程设计—学生信息管理系统\\DrawData\\Debug\\DrawData.exe", NULL, NULL, SW_SHOWNORMAL);
}
//导出数据按钮
void CStudentInformationManagementSystemDlg::OnBnClickedFileSaveButton()
{
theApp.m_Management.SaveToFile(&m_List);
}
//导入数据按钮
void CStudentInformationManagementSystemDlg::OnBnClickedFileLoadButton()
{
theApp.m_Management.GetFromFile(&m_List);
}
//查找按钮
void CStudentInformationManagementSystemDlg::OnBnClickedSearchButton()
{
// TODO: 在此添加控件通知处理程序代码
//将编辑框内容写入临时变量str
char str[20];
GetDlgItemText(IDC_SEARCH_EDIT, str, sizeof(str)); //获取编辑框的信息
if ((CString)str == "")
{
MessageBox(_T("请输入姓名或学号"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
//查找函数
int nCount = m_List.GetItemCount();//listCtrl中的总行数
int i = 0, j = -1; // j是返回值,返回查找到的数据的行号
if (IDC_ID_RADIO== GetCheckedRadioButton(IDC_ID_RADIO, IDC_NAME_RADIO))//如果输入的是学号
{
while (i < nCount)
{
if (m_List.GetItemText(i, 2) == (CString)str)
{
j = i;
break;
}
i++;
}
}
else
{
while (i < nCount)
{
if (m_List.GetItemText(i, 0) == (CString)str)
{
j = i;
break;
}
i++;
}
}
if (j!=-1)
{
//高亮显示选中行
m_List.SetFocus();
m_List.SetItemState(j, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
m_List.EnsureVisible(j, FALSE);
}
else
{
MessageBox(_T("没有找到该学生,请检查输入!"), _T("警告"), MB_OK | MB_ICONWARNING);
}
}
//排序按钮
void CStudentInformationManagementSystemDlg::OnBnClickedSortButton()
{
// TODO: 在此添加控件通知处理程序代码
int nSel = m_Combo.GetCurSel();//取得当前选中项
theApp.m_Management.SortStudents(&m_List,nSel);//排序函数
}
#pragma once
class Student
{
public:
Student();
~Student();
char name[20];
char ID[20];
bool gender;
char math[5];
char program[5];
char sum[5];
void Sum();
friend class Management;
};
#include "pch.h"
#include "Student.h"
Student::Student()
{
}
Student ::~Student()
{
}
void Student::Sum()
{
int Math = atoi(math);//类型转换
int Program = atoi(program);
int all = Math + Program;
_itoa_s(all, sum, 10);//写入类中
}
#pragma once
#include
#include
#include "Student Information Management SystemDlg.h"
#include
#include "CAddStudentDlg.h"
#include "Student.h"
#include
#include
#include
#include
class Management :
public CDialogEx
{
public:
Management() {};
~Management() {};
void AddStudent(CListCtrl* pList);//添加数据按钮
void DeleteStudent(CListCtrl* pList);//删除数据按钮
void ChangeStudent(CListCtrl* pList);//修改数据按钮
void SortStudents(CListCtrl* pList,int nSel);//排序按钮,nSel是引入的行数
void LoadFile(CListCtrl* pList);//加载数据
void SaveToFile(CListCtrl* pList);//保存为TXT文件
void GetFromFile(CListCtrl* pList);//从TXT文件导入
};
#include "pch.h"
#include "Management.h"
bool sort_id(Student a, Student b) //学号大小比较函数
{
return _ttoi((CString)a.ID) < _ttoi((CString)b.ID); //将char转换成CString,再转化成int
}
bool sort_math(Student a, Student b)
{
return _ttoi((CString)a.math) > _ttoi((CString)b.math); //高数比较成绩函数
}
bool sort_sum(Student a, Student b)
{
return (_ttoi((CString)a.program) + _ttoi((CString)a.math)) > (_ttoi((CString)b.program) + _ttoi((CString)b.math)); //总成绩比较函数
}
bool sort_program(Student a, Student b)
{
return _ttoi((CString)a.program) > _ttoi((CString)b.program); //大小比较函数
}
//添加数据
void Management::AddStudent(CListCtrl* pList)
{
CAddStudentDlg temp;
temp.DoModal();//调用CAddStudentDlg将新信息写入ListCtrl
LoadFile(pList);////更新ListCtrl界面
}
//删除数据
void Management::DeleteStudent(CListCtrl* pList)
{
POSITION pos = pList->GetFirstSelectedItemPosition();//找到当前选中行
if (pos == NULL)
{
MessageBox(_T("请选择要删除的数据"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
else
{
while (pos)
{
Student temp;
int nItem = pList->GetNextSelectedItem(pos);//获取当前选中行的行号
pList->GetItemText(nItem, 2, temp.ID, sizeof(temp.ID));//将选中行的学号信息写入临时变量
pList->DeleteItem(nItem);//在ListCtrl中删除选中行
CFile file;
if (!file.Open("./studentfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
MessageBox(_T("无法打开文件!"), _T("错误"), MB_OK | MB_ICONERROR);
return;
}
CFile temporaryfile;//临时数据存储文件,如果不存在则创建新的
if (!temporaryfile.Open("./tempfile.dat", CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone))
{
MessageBox(_T("无法打开文件!"), _T("错误"), MB_OK | MB_ICONERROR);
return;
}
//读取学生成绩储存文件,将未删除的学生信息写入临时文件temporaryfile中
Student u;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
if ((CString)u.ID == (CString)temp.ID)//根据学号判断是否该写入
continue;
temporaryfile.Write(&u, sizeof(u));
}
file.Close();
temporaryfile.Close();
//这里无论文件是否存在都创建了新的空文件studentfile.dat,是因为原文件中有数据,需要清除
if (!file.Open("./studentfile.dat", CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone))
{
MessageBox(_T("无法打开文件!"), _T("错误"), MB_OK | MB_ICONERROR);
return;
}
if (!temporaryfile.Open("./tempfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
MessageBox(_T("无法打开文件!"), _T("错误"), MB_OK | MB_ICONERROR);
return;
}
//读取学生成绩储存文件,将临时文件tempfile.dat中学生信息写入真正存储学生信息的studentfile.dat中
while (temporaryfile.Read(&u, sizeof(u)) == sizeof(u))
file.Write(&u, sizeof(u));
LoadFile(pList); //更新学生成绩管理系统界面的信息
return;
}
}
}
//修改数据
void Management::ChangeStudent(CListCtrl* pList)
{
CAddStudentDlg tempdlg;
tempdlg.DoModal();
LoadFile(pList);
}
//排序
void Management::SortStudents(CListCtrl* pList, int nSel)
{
Student SomeStudent[100];
CFile file;
if (!file.Open("./studentfile.dat", CFile::modeRead | CFile::shareDenyNone))
{
MessageBox(_T("无法打开文件!"), _T("错误"), MB_OK | MB_ICONERROR);
return;
}
int i = 0;
while (file.Read(&SomeStudent[i], sizeof(SomeStudent[i])) == sizeof(SomeStudent[i]))
{
i++;
}
file.Close();
int b = (CString)SomeStudent[0].ID < (CString)SomeStudent[1].ID;
if (nSel == 0) //0是高数成绩排序
std::sort(SomeStudent, SomeStudent + i, sort_math);
if (nSel == 1) //1是课设成绩排序
std::sort(SomeStudent, SomeStudent + i, sort_program);
if (nSel == 2) //2是学号排序
std::sort(SomeStudent, SomeStudent + i, sort_id);
if (nSel == 3) //3是总成绩排序
std::sort(SomeStudent, SomeStudent + i, sort_sum);
if (!file.Open("./studentfile.dat", CFile::modeWrite | CFile::shareDenyNone))
{
MessageBox(_T("无法打开文件!"), _T("错误"), MB_OK | MB_ICONERROR);
return;
}
int t = 0;
while (t < i) //将排好序的信息写入studentfile.dat
{
file.Write(&SomeStudent[t], sizeof(SomeStudent[t]));
t++;
}
file.Close();
LoadFile(pList); ////更新ListCtrl界面
}
//更新ListCtrl界面
void Management::LoadFile(CListCtrl* pList)
{
CFile file;//打开数据存储文件,如果不存在则创建新文件
if (!file.Open("./studentfile.dat", CFile::modeRead | CFile::modeCreate | CFile::modeNoTruncate | CFile::shareDenyNone))
{
MessageBox(_T("无法打开文件"), _T("错误"), MB_OK | MB_ICONERROR);
return;
}
pList->DeleteAllItems();//清屏
//重新写入ListCtrl
Student u;
int i = 0;
while (file.Read(&u, sizeof(u)) == sizeof(u))
{
u.Sum();
pList->InsertItem(i, u.name);
if (u.gender)
pList->SetItemText(i, 1, _T("男"));
else
pList->SetItemText(i, 1, _T("女"));
pList->SetItemText(i, 2, u.ID);
pList->SetItemText(i, 3, u.math);
pList->SetItemText(i, 4, u.program);
pList->SetItemText(i, 5, u.sum);
i++;
}
file.Close();
}
//导出数据
void Management::SaveToFile(CListCtrl* pList)
{
if (pList->GetItemCount() <= 0)
{
MessageBox(_T("没有需要保存的数据"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
//调用系统另存为窗口
char szFilters[] = _T("txt文件(*.txt)|*.txt|所有文件(*.*)|*.*||");
CFileDialog dlg(FALSE, _T("txt"), _T("学生信息"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilters, this);
if (dlg.DoModal() != IDOK)
return;
//获取文件路径
CString strFilePath;
strFilePath = dlg.GetPathName();
//判断文件是否已存在,存在则删除重建
DWORD dwre = GetFileAttributes(strFilePath);
if (dwre != (DWORD)-1)
{
DeleteFile(strFilePath);
}
//保存文件数据
FILE* fp;
fopen_s(&fp, strFilePath, "w");
//char str[1024];
if (fp == NULL)
{
printf("Save file ERROR\n");
return;
}
//获取ListCtrl中每一列的第一行,即数据的类别
int nHeadNum = pList->GetHeaderCtrl()->GetItemCount();
LVCOLUMN lvcol;
char str_out[256];
int nColNum;
nColNum = 0;
lvcol.mask = LVCF_TEXT;
lvcol.pszText = str_out;
lvcol.cchTextMax = 256;
while (pList->GetColumn(nColNum, &lvcol))
{
nColNum++;
fprintf_s(fp, "%-30s", lvcol.pszText);
}
fprintf_s(fp, "\n", lvcol.pszText);//写入文件中
//读取行的数据
int nRow = pList->GetItemCount();
for (int i = 0; i < nRow; i++)
{
for (int j = 0; j < nColNum; j++)
{
CString str_data = pList->GetItemText(i, j);//获取指定列,存为字符串形式
fprintf_s(fp, "%-30s", str_data);
}
fprintf_s(fp, "\n");
}
fclose(fp);
MessageBox(_T("数据保存成功"), _T("成功"), MB_OK | MB_ICONASTERISK);
}
//导入数据
void Management::GetFromFile(CListCtrl* pList)
{
// TODO: 在此添加控件通知处理程序代码
//调用系统窗口
char szFilters[] = _T("txt文件(*.txt)|*.txt|所有文件(*.*)|*.*||");
CFileDialog dlg(TRUE, _T("txt"), _T("学生信息"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilters, this);
dlg.m_ofn.lpstrTitle = _T("导入数据");
if (dlg.DoModal() != IDOK)
return;
//获取文件路径
CString strFilePath;
strFilePath = dlg.GetPathName();
//判断文件是否存在
DWORD dwre = GetFileAttributes(strFilePath);
if (dwre != (DWORD)-1)//如果路径正确
{
//清除之前所有数据
pList->DeleteAllItems();
int nColumnCount = pList->GetHeaderCtrl()->GetItemCount();
for (int i = 0; i < nColumnCount; i++)
{
pList->DeleteColumn(0);
}
}
else
{
MessageBox(_T("文件不存在!"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
//读取文件中的数据
FILE* fp;
fopen_s(&fp, strFilePath, "r");
char str[1024];
if (fp == NULL)
{
printf("Open file ERROR\n");
return;
}
int iRow = 0;
CFile file;
if (!file.Open("./studentfile.dat", /*CFile::modeCreate | */CFile::modeRead|CFile::modeWrite | CFile::shareDenyNone))
{
MessageBox(_T("无法打开文件!"), _T("错误"), MB_OK | MB_ICONERROR);
return;
}
Student u;
int nLength = 0;
while (fgets(str, sizeof(str), fp))
{
char _index[256] = "temp";
sprintf_s(_index, "%d", iRow);
pList->InsertItem(iRow, _index);
std::string s = str;
std::string buf;
std::stringstream ss(s);
std::vector<std::string> tokens;
int i = 0;
int j = 0;
while (ss >> buf)
{
if (buf.size() > 0)
{
tokens.push_back(buf);
if (iRow == 0)
{
pList->InsertColumn(++j, _T(tokens.at(i).c_str()), LVCFMT_CENTER, 100);
}
else
{
pList->SetItemText(iRow, i, tokens.at(i).c_str());
char temp[20];//临时储存性别,便于判断
strcpy_s(temp, tokens.at(i).c_str());
switch (i)
{
case 0:
strcpy_s(u.name, tokens.at(i).c_str());
break;
case 1:
if (strcmp("女", temp))
{
u.gender = true;
break;
}
else
{
u.gender = false;
break;
}
case 2:
strcpy_s(u.ID, tokens.at(i).c_str());
break;
case 3:
strcpy_s(u.math, tokens.at(i).c_str());
break;
case 4:
strcpy_s(u.program, tokens.at(i).c_str());
break;
case 5:
strcpy_s(u.sum, tokens.at(i).c_str());
break;
default:
break;
}
}
i++;
}
}
iRow++;
if (iRow > 1)
file.Write(&u, sizeof(u));
}
fclose(fp);
pList->DeleteItem(0);
file.Close();
LoadFile(pList);//更新ListCtrl界面
}
请下载完整项目查看。