【MFC】学生数据管理-广州大学程序设计课程设计报告

在这里插入图片描述

一、课程设计题目及内容

(1)设计一个学生类Student,包括数据成员:姓名、学号、二门课程(面向对象程序设计、高等数学)的成绩。
(2)创建一个管理学生的类Management,包括实现学生的数据的增加、删除、修改、按课程成绩排序、保存学生数据到文件及加载文件中的数据等功能。
(3)创建一个基于对话框的MFC应用程序,程序窗口的标题上有你姓名、学号和应用程序名称。使用(1)和(2)中的类,实现对学生信息和成绩的输入和管理。
在这里插入图片描述
(4)创建一个单文档的MFC应用程序,读取(3)中保存的文件中的学生成绩,分别用直方图和折线方式显示所有学生某课程的成绩分布图。
在这里插入图片描述

二、程序中使用的数据及主要符号说明

//管理系统数据
CString studyNumber;	//学号
	CString name;	//姓名
	CListBox lis;	//列表名
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnLbnSelchangeList1();
	CButton del;	//删除键命名
	afx_msg void OnBnClickedButton4();
	afx_msg void OnBnClickedButton5();
	void Removelis();	//清除列表
	afx_msg void OnDestroy();	//销毁函数
	CString address;	//通信地址
	int sorting;	//排序下拉列表变量
	afx_msg void OnCbnSelchangeCombo2();
	afx_msg void OnBnClickedButton6();
	BOOL sex;		//性别
	CString age;	//年龄
	CString mTest;	//数学成绩
CString cTest;	//C++成绩CString temp;	//临时字符串
	Student* pImfo = new Student;	//学生类指针
//绘图数据

afx_msg void OnFilePrintPreview();
	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
	DECLARE_MESSAGE_MAP()
	void DrawScore(CDC* pDC, int * fScore, int nNum);
	void Drawlist(CDC * pDC, int * fScore, int nNum);
	CButton m_button1, m_button2, m_button3, m_button4, m_button5, m_button6;
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	int m_Num[1000];
	afx_msg void OnHigger1();
	afx_msg void OnHigger2();
	afx_msg void OnHigger4();
	afx_msg void OnHigger5();

三、带有详细注释的自己编写的源程序

// Students.h
#pragma once
class Student {
public:
	char Name[10];	//姓名
	char StudyNumber[20];	//学号
	bool Sex;	//性别
	char Age[6];	//年龄
	char CTest[6];	//C++成绩(C++Test)
	char MTest[6];	//数学成绩(MathTest)
	char Test[6];		//总成绩的字符型数值
	char Address[100];	//通信地址
};
// 管理系统Dlg.h

// 管理系统Dlg.h : 头文件
#pragma once
#include "afxwin.h"
#include"Students.h"
// C管理系统Dlg 对话框
class C管理系统Dlg : public CDialogEx
{
// 构造
public:
	C管理系统Dlg(CWnd* pParent = NULL);	// 标准构造函数

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

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

// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	CString studyNumber;	//学号
	CString name;	//姓名
	CListBox lis;	//列表名
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnLbnSelchangeList1();
	CButton del;	//删除键命名
	afx_msg void OnBnClickedButton4();
	afx_msg void OnBnClickedButton5();
	void Removelis();	//清除列表
	afx_msg void OnDestroy();	//销毁函数
	CString address;	//通信地址
	int sorting;	//排序下拉列表变量
	afx_msg void OnCbnSelchangeCombo2();
	afx_msg void OnBnClickedButton6();
	BOOL sex;		//性别
	CString age;	//年龄
	CString mTest;	//数学成绩
	CString cTest;	//C++成绩
};
// 管理系统Dlg.cpp


// 管理系统Dlg.cpp : 实现文件
//

#include "stdafx.h"
#include "管理系统.h"
#include "管理系统Dlg.h"
#include "afxdialogex.h"
#include <fstream>
#include <iostream>
#include <algorithm>
#include <list>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace std;

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

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

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

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// C管理系统Dlg 对话框


//初始化类变量
C管理系统Dlg::C管理系统Dlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_MY_DIALOG, pParent)
	, studyNumber(_T(""))
	, name(_T(""))
	, address(_T(""))
	, sorting(0)
	, sex(FALSE)
	, age(_T(""))
	, mTest(_T(""))
	, cTest(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void C管理系统Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, studyNumber);
	DDX_Text(pDX, IDC_EDIT2, name);
	//  DDX_Radio(pDX, IDC_RADIO1, sex);
	//  DDX_Text(pDX, IDC_EDIT3, age);
	//  DDX_Text(pDX, IDC_EDIT5, mTest);
	//  DDX_Text(pDX, IDC_EDIT6, cTest);
	DDX_Control(pDX, IDC_LIST1, lis);
	DDX_Control(pDX, IDC_BUTTON2, del);
	DDX_Text(pDX, IDC_EDIT7, address);
	DDX_CBIndex(pDX, IDC_COMBO2, sorting);
	DDX_Radio(pDX, IDC_RADIO1, sex);
	DDX_Text(pDX, IDC_EDIT3, age);
	DDX_Text(pDX, IDC_EDIT5, mTest);
	DDV_MaxChars(pDX, mTest, 10);
	DDX_Text(pDX, IDC_EDIT6, cTest);
	DDV_MaxChars(pDX, cTest, 10);
}

BEGIN_MESSAGE_MAP(C管理系统Dlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &C管理系统Dlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &C管理系统Dlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &C管理系统Dlg::OnBnClickedButton3)
	ON_LBN_SELCHANGE(IDC_LIST1, &C管理系统Dlg::OnLbnSelchangeList1)
	ON_BN_CLICKED(IDC_BUTTON4, &C管理系统Dlg::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON5, &C管理系统Dlg::OnBnClickedButton5)
	
	ON_WM_DESTROY()
	ON_CBN_SELCHANGE(IDC_COMBO2, &C管理系统Dlg::OnCbnSelchangeCombo2)
	ON_BN_CLICKED(IDC_BUTTON6, &C管理系统Dlg::OnBnClickedButton6)
END_MESSAGE_MAP()


// C管理系统Dlg 消息处理程序

BOOL C管理系统Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。
	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

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

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void C管理系统Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void C管理系统Dlg::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 C管理系统Dlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void C管理系统Dlg::OnBnClickedButton1()
{
	// 增加
	if (UpdateData(true))
	{
		CString temp;	//临时字符串
		Student* pImfo = new Student;	//学生类指针,用于存储当前画面新填入的信息

		//将画面中的信息存储到指针指向的类中
		strcpy_s(pImfo->Name, name);
		strcpy_s(pImfo->StudyNumber, studyNumber);
		strcpy_s(pImfo->Address, address);
		pImfo->Sex = sex;
		strcpy_s(pImfo->Age, age);
		strcpy_s(pImfo->MTest, mTest);
		strcpy_s(pImfo->CTest, cTest);
		int e = _ttoi(_T(mTest));
		int f = _ttoi(_T(cTest));
		temp.Format(_T("%d"), (e+f));
		strcpy_s(pImfo->Test, temp);

		//添加列表项目
		CString LongName = pImfo->Name;		//字符串LongName用于添加列表名称
		LongName.Append("  总分");		
		LongName.Append(pImfo->Test);
		int nIndex = lis.AddString(LongName);	//接收索引号
		lis.SetItemData(nIndex, (DWORD_PTR)pImfo);		//设置相应项目ID

		//清空画面操作
		name = "";
		studyNumber = "";
		address = "";
		sex = 0;
		age = "";
		mTest = "";
		cTest = "";
		UpdateData(FALSE);
	}
}


void C管理系统Dlg::OnBnClickedButton2()
{
	// 删除
	int  nCur = lis.GetCurSel();	//读取当前点中的列表索引号
	if (nCur != LB_ERR)
	{
		Student* pImfo = (Student*)lis.GetItemData(nCur);	//类指针指向对应列表数据
		lis.DeleteString(nCur);		//删除该列

		//清空数据
		name = "";
		studyNumber = "";
		address = "";
		sex = 0;
		age = "";
		mTest = "";
		cTest = "";

		// 判断当前行数,若行数为0,则删除键不可见
		if (lis.GetCount() == 0)
		{
			del.EnableWindow(FALSE);
		}
		UpdateData(FALSE);
		delete pImfo;	//释放指针防止内存泄漏
	}

}


void C管理系统Dlg::OnBnClickedButton3()
{
	// 修改
	// 思路:删旧增新
	int  nCur = lis.GetCurSel();	//读取当前点中的列表索引号
	if (nCur != LB_ERR)
	{
		Student* pImfo = (Student*)lis.GetItemData(nCur);	//类指针指向对应列表数据
		lis.DeleteString(nCur);		//删除该列
		delete pImfo;	//释放指针防止内存泄漏
	}
	OnBnClickedButton1();	//调用“增加”按钮,读取当前画面中的信息将其再次添加
}


