📄 studentdoc.cpp
字号:
// StudentDoc.cpp : implementation of the CStudentDoc class
//
#include "stdafx.h"
#include "Student.h"
#include "StudentDoc.h"
#include "DlgQuery.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CStudentDoc
IMPLEMENT_DYNCREATE(CStudentDoc, CDocument)
BEGIN_MESSAGE_MAP(CStudentDoc, CDocument)
//{{AFX_MSG_MAP(CStudentDoc)
ON_COMMAND(ID_PROCESS_QUERY, OnProcessQuery)
ON_COMMAND(ID_PROCESS_SORT, OnProcessSort)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CStudentDoc construction/destruction
CStudentDoc::CStudentDoc()
{
// TODO: add one-time construction code here
}
CStudentDoc::~CStudentDoc()
{
}
BOOL CStudentDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CStudentDoc serialization
void CStudentDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CStudentDoc diagnostics
#ifdef _DEBUG
void CStudentDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CStudentDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CStudentDoc commands
void CStudentDoc::OnProcessQuery() // “处理/查询”菜单命令对应的消息处理函数
{
// TODO: Add your command handler code here
CDatabase database; // 声明数据库对象
CRecordset* pRecordset; // 声明记录集指针
CString strSQL; // 声明MFC之字符串类的对象,存放用于数据库查询的SQL语句
CDBVariant dbv; // 声明代表MFC之ODBC类中的变体类型的对象
string id, name;
float exercise, report, midterm, terminal;
CString str;
int i, n;
CDlgQuery dlg; // 声明用于查询班级和课程的对话框对象
// 打开数据源(Access数据库)
if (!database.Open(_T("ODBC;DSN=MS Access Database")))
{
AfxMessageBox("不能打开数据源!");
return;
}
pRecordset = new CRecordset(&database); // 创建存放数据的记录集
strSQL = "SELECT 班级名称 FROM 班级;"; // 创建查询班级的SQL语句
// 用SQL查询数据库,将数据存放于记录集中
if (!pRecordset->Open(CRecordset::forwardOnly, strSQL, CRecordset::readOnly))
{
AfxMessageBox("不能打开记录集!");
delete pRecordset;
database.Close();
return;
}
// 扫描记录集,确定班级数目
dlg.m_lstClass.nodeNum = 0;
while (!pRecordset->IsEOF())
{
pRecordset->GetFieldValue("班级名称", str);
pRecordset->MoveNext();
dlg.m_lstClass.nodeNum ++;
}
pRecordset->Close();
// 创建对话框对象中用于存放班级名称的数组
dlg.m_lstClass.pStrArr = new CString[dlg.m_lstClass.nodeNum];
// 用SQL查询数据库,将班级名称存放于记录集中
pRecordset->Open(CRecordset::forwardOnly, strSQL, CRecordset::readOnly);
// 从记录集中取出班级名称,存放于对话框对象的数组中
for (i = 0; i < dlg.m_lstClass.nodeNum; i ++)
{
pRecordset->GetFieldValue("班级名称", str);
dlg.m_lstClass.pStrArr[i] = str;
pRecordset->MoveNext();
}
pRecordset->Close();
strSQL = "SELECT 课程名称 FROM 课程;"; // 创建查询课程的SQL语句
// 用SQL查询数据库,将数据存放于记录集中
pRecordset->Open(CRecordset::forwardOnly, strSQL, CRecordset::readOnly);
// 扫描记录集,确定课程数目
dlg.m_lstCourse.nodeNum = 0;
while (!pRecordset->IsEOF())
{
pRecordset->GetFieldValue("课程名称", str);
pRecordset->MoveNext();
dlg.m_lstCourse.nodeNum ++;
}
pRecordset->Close();
// 创建对话框对象中用于存放课程名称的数组
dlg.m_lstCourse.pStrArr = new CString[dlg.m_lstCourse.nodeNum];
// 用SQL查询数据库,将课程名称存放于记录集中
pRecordset->Open(CRecordset::forwardOnly, strSQL, CRecordset::readOnly);
// 从记录集中取出课程名称,存放于对话框对象的数组中
for (i = 0; i < dlg.m_lstCourse.nodeNum; i ++)
{
pRecordset->GetFieldValue("课程名称", str);
dlg.m_lstCourse.pStrArr[i] = str;
pRecordset->MoveNext();
}
pRecordset->Close();
// 弹出对话框选择班级和课程,如果都已选择,则用选中的班级和课程生成SQL语句
if (dlg.DoModal() == IDOK && dlg.m_selClass >= 0 && dlg.m_selCourse >= 0)
{
m_Class = dlg.m_lstClass.pStrArr[dlg.m_selClass];
m_Course = dlg.m_lstCourse.pStrArr[dlg.m_selCourse];
strSQL = "SELECT 学生.学号, 学生.姓名, 成绩.平时作业, 成绩.实验报告, 成绩.期中考试, 成绩.期末考试 ";
strSQL += "FROM (班级 INNER JOIN 学生 ON 班级.班级ID = 学生.班级ID) INNER JOIN (课程 INNER JOIN 成绩 ON 课程.课程ID = 成绩.课程ID) ON 学生.学生ID = 成绩.学生ID ";
strSQL += "WHERE 班级.班级名称='";
strSQL += m_Class;
strSQL += "' AND 课程.课程名称='";
strSQL += m_Course;
strSQL += "'";
// 用SQL查询数据库,将数据存放于记录集中
pRecordset->Open(CRecordset::forwardOnly, strSQL, CRecordset::readOnly);
// 对记录集进行扫描以确定记录数
i = 0;
while (!pRecordset->IsEOF())
{
pRecordset->MoveNext();
i ++;
}
pRecordset->Close();
n = i;
// 如果记录集不空,则逐个取出记录,将字段转储到变量,然后用变量对对象数组元素进行赋值
if (n > 0)
{
Student2* pStudent = new Student2[n]; // 创建一个Student派生类对象数组
pRecordset->Open(CRecordset::forwardOnly, strSQL, CRecordset::readOnly);
for (i = 0; i < n; i++)
{
pRecordset->GetFieldValue("学号", str); // 取出记录
id = str; // 转储到C++字符串变量,下同
pRecordset->GetFieldValue("姓名", str);
name = str;
pRecordset->GetFieldValue("平时作业", dbv); // 取出记录
exercise = dbv.m_fltVal; // 转储到浮点变量,下同
pRecordset->GetFieldValue("实验报告", dbv);
report = dbv.m_fltVal;
pRecordset->GetFieldValue("期中考试", dbv);
midterm = dbv.m_fltVal;
pRecordset->GetFieldValue("期末考试", dbv);
terminal = dbv.m_fltVal;
pStudent[i].SetStudent(id, name, exercise, report, midterm, terminal); // 用变量为对象数组元素赋值
pStudent[i].CalcMark(); // 对数组元素计算总评成绩
pRecordset->MoveNext();
}
pRecordset->Close(); // 关闭记录集
m_studentlist.SetStudentList(pStudent, n); // 用数组为Student派生类对象的线性表赋值
delete[] pStudent; // 删除Student派生类对象数组
}
else // 如果记录集为空,则创建只有一个元素的线性表(数据为空或0)
{
Student2* pStudent = new Student2[1];
id = name = "";
exercise = report = midterm = terminal = 0;
pStudent[0].SetStudent(id, name, exercise, report, midterm, terminal);
pStudent[0].CalcMark();
m_studentlist.SetStudentList(pStudent, 1);
delete[] pStudent;
}
}
else // 如班级和课程未同时选中,则弹出错误提示
{
AfxMessageBox("查询成绩须同时选定一个班级和一门课程。");
}
delete pRecordset; // 删除记录集
database.Close(); // 关闭数据库
delete[] dlg.m_lstClass.pStrArr; // 删除对话框对象中用于存放班级名称的数组
delete[] dlg.m_lstCourse.pStrArr; // 删除对话框对象中用于存放课程名称的数组
UpdateAllViews(NULL, 0); // 刷新视图、显示数据
}
void CStudentDoc::OnProcessSort() // “处理/排序”菜单命令对应的消息处理函数
{
// TODO: Add your command handler code here
if (m_studentlist.GetnStudent() && (m_Period >= 0 && m_Period <= 4)) // 如果阶段选择正确
{
m_studentlist.BubSort(m_Period); // 则按指定考核阶段对应的成绩对线性表排序
UpdateAllViews(NULL, 0); // 刷新视图
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -