如題
********菜雞的課設,僅供交流參考
(2)程序功能模塊的設計:
1.學生管理系統的實現:
在我的程序裏,MFC主對話框“學生管理系統”中擁有“保存”,“打開”,“添加”,“刪除”,“按高數成績排序”,“按C++成績排序”,“修改”,“確定”,“反選”一共9個按鈕,以及“學號”,“姓名”,“高數”,“C++”四個編輯框,還有一個list control列表用於顯示數據。四個編輯框綁定了4個CString變量,利於直接獲取數據,
在students managementDlg.cpp中擁有list control初始化的代碼以及8個按鈕分別對應實現的代碼。在student.h頭文件,裏面用於存放一個“學生類”,在public中存放學生的姓名,學號,高數成績,c++成績,(分CString以及long long)兩個類型存儲,用一個convert成員函數實現從CString數據轉變爲long long存儲以便實現排序功能。
在manageff.h頭文件中,存放一個用於管理“學生類”的“管理類”,在private中存儲len(管理學生的容器總大小),count(已存學生數量),public中實現構造函數(初始化),學生類指針(容器),獲取容器大小的函數getcount,向容器中添加學生的函數add,指定位置刪除容器中的學生函數del,根據高數成績排序的函數math_sort,根據c++成績排序的函數Cjj_sort以及判斷容器中是否有相同學號的人的函數getsame(實現當添加時容器中已存在學號相同的學生則無法添加的功能)
在mangement.cpp中實現“學生類”以及“管理類”中的函數。
2.數據用直方圖以及折線圖顯示的實現:
在MFC單文檔中的View.h的類CView的public添加兩個按鈕CButton函數以及一個函數Open。在View.cpp中的OnDraw函數裏實現的繪圖,在類嚮導中添加一個OnCreate函數,並且實現按鈕的顯示。最後實現兩個按鈕的函數(打開“學生管理系統”中保存的save.txt,根據提取save.txt中的數據更改各個分段的高度以顯示出直方圖以及折現圖)。
(3)帶有詳細註釋的自己編寫的關鍵源程序:
1.學生管理系統:
//將四個編輯框分別綁定四個CString變量:Id,name,math,Cjj
1.Student.h頭文件:
#include <afxtempl.h>
#define ll long long
using namespace std;
#pragma once
class student
{
public:
//除了name以外所有數據均存一份CString跟一份long long
ll Idq;
ll mathq;
ll Cjjq;
CString name;//姓名
CString Id;//學號
CString math;//高數成績
CString Cjj;//C++成績
void convert();//將存儲的CString轉換成long long
};
2.Manageff.h頭文件:
#pragma once
#include "stdafx.h"
#include "Student.h"
class studentmanag
{
//學生類數組容器類
private:
int len;//容器總大小
int count;//容器已存的大小
public:
studentmanag();//構造函數
student * group;//學生數組容器
int getcount();//獲取容器已存大小
void add(student x);//向容器添加一個學生
void del(int x);//從容器中選擇刪除一個學生
void math_sort();//按高數成績排序數組
void Cjj_sort();//按C++成績排序數組
bool getsame(student a);//判斷容器中是否有學號相同的人
};
3.Management.cpp:
#include "stdafx.h"
#include "Student.h"
#include "manageff.h"
#include <algorithm>
using namespace std;
void student::convert()
{
//將CString轉成long long型存儲
Idq = _ttoi(Id);
mathq = _ttoi(math);
Cjjq = _ttoi(Cjj);
return;
}
studentmanag::studentmanag()
{
//初始化
group = new student[100];
len = 100;
count = 0;
}
int studentmanag::getcount()
{
//獲取容器已存大小
return this->count;
}
void studentmanag::add(student x)
{
//容器添加操作
count++;
if (count >= len)//如果現有大小等於容器大小,則擴大容器
{
student *p = new student[len + 10];//開闢新容器
len += 10;
for (int i = 0; i < count - 1; i++)//將新容器複製舊容器
{
p[i] = group[i];
}
delete[]group;//刪除舊容器的空間
group = p;//綁定新容器
}
group[count - 1] = x;
return;
}
void studentmanag::del(int x)
{
//容器刪除操作
count--;
int times = count - x;
while (times--)
{
group[x] = group[x + 1];
x++;
}
return;
}
bool cmp1(student x, student y)
{
//用於排序高數成績的cmp
if (x.mathq == y.mathq)
{
return x.Cjjq > y.Cjjq;
}
return x.mathq > y.mathq;
}
void studentmanag::math_sort()
{
//按高數成績排序
sort(group, group + count, cmp1);
return;
}
bool cmp2(student x, student y)
{
//用於排序c++成績的cmp
if (x.Cjjq == y.Cjjq)
{
return x.mathq > y.mathq;
}
return x.Cjjq > y.Cjjq;
}
void studentmanag::Cjj_sort()
{
//按C++成績排序
sort(group, group + count, cmp2);
return;
}
bool studentmanag::getsame(student a)
{
//判斷容器中是否存在學號相同的人
ll num = a.Idq;
bool flag = 0;
for (int i = 0; i < count; i++)
{
if (this->group[i].Idq == num)
{
flag = 1;
break;
}
}
return flag;
}
4.students managementDlg.cpp中關鍵源代碼:
OnInitDialog函數中添加:
//這是listcontrol的初始化,初始化添加勾選框
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES);
m_list.InsertColumn(0, _T("學號"),0,80);
m_list.InsertColumn(1, _T("姓名"),0, 80);
m_list.InsertColumn(2, _T("高數成績"),0, 99);
m_list.InsertColumn(3, _T("C++成績"),0, 97);
按鈕實現:
void CstudentsmanageDlg::OnBnClickedButton3()
{
//添加按鈕
UpdateData(TRUE);
//將編輯框中的數據寫入學生類
student a;
a.Cjj = Cjj;
a.Id = Id;
a.math = math;
a.name = name;
a.convert();
if (stdmanag.getsame(a))
{
CString k = "學號重複了!";
MessageBox(k);
//彈出信息框k
}
else
{
stdmanag.add(a);//將該學生加入容器中
//將數據在列表中顯示出來
int ncount = m_list.GetItemCount();
m_list.InsertItem(ncount, a.Id);
m_list.SetItemText(ncount, 1, a.name);
m_list.SetItemText(ncount, 2, a.math);
m_list.SetItemText(ncount, 3, a.Cjj);
}
}
void CstudentsmanageDlg::OnBnClickedButton2()
{
//刪除按鈕
for (int i = 0; i < m_list.GetItemCount(); i++)
{
//判斷是否勾選
BOOL check = m_list.GetCheck(i);
if (check)
{
stdmanag.del(i);
//調用刪除函數
m_list.DeleteItem(i);
//刪除列表中該行數據
i--;
}
}
}
void CstudentsmanageDlg::OnBnClickedButton1()
{
//修改按鈕
for (int i = 0; i < m_list.GetItemCount(); i++)
{
BOOL check = m_list.GetCheck(i);
if (check)
{
//如果勾選了該項
UpdateData(TRUE);
student a;
a.Cjj = Cjj;
a.Id = Id;
a.math = math;
a.name = name;
a.convert();
stdmanag.group[i] = a;
//根據編輯框中數據更新容器中學生數據
int ncount = m_list.GetItemCount();
m_list.SetItemText(i, 0, a.Id);
m_list.SetItemText(i, 1, a.name);
m_list.SetItemText(i, 2, a.math);
m_list.SetItemText(i, 3, a.Cjj);
//更新列表數據顯示
}
}
}
void CstudentsmanageDlg::OnBnClickedButton4()
{
//按高數成績排序按鈕
int count = stdmanag.getcount();
stdmanag.math_sort();
//調用排序
m_list.DeleteAllItems();
//刪除所有列表中所有數據
for (int i = 0; i < count; i++)
{
//容器中所有容器數據添加進列表
m_list.InsertItem(i, stdmanag.group[i].Id);
m_list.SetItemText(i, 1, stdmanag.group[i].name);
m_list.SetItemText(i, 2, stdmanag.group[i].math);
m_list.SetItemText(i, 3, stdmanag.group[i].Cjj);
}
}
void CstudentsmanageDlg::OnBnClickedButton5()
{
//按C++成績排序按鈕
int count = stdmanag.getcount();
stdmanag.Cjj_sort();
//調用排序
m_list.DeleteAllItems();
//刪除所有列表中所有數據
for (int i = 0; i < count; i++)
{
//容器中所有容器數據添加進列表
m_list.InsertItem(i, stdmanag.group[i].Id);
m_list.SetItemText(i, 1, stdmanag.group[i].name);
m_list.SetItemText(i, 2, stdmanag.group[i].math);
m_list.SetItemText(i, 3, stdmanag.group[i].Cjj);
}
}
void CstudentsmanageDlg::OnBnClickedButton7()
{
//打開按鈕
CFileDialog saveDlg(TRUE, ".txt", "save", OFN_OVERWRITEPROMPT, "文本文檔(*.txt)|*.txt|所有文件(*.*)|*.*||", NULL);
//設置保存文件對話框格式
if (saveDlg.DoModal() == IDOK)
{
//如果按了保存
//獲取文件路徑,並且設置只讀
CString path = saveDlg.GetPathName();
CStdioFile file(path, CFile::modeRead);
CString date;
student ui;
int i = 0, j = 0;
while (file.ReadString(date))//當還能讀取到數據時
{
//將數據顯示在列表中
if (i % 4 == 0)
{
m_list.InsertItem(j, date);
}
else
{
m_list.SetItemText(j, i % 4, date);
}
//將數據添加進容器
if (i % 4 == 0)
{
//第一行爲學號
if (j != 0)
{
//除了第一個數據之外,當爲4倍數時即說明ui已獲取完一個學生數據
//然後添加進容器
ui.convert();
stdmanag.add(ui);
}
ui.Id = date;
}
else if (i % 4 == 1)
{
//第二行爲姓名
ui.name = date;
}
else if (i % 4 == 2)
{
//第三行爲高數成績
ui.math = date;
}
else if (i % 4 == 3)
{
//第四行爲C++成績
ui.Cjj = date;
}
i++;
if (i % 4 == 0) j++;
//四個數據一換行
}
//將最後一個數據傳進容器
ui.convert();
stdmanag.add(ui);
}
}
void CstudentsmanageDlg::OnBnClickedButton8()
{
//保存按鈕
CFileDialog saveDlg(FALSE, ".txt", "save", OFN_OVERWRITEPROMPT, "文本文檔(*.txt)|*.txt|所有文件(*.*)|*.*||", NULL);
//設置保存文件對話框格式
if (saveDlg.DoModal() == IDOK)
{
//如果按了保存
CString path = saveDlg.GetPathName();//獲取文件路徑
CString k = "文件已保存在路徑";
CString k2;
k2.Format("%s%s", k, path);//k+k2
MessageBox(k2);
//彈出信息框k2
CStdioFile file(path,CFile::modeWrite|CFile::modeCreate);
//創建或者寫入文件
//保存數據
CString cs, hh = "\n";
for (int i = 0; i < m_list.GetItemCount(); i++)
{
//i行
for (int j = 0; j < 4; j++)
{
//j列
cs = m_list.GetItemText(i, j);
file.WriteString(cs);
//寫入一個數據
file.WriteString(hh);
//換行
}
}
file.Close();
//關閉文件
}
}
void CstudentsmanageDlg::OnBnClickedButton9()
{
//反選按鈕
for (int i = 0; i < m_list.GetItemCount(); i++)
{
m_list.SetCheck(i, !m_list.GetCheck(i));//設置是否勾中
}
}
2.直方圖以及折線圖的顯示:
在Doc.cpp中的OnNewDocument函數中添加以下代碼(修改標題)
SetTitle(_T("直方圖/折線圖實現"));
1.在View.h中的Cview類的public添加以下代碼:
afx_msg void OnClickButton1();
afx_msg void OnClickButton2();
//定義按鈕1,2
CButton m_button;
CButton m_button1;
2.View.cpp中關鍵源代碼:
int a = 0, b = 0, c = 0, d = 0, e = 0;
//矩陣高度
//在Ondraw函數中添加以下代碼:
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetViewportOrg(200,450);//設置原點
pDC->MoveTo(100, 0);//從100,0畫到1300,0
pDC->LineTo(1300, 0);
//設置畫筆參數
CBrush brush;
//畫筆顏色
brush.CreateHatchBrush(HS_BDIAGONAL, RGB(150, 100, 45));
pDC->SelectObject(brush);
int i = 1;
//繪製矩形,分別爲四個點座標
pDC->Rectangle(200, 0, 400, 50*a);
pDC->Rectangle(400, 0, 600, 50 * b);
pDC->Rectangle(600, 0, 800, 50 * c);
pDC->Rectangle(800, 0, 1000, 50 * d);
pDC->Rectangle(1000, 0, 1200, 50 * e);
//設置分段文本座標
pDC->TextOut(250, 0, " <60");
pDC->TextOut(450, 0, "60-70");
pDC->TextOut(650, 0, "70-80");
pDC->TextOut(850, 0, "80-90");
pDC->TextOut(1050, 0, "90-100");
//設置文字高度(多少人)
CString y1,y2,y3,y4,y5;
y1.Format("%d", a);
y2.Format("%d", b);
y3.Format("%d", c);
y4.Format("%d", d);
y5.Format("%d", e);
//x軸從250-1050
pDC->MoveTo(250, 50 * a + 100);
pDC->LineTo(450, 50 * b + 100);
pDC->LineTo(650, 50 * c + 100);
pDC->LineTo(850, 50 * d + 100);
pDC->LineTo(1050, 50 * e + 100);
//設置文本位置
if(a!=0)
pDC->TextOut(250, 27 * a, y1 + "人");
if (b != 0)
pDC->TextOut(450, 27 * b, y2 + "人");
if (c != 0)
pDC->TextOut(650, 27 * c, y3 + "人");
if (d != 0)
pDC->TextOut(850, 27 * d, y4 + "人");
if (e != 0)
pDC->TextOut(1050, 27 * e, y5 + "人");
//在類嚮導中添加處理程序OnCreate
//在View.cpp中OnCreate函數添加以下代碼:
m_button.Create("高等數學",//設置按鈕1標題
WS_CHILD | WS_VISIBLE | WS_BORDER,
//設置按鈕1座標
CRect(1200, 10, 1360, 60),
this,
IDC_BUTTON1);
m_button.ShowWindow(SW_SHOWNORMAL);
m_button1.Create("C++",//設置按鈕2標題
WS_CHILD | WS_VISIBLE | WS_BORDER,
//設置按鈕2座標
CRect(1200, 70, 1360, 120),
this,
IDC_BUTTON2);
m_button1.ShowWindow(SW_SHOWNORMAL);
//兩個按鈕的函數實現
void CDrawT12View::OnClickButton1()
{
//按鈕1實現
//初始化
a = b = c = d = e = 0;
//打開文件並且操作
CFileDialog fdlg(TRUE, ".dat", "save", OFN_OVERWRITEPROMPT, "數據文件(*.txt)|*.txt|所有文件(*.*)|*.*||", NULL);
//如果成功讀取文件
if (fdlg.DoModal() == IDOK)
{
CStdioFile file(fdlg.GetPathName(), CFile::modeRead);
CString cs;
int i = 0;
while (file.ReadString(cs))
{
//當還能讀取到行
if (i % 4 == 2)
{
//如果是高數成績,則轉換爲數值再判斷大小
long long q = _ttoi(cs);
if (q < 60) a++;
else if (q >= 60 && q <= 70) b++;
else if (q > 70 && q <= 80) c++;
else if (q > 80 && q <= 90) d++;
else if (q > 90) e++;
}
i++;
}
}
InvalidateRect(NULL);
}
void CDrawT12View::OnClickButton2()
{
//按鈕2實現
//初始化
a = b = c = d = e = 0;
//打開文件並且操作
CFileDialog fdlg(TRUE, ".dat", "save", OFN_OVERWRITEPROMPT, "數據文件(*.txt)|*.txt|所有文件(*.*)|*.*||", NULL);
//如果成功讀取文件
if (fdlg.DoModal() == IDOK)
{
CStdioFile file(fdlg.GetPathName(), CFile::modeRead);
CString cs;
int i = 0;
while (file.ReadString(cs))
{
//當還能讀取到行
if (i % 4 == 3)
{
//如果是C++成績,則轉換爲數值再判斷大小
long long q = _ttoi(cs);
if (q < 60) a++;
else if (q >= 60 && q <= 70) b++;
else if (q > 70 && q <= 80) c++;
else if (q > 80 && q <= 90) d++;
else if (q > 90) e++;
}
i++;
}
}
InvalidateRect(NULL);
}
(4)程序運行時的效果圖:
(5).實驗結果分析,實驗收穫和體會:
這次mfc實驗是對話框實現以及View單文檔視圖的綜合應用
1.這次實驗進行初期,我對MFC中工具箱中控件跟實際映射的變量以及函數應用不太熟練,經過實驗,我熟悉了MFC的Dlg界面設計,以及各個控件之間的關聯綁定。
2.這次實驗需要大量使用MFC中各個控件的自帶函數(例如讀寫txt文件,list control的函數方法等等),需要在網上查找資料,經過實驗後,使得我對這些函數的使用更加的熟悉了。
3.經過實驗,我鞏固了頭文件的編寫與多cpp的編寫形式。
4.在cpp文件運用頭文件中書寫的類時會出現很多問題:無法識別頭文件中的類,將頭文件stdafx.h書寫在最前面include就解決了問題,具體原因未知。
5.試驗初期,我運用了CArray(MFC自帶的模板容器)來存儲學生類,很快就完成完了要求,但是後來因爲老師不允許使用STL容器以及其他容器,所以自己寫了一個容器,並且通過自己實現了很多類容器的函數方法,讓我更加提升了自己的代碼能力。
6.實驗要求實現MFC單文檔內展示兩個不同的直方/折現圖,因此需要在單文檔視圖中添加按鈕實現,於是我在網上查找資料學習到了在MFC單文檔中安置按鈕的方法,以及熟悉了在MFC中CBrush(畫筆)的函數方法使用。
7.實現排序功能時,我寫了多個cmp用於實現多個排序方法,再用algorithm頭文件中的sort函數進行快排,實現便捷並且效率高。
8.在實現直方圖/折線圖的時候,實現界面的標題是未定義標題,覺得有點不太好看(截圖在實驗報告不美觀),因此在網上查找資料,學會了更改標題的方法。
(6)實驗的改進意見和建議:
1.實驗要求中沒有要求到的,我覺得挺重要的按鈕:按學號查找,我的想法是在容器類中添加find函數用於查找參數中輸入的int學號,再彈出對話框顯示該學號學生的所有信息。
2.在學生管理系統中,雖然實驗沒有要求,但是我添加了反選的按鈕,因爲我發現在調試的時候,要一個個勾選刪除比較麻煩,所以添加反選按鈕實現一鍵刪除功能。
3.我認爲判斷是否學號重複添加的功能是很需要的,因此我在類容器中寫了個查找學號是否重複的函數,用於實現這個功能,若重複添加則彈出“學號重複”信息框。
總結:(之前覺得MFC是個上世紀的產物,覺得沒用,課也沒聽,但是爲了寫這課程設計,還特地去學,枯遼,但是感覺學會了還行8)