void C管理系统Dlg::OnLbnSelchangeList1()
{
	// 列表事件
	int nCur = lis.GetCurSel();		//读取当前点中的列表索引号
	if (nCur != LB_ERR)
	{
		del.EnableWindow(TRUE);		//if (nCur != LB_ERR)→有选中列表→可以删除→删除键可见
		Student* pImfo = (Student*)lis.GetItemData(nCur);	//类指针指向对应列表数据

		//数据读取
		name = pImfo->Name;
		address = pImfo->Address;
		studyNumber = pImfo->StudyNumber;
		sex = pImfo->Sex;
		age = pImfo->Age;
		mTest = pImfo->MTest;
		cTest = pImfo->CTest;
		UpdateData(FALSE);
	}
	
}


void C管理系统Dlg::OnBnClickedButton4()
{
	// TODO: 保存
	CFileDialog dlg(FALSE);		//打开“另存为”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路径
		ofstream out(strFile, ios::binary);		//二进制写入数据
		if (out.is_open())
		{
			int n = lis.GetCount();		//获取当前信息数目

			//将信息写入文件中
			out.write((char*)&n, sizeof(int));
			for (int i = 0; i < n; i++)
			{
				Student* pImfo = (Student*)lis.GetItemData(i);
				out.write((char*)pImfo, sizeof(Student));
			}
		}
	}
}


void C管理系统Dlg::OnBnClickedButton5()
{
	// TODO: 读取
	CFileDialog dlg(TRUE);	//打开“打开”界面
	if (dlg.DoModal() == IDOK)
	{
		Removelis();	//清空当前列表
		CString strFile = dlg.GetPathName();	//返回文件路径
		ifstream in(strFile, ios::binary);		//二进制读出数据
		if (in.is_open())
		{
			int n = lis.GetCount();		//获取当前信息数目

			//从文件中读取信息
			in.read((char*)&n, sizeof(int));
			for (int i = 0; i < n; i++)
			{
				Student* pImfo = new Student;
				in.read((char*)pImfo, sizeof(Student));
				CString LongName = pImfo->Name;		//字符串LongName用于添加列表名称
				LongName.Append("  总分");
				LongName.Append(pImfo->Test);
				int nIndex = lis.AddString(LongName);	//接收索引号
				lis.SetItemData(nIndex, (DWORD_PTR)pImfo);		//设置相应项目ID
			}
			OnLbnSelchangeList1();		//更新列表栏
		}
		else
		{
			AfxMessageBox("Open File Err");
		}
	}
}

//快排调用
BOOL  cmpAll(Student* pt1, Student* pt2)   //比较总成绩
{
	int temp1 = _ttoi(_T(pt1->Test));
	int temp2 = _ttoi(_T(pt2->Test));
	return temp1 > temp2;
}
BOOL  cmpM(Student* pt1, Student* pt2)   //比较数学成绩
{
	int temp1 = _ttoi(_T(pt1->MTest));
	int temp2 = _ttoi(_T(pt2->MTest));
	return temp1 > temp2;
}
BOOL  cmpC(Student* pt1, Student* pt2)   //比较C成绩
{
	int temp1 = _ttoi(_T(pt1->CTest));
	int temp2 = _ttoi(_T(pt2->CTest));
	return temp1 > temp2;
}
	
void C管理系统Dlg::Removelis()		
{
	//列表清除
	int n = lis.GetCount();		//获取当前信息数目
	//逐条读取指针,释放指针
	for (int i = 0; i < n; i++)
	{
		Student* pImfo = (Student*)lis.GetItemData(i);
		delete pImfo;
	}
	lis.ResetContent();		//释放内容
	OnLbnSelchangeList1();		//更新列表栏
}


void C管理系统Dlg::OnDestroy()
{
	CDialogEx::OnDestroy();
	Removelis();	//在关闭整个页面前正确释放指针,避免内存泄漏
	// TODO: 在此处添加消息处理程序代码
}




void C管理系统Dlg::OnCbnSelchangeCombo2()
{
	// 排序
	if (UpdateData(true)) {

		//使用容器读取信息,进行排序
		list<Student*> sts;
		int num = lis.GetCount();
		Student *temp;
		for (int i = 0; i < lis.GetCount(); i++)
		{
			temp = (Student*)lis.GetItemData(i);
			sts.push_back(temp);
		}

		//根据下拉列表框的选择执行不同的排序
		switch (sorting)
		{
		case 0:
			break;
		case 1:
			sts.sort(cmpM);		//按照数学成绩排序
			break;
		case 2:
			sts.sort(cmpC);		//按照程序设计成绩排序
			break;
		case 3:
			sts.sort(cmpAll);		//按照总成绩排序
			break;
		}
		//逐条删除列表
		while (lis.GetCount() > 0) lis.DeleteString(0);
		//将在容器中排好序的信息再添加到列表中
		for (auto iter = sts.begin(); iter != sts.end(); ++iter)
		{
			auto st = *iter;
			CString LongName = st->Name;	//字符串LongName用于添加列表名称
			LongName.Append("  总分");
			LongName.Append(st->Test);
			lis.AddString(LongName);
			lis.SetItemDataPtr(lis.GetCount() - 1, st);
		}
	}
}


void C管理系统Dlg::OnBnClickedButton6()
{
	// 呼叫绘图程序
	ShellExecute(NULL, "open", ".\\MFCApplication8.exe", NULL, NULL, SW_SHOWNORMAL);
}
// MFCApplication8View.h
// MFCApplication8View.h : CMFCApplication8View 类的接口
//

#pragma once


class CMFCApplication8View : public CView
{
protected: // 仅从序列化创建
	CMFCApplication8View();
	DECLARE_DYNCREATE(CMFCApplication8View)

// 特性
public:
	CMFCApplication8Doc* GetDocument() const;

// 操作
public:

// 重写
public:
	virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// 实现
public:
	virtual ~CMFCApplication8View();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// 生成的消息映射函数
protected:
	afx_msg void OnFilePrintPreview();
	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
	DECLARE_MESSAGE_MAP()
	void DrawScore(CDC* pDC, int * fScore, int nNum);
	void Drawlist(CDC * pDC, int * fScore, int nNum);
	CButton m_button1, m_button2, m_button3, m_button4, m_button5, m_button6;
public:
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	int m_Num[1000];
	afx_msg void OnHigger1();
	afx_msg void OnHigger2();
	afx_msg void OnHigger4();
	afx_msg void OnHigger5();
};

#ifndef _DEBUG  // MFCApplication8View.cpp 中的调试版本
inline CMFCApplication8Doc* CMFCApplication8View::GetDocument() const
   { return reinterpret_cast<CMFCApplication8Doc*>(m_pDocument); }
#endif

// MFCApplication8View.cpp
// MFCApplication8View.cpp : CMFCApplication8View 类的实现
//

#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "MFCApplication8.h"
#endif
#include "MFCApplication8Doc.h"
#include "MFCApplication8View.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include <fstream>
#include "Students.h"
using namespace std;

// CMFCApplication8View

IMPLEMENT_DYNCREATE(CMFCApplication8View, CView)

BEGIN_MESSAGE_MAP(CMFCApplication8View, CView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMFCApplication8View::OnFilePrintPreview)
	ON_WM_CONTEXTMENU()
	ON_WM_RBUTTONUP()
	ON_WM_CREATE()
	ON_COMMAND(IDC_HIGGER1, &CMFCApplication8View::OnHigger1)
	ON_COMMAND(IDC_HIGGER2, &CMFCApplication8View::OnHigger2)
	ON_COMMAND(IDC_HIGGER4, &CMFCApplication8View::OnHigger4)
	ON_COMMAND(IDC_HIGGER5, &CMFCApplication8View::OnHigger5)
END_MESSAGE_MAP()

// CMFCApplication8View 构造/析构

CMFCApplication8View::CMFCApplication8View()
{
	// TODO: 在此处添加构造代码

}

CMFCApplication8View::~CMFCApplication8View()
{
}

BOOL CMFCApplication8View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// CMFCApplication8View 绘制

void CMFCApplication8View::OnDraw(CDC* pDC)
{
	CMFCApplication8Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
 
}
void CMFCApplication8View::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
	AFXPrintPreview(this);
#endif
}

BOOL CMFCApplication8View::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}
void CMFCApplication8View::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CMFCApplication8View::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}


// CMFCApplication8View 诊断

#ifdef _DEBUG
void CMFCApplication8View::AssertValid() const
{
	CView::AssertValid();
}

void CMFCApplication8View::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMFCApplication8Doc* CMFCApplication8View::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCApplication8Doc)));
	return (CMFCApplication8Doc*)m_pDocument;
}
#endif //_DEBUG


// CMFCApplication8View 消息处理程序
void CMFCApplication8View::DrawScore(CDC* pDC, int * fScore, int nNum) //画直方图函数
{
	// fScore是成绩数组指针,nNum是学生人数
	int nScoreNum[] = { 0, 0, 0, 0, 0 };  // 各成绩段的人数的初 始值 
										  // 下面是用来统计各分数段的人数   
	for (int i = 0; i < nNum; i++)
	{
		int nSeg = (int)(fScore[i]) / 10; // 取数的"十"位上的值   
		if (nSeg < 6) nSeg = 5; // <60分    
		if (nSeg == 10) nSeg = 9;// 当为100分,算为>90分数段   
		nScoreNum[nSeg - 5] ++;   // 各分数段计数   
	}
	int nSegNum = sizeof(nScoreNum) / sizeof(int); // 计算有多少个分数段

												   // 求分数段上最大的人数 
	int nNumMax = nScoreNum[0];
	for (int i = 1; i < nSegNum; i++)
	{
		if (nNumMax < nScoreNum[i])
			nNumMax = nScoreNum[i];
	}
	CRect rc;
	GetClientRect(rc);
	rc.DeflateRect(280, 40);      // 缩小矩形大小  
	int nSegWidth = rc.Width() / nSegNum;   // 计算每段的宽度  
	int nSegHeight = rc.Height() / nNumMax;   // 计算每段的单位高度  
	COLORREF crSeg = RGB(0, 0, 192);  // 定义一个颜色变量   
	CBrush brush1(HS_FDIAGONAL, crSeg);
	CBrush brush2(HS_BDIAGONAL, crSeg);
	CPen   pen(PS_INSIDEFRAME, 2, crSeg);
	CBrush* oldBrush = pDC->SelectObject(&brush1);   // 将brush1选入设备环境   
	CPen* oldPen = pDC->SelectObject(&pen);  // 将pen选 入设备环境  
	CRect rcSeg(rc);
	rcSeg.right = rcSeg.left + nSegWidth;   // 使每段的矩形宽度等于nSegWidth  
	CString strSeg[] = { (CString)"<60", (CString)"60-70", (CString)"70-80", (CString)"80-90", (CString)">=90" };
	CRect rcStr;
	for (int i = 0; i<nSegNum; i++)
	{  // 保证相邻的矩形填充样式不相同    
		if (i % 2)
			pDC->SelectObject(&brush2);
		else
			pDC->SelectObject(&brush1);
		rcSeg.top = rcSeg.bottom - nScoreNum[i] * nSegHeight - 2;  // 计算每段矩形的高度   
		pDC->Rectangle(rcSeg);
		if (nScoreNum[i] > 0)
		{
			CString str;
			str.Format((CString)"%d人", nScoreNum[i]);
			pDC->DrawText(str, rcSeg, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		}
		rcStr = rcSeg;
		rcStr.top = rcStr.bottom + 2;
		rcStr.bottom += 20;
		pDC->DrawText(strSeg[i], rcStr, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		rcSeg.OffsetRect(nSegWidth, 0);  // 右移矩形   
	}
	pDC->SelectObject(oldBrush);  // 恢复原来的画刷属性   
	pDC->SelectObject(oldPen);    // 恢复原来的画笔属性 

	CDC* pControlDC = pDC;
	pControlDC->SelectStockObject(BLACK_BRUSH);//设置画刷
	CString str;
}

void CMFCApplication8View::Drawlist(CDC* pDC, int* fScore, int nNum)//画折线图
{
	// fScore是成绩数组指针,nNum是学生人数

	int nScoreNum[] = { 0, 0, 0, 0, 0 };  // 各成绩段的人数的初 始值 
	// 下面是用来统计各分数段的人数   
	for (int i = 0; i < nNum; i++)
	{
		int nSeg = (int)(fScore[i]) / 10; // 取数的"十"位上的值   
		if (nSeg < 6) nSeg = 5; // <60分    
		if (nSeg == 10) nSeg = 9;// 当为100分,算为>90分数段   
		nScoreNum[nSeg - 5] ++;   // 各分数段计数   
	}
	CDC* pControlDC = pDC;
	pControlDC->SelectStockObject(BLACK_BRUSH);//设置画刷
	CString str;
	CString strSeg[] = { (CString)"<60", (CString)"60-70", (CString)"70-80", (CString)"80-90", (CString)">=90" };
	pControlDC->MoveTo(280, 40);//画线的开始位置
	pControlDC->LineTo(280, 380);
	pControlDC->MoveTo(280, 380);//画线的开始位置
	pControlDC->LineTo(900, 380);
	pControlDC->MoveTo(280, 380);
	for (int i = 0; i < 5; i++)
	{
		pControlDC->SetPixel(0, 290, RGB(0, 0, 255));  //设置点的位置及颜色
		pControlDC->LineTo(i * 140 + 280, 380 - (380 * nScoreNum[i] / nNum));//换两点之间的线
		str.Format("%d人", nScoreNum[i]);
		pControlDC->TextOut(i * 140 + 280, 380 - (380 * nScoreNum[i] / nNum) - 20, str);//在线的上方输出文字
		pControlDC->TextOut(i * 140 + 280, 390, strSeg[i]);
	}
}


int CMFCApplication8View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	m_button1.Create((CString)"数学(直方)",//按钮标题
		WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
		CRect(10, 10, 200, 40),            //按钮大小
		this,                          //按钮父指针
		IDC_HIGGER1);                      //该按钮对应的ID号
	m_button1.ShowWindow(SW_SHOWNORMAL);
	m_button2.Create((CString)"程序设计(直方)",//按钮标题
		WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
		CRect(10, 60, 200, 90),            //按钮大小
		this,                          //按钮父指针
		IDC_HIGGER2);                      //该按钮对应的ID号
	m_button2.ShowWindow(SW_SHOWNORMAL);
	
	m_button4.Create((CString)"(折线)",//按钮标题
		WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
		CRect(200, 10, 270, 40),            //按钮大小
		this,                          //按钮父指针
		IDC_HIGGER4);                      //该按钮对应的ID号
	m_button4.ShowWindow(SW_SHOWNORMAL);
	m_button5.Create((CString)"(折线)",//按钮标题
		WS_CHILD | WS_VISIBLE | WS_BORDER,//按钮风格
		CRect(200, 60, 270, 90),            //按钮大小
		this,                          //按钮父指针
		IDC_HIGGER5);                      //该按钮对应的ID号
	m_button5.ShowWindow(SW_SHOWNORMAL);

	return 0;

}

void CMFCApplication8View::OnHigger1()
{
	// TODO: 在此添加命令处理程序代码
	CFileDialog dlg(TRUE);	//打开“打开”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路径
		CFile file;
		if (!file.Open(strFile, CFile::modeReadWrite | CFile::shareDenyNone))
		{
			AfxMessageBox("文件无法打开,无法画图!");
			return;
		}
		Student u;
		int i = 0;
		int n;
		file.Read((char*)&n, sizeof(int));
		while (file.Read(&u, sizeof(u)) == sizeof(u))
		{
			m_Num[i] = _ttoi((CString)u.MTest);
			i++;
		}
		InvalidateRect(NULL);
		UpdateWindow();
		DrawScore(GetDC(), m_Num, i);
		file.Close();
	}
}


void CMFCApplication8View::OnHigger2()
{
	// TODO: 在此添加命令处理程序代码
	CFileDialog dlg(TRUE);	//打开“打开”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路径
		CFile file;
		if (!file.Open(strFile, CFile::modeReadWrite | CFile::shareDenyNone))
		{
			AfxMessageBox("文件无法打开,无法画图!");
			return;
		}
		Student u;
		int i = 0;
		int n;
		file.Read((char*)&n, sizeof(int));
		while (file.Read(&u, sizeof(u)) == sizeof(u))
		{
			m_Num[i] = _ttoi((CString)u.CTest);
			i++;
		}
		InvalidateRect(NULL);
		UpdateWindow();
		DrawScore(GetDC(), m_Num, i);
		file.Close();
	}
}



void CMFCApplication8View::OnHigger4()
{
	// TODO: 在此添加命令处理程序代码
	CFileDialog dlg(TRUE);	//打开“打开”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路径
		CFile file;
		if (!file.Open(strFile, CFile::modeReadWrite | CFile::shareDenyNone))
		{
			AfxMessageBox("文件无法打开,无法画图!");
			return;
		}
		Student u;
		int i = 0;
		int n;
		file.Read((char*)&n, sizeof(int));
		while (file.Read(&u, sizeof(u)) == sizeof(u))
		{
			m_Num[i] = _ttoi((CString)u.MTest);
			i++;
		}
		InvalidateRect(NULL);
		UpdateWindow();
		Drawlist(GetDC(), m_Num, i);
		file.Close();
	}
}


void CMFCApplication8View::OnHigger5()
{
	// TODO: 在此添加命令处理程序代码
	CFileDialog dlg(TRUE);	//打开“打开”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路径
		CFile file;
		if (!file.Open(strFile, CFile::modeReadWrite | CFile::shareDenyNone))
		{
			AfxMessageBox("文件无法打开,无法画图!");
			return;
		}
		Student u;
		int i = 0;
		int n;
		file.Read((char*)&n, sizeof(int));
		while (file.Read(&u, sizeof(u)) == sizeof(u))
		{
			m_Num[i] = _tstoi(u.CTest);
			i++;
		}
		InvalidateRect(NULL);
		UpdateWindow();
		Drawlist(GetDC(), m_Num, i);
		file.Close();
	}

}
// Resource.h
//四个绘图按钮
#define IDC_HIGGER1					5001
#define IDC_HIGGER2					5002
#define IDC_HIGGER4					5004
#define IDC_HIGGER5					5005

四、程序运行时的效果图

  1. 初始界面
    初始界面

  2. 填写信息在这里插入图片描述

  3. 点选“增加”后在这里插入图片描述

  4. 点选左侧列表框对信息进行修改在这里插入图片描述

  5. 点击修改后可见左侧列表框的总分和信息发生了改变在这里插入图片描述

  6. 增加了十个项目框在这里插入图片描述

  7. 列表框内信息:在这里插入图片描述

  8. 点选“保存”后
    在这里插入图片描述

  9. 点选“删除”后List item

  10. 点选“读取”后在这里插入图片描述

  11. “打开”文件后List item

  12. 排序方式选择按数学成绩排序后在这里插入图片描述

  13. 列表框内信息:可见与图中排列方式一致在这里插入图片描述

  14. 排序方式选择按程序设计成绩排序后在这里插入图片描述

  15. 列表框内信息:可见与图中排列方式一致在这里插入图片描述

  16. 排序方式选择按总成绩排序后在这里插入图片描述

  17. 列表框内信息:可见与图中排列方式一致
    在这里插入图片描述

  18. 点选“绘图”后List item

  19. 点选“数学(直方)”后在这里插入图片描述

  20. 点选“数学(折线)”后在这里插入图片描述

  21. 点选“程序设计(直方)”后在这里插入图片描述

  22. 点选“程序设计(折线)”后在这里插入图片描述

五、实验结果分析,实验收获和体会。

1、实验结果分析:

(1)调用sort函数进行排序,编写了三种不同排序的bool型比较函数,将比较函数当陈参数传入sort函数内。
(2)本实验中按照降序进行排序。与一般的冒泡之类的排序方法不同的是,sort函数是通过不断二分插入的方法进行排序的,时间复杂度为nlogn,大大节省了排序时间。
(3)排序时将指针指向的列表内数据放入list中,然后将指针撤销,将list内部的学生类数据按照选择的排序方式进行排序,然后添加到列表中,实现排序。
(4)新建了Students.h头文件存储学生类
(5)将单文档与管理系统关联起来,使得在管理系统界面能够实现绘图功能。
(6)绘制了单文档的按钮,以及增加相应命令。

2、实验收获和体会:

(1)熟练使用UpdateDate函数进行界面数据更改与读入。
(2)对如listbox等控件的使用有了深层次的理解
(3)对listbox的各项函数、、sort函数等的使用的更加得心应手。
(4)领悟了char与CString在调用时的区别,以及掌握了将浮点型转化为字符型的方法。
(5)能够更加熟练的运用文件输入输出流对数据进行输入输出。
(6)踩过CString和double型数据的坑,后来把这些数据内容都改成了固定长度的char型。double类型和其他类型是不能紧挨着存储的,都是会有空间浪费掉,但是作为一个结构体存储的时候,它们的数据会被挨在一起存放,重新读取的时候就会出问题。
(7)对单文档的绘图功能有了一定的了解。

  • 6
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
为了稳固本学期所学的?C++面向程序设计?以及?数据库原理?的学习。提高和加强学 生的计算机应用及软件开发能力,使学生具备初级程序员的根本素质;培养学生独立分 析问题、解决问题、查阅资料以及自学能力,以适应信息管理行业日新月异的开展形势 ;本次课程设计为一个?学生信息管理系统?。该系统通过ODBC模式连接了SQL2005数据库 ,数据库包含了: 一.学生的根本信息表 〔学号、姓名、姓名、性别、年龄、所学专业、 〕 二.选修课程信息表 〔课程号、课程名、 学分 〕 三. 选课信息表 〔学号、 课程号、 成绩 〕 该系统还对这三个表都具有【增】、【删】、【查】、【改】的功能,同时还设计 它们之间的关系,如学生与课程关系和学生的成绩等,同时还要对一些数据进行查询, 如通过课程号查询学生成绩的集合。 八.心得体会 1〕过这次课程设计,初步掌握MFC程序设计,对消息的机制有了较为深刻的认识, 对MFC中的应用结构类,菜单类,窗口,对话框有了理解。 2〕也了解了数据库的有关知识,学会了一些常用的数据库查询语句,对数据库的功能和 作用也有了一定的认识。 3〕合理的规划和设计界面也是十分重要的,一个好的程序也需要便捷的操作和美观的界 面,人性化设计是需要考虑进取的。 4〕了解了ODBC数据库访问技术,ODBC提供了一组标准应用程序接口,可以使用SOL语句 实现对数据库的管理系统的访问。 一、设计思路: 本程序运用了MFC ODBC应用程序设计与SQL数据库,利用VC++中提供的MFC ODBC 开放数据库连接组件进行数据库的访问,利用了记录集(RECORDSET类)进行信息的添加( ADD ( ) ),删除 (DEL ( )),修改 (UPDATE( )), 查询〔select〔〕〕功能,并且对用户登陆的权限进行检验,并且具有错误提示功能。 二、设计说明与调试分析 A 根据设计要求分析数据的结构: 数据项列表 "名称 "注释 "数据类型 "主要的 "所在表" "Sname "姓名 "nchar(4 ) "not " " " " " "null " " "Ssex "性别 "nchar(3) "null " " "Sage "年龄 "tinyint "null " " "Sprof "专业 "nchar〔20 "null " " " " "〕 " " " "Stel " "char〔11〕"null " " "Kid "课程号 "char〔3〕 "主键 "kc " "Kname "课程名 "nchar(20) "not " " " " " "null " " "Kscore "课程学分 "tnyint "not " " " " " "null " " "Sid "学号 "Char(6) "主键 "s_kc " "Kid "课程号 "char(3) "主键 " " "grade "选修成绩 "tinyint "not " " " " " "null " " B 建立表 根据设计要求分析数据的结构,利用SQL 2005创立一个数据库,数据库命名为:【wami】, 创立3张表:xs表,kc表,xs_kc表,,如下列图: C 在表里面填好初始化数据 三.ODBC的配置源程序说明&附加SQL Server 2005数据库 配置ODBC 运行本实例需要配置用户DSN,在ODBC数据源管理器中配置用户DSN连接指定的SQL Server数据库。关键操作步骤如下: 〔1〕单击"开始〞按钮,选择"程序〞 "管理工具〞 "数据源〔ODBC〕〞命令,翻开"OD BC数据源管理器〞对话框,翻开"用户DSN〞选项卡。 〔2〕单击"添加〞按钮,翻开"创立新数据源〞对话框,选择安装数据源的驱动程序,这 里选择"SQL Server〞。 〔3〕单击"完成〞按钮,翻开"创立到SQL Server的新数据源〞对话框,在"名称〞文本框中设置数据源名称为"wangming〞〔即程 序里面的DSN〕,在"描述〞文本框设置数据源描述为"配置SQL Server数据库DSN〞,在"效劳器〞下拉列表框中选择连接的数据库所在效劳器为"自己的 计算机名〔例如我的是:WIN-PHT03USEDJ9\SQLEXPRESS〕〞。 〔4〕单击"下一步〞按钮,选择"使用网络登录ID的Windows NT验证〞单项选择框,其他默认〔5〕单击"下一步〞按钮,选择"更改默认的数据库为〞 复选框,并在其下拉列表框中选择连接的数据库名称,这里选择"student〞【数据库的 名字】,单击"下一步〞按钮。 〔6〕单击"完成〞按钮,翻开"ODBC Microsoft SQL Server安装〞对话框,显示新创立的ODBC数据源配置信息。 〔7〕单击"测试数据源〞按钮测试数据库连接是否成功,如果测试成功,单击"确定〞按
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值