1122 物件導向程式設計
作業二
繳交時間
113/04/08 星期一 21:00
簡易成績資料庫
範例執行程式
上一次作業中最主要是複習 C 語法,在課後練習資料裡大家練習完成個別抽象資料型態的撰寫
Complex,以及運用 Complex 類別 ADT 製作簡單的應用程式。本次作業中你要應用 C++ 語法設計基本的類別與物件,
加上建構元、 解構元、 new/delete、
以及類別界面的設計, 製作一個基本的成績資料庫以存放某一科目一學期內學生的所有成績, 並提供操作者進行查詢、增加、修改、刪除、存檔等功能。 你在這一次作業中應該要練習
- 建構並維護整個程式執行時的物件架構
- 基於上述物件架構,以及各個不同類別或是相同類別的物件之間的互動, 完成指定的程式功能
- 熟悉運用 C++ 製作物件導向程式的工具,包括 Visual Studio 提供的一些輔助功能,書簽功能,分檔案編譯連結的基本形式
- 了解並且練習設計物件導向程式的基本流程
- 嘗試將系統中的類別/物件描述出來,實作軟體的靜態模型
- 嘗試以 UML 描述類別及類別之間的關係 (可以用手畫, 用 Powerpoint, Visio, StarUML,
或是 VC 的類別圖表 等等)
- 嘗試設計 類別/物件 的介面
- 小心地封裝所有的實作細節
- 建構元與解構元的製作
- 檔案串流的使用
- 請特別注意識別字(identifier) (包括變數名稱,類別名稱與函式名稱) 的命名,每一個變數的名稱都必須要是有意義的英文字,實在不知道怎樣用英文命名的話可以查詢漢英字典或是同義字
(thesaurus) 辭典或是請教一下 Google,應該可以有一些幫助
- 請撰寫各個類別獨立測試的函式,你有寫的成員函式或是界面就應該要設計它可以派上用場的環境來呼叫看看,運用
assert 建立自動比對的程式碼,製作 unitTest 的功能 (請參考步驟六與步驟七)
- 請注意記憶體的配置 new/new[] 與釋放 delete/delete[], 請以 memory_leak
功能檢查自己的程式是不是有記憶體遺失的問題
這是一個文字介面的程式,以下是範例程式執行時的輸出結果, 請仔細閱讀,可以說明大部分程式的功能
c:>GradeDB1
---
請選擇下列功能:
1:輸入資料庫檔案名稱
2:結束操作
1
請輸入檔案名稱:class1122.dat
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
6
>>資料庫內沒有任何資料
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
1
請輸入學生姓名:張三
請輸入學生學號:B001
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
2
請輸入學生姓名:張三
請輸入成績:76
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
2
請輸入學生姓名:張三
請輸入成績:96
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
3
請輸入學生姓名:張三
>>姓名:張三
>>學號:B001
>>成績:76 96
>>平均成績是:86
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
1
請輸入學生姓名:李四
請輸入學生學號:B002
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
3
請輸入學生姓名:李四
>>姓名:李四
>>目前沒有記錄任何資料
---
|
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
2
請輸入學生姓名:李四
請輸入成績:80
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
3
請輸入學生姓名:王五
>>資料庫內找不到此學生
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
4
請輸入學生姓名:張三
>>姓名:張三
>>學號:B001
>>成績:76 96
請問要修改第幾筆成績:2
請輸入成績:98
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
6
>>姓名:張三
>>學號:B001
>>成績:76 98
>>平均成績是:87
>>姓名:李四
>>學號:B002
>>成績:80
>>平均成績是:80
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
5
請輸入學生姓名:李四
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
1
請輸入學生姓名:張三
>>資料庫內已經有此一學生
---
<class1122.dat>請選擇下列功能:
1:增加一新學生
2:對一學生增加一新成績
3:查詢一學生之所有成績
4:更改一學生之成績
5:刪除某一學生
6:列印顯示所有資料庫中之資料
7:存檔並關閉 class1122.dat 檔案
8:結束操作
7
---
請選擇下列功能:
1:輸入資料庫檔案名稱
2:結束操作
2
|
請注意:
請依照下列提示製作你的類別:
- 請製作 Grade 類別以存放同一個學生該科目本學期的所有成績, 本作業中限定最多可輸入 6 個成績, 如果使用者打算存入第七個成績時系統會列印出下列錯誤訊息:
>>超過個人最多成績筆數無法加入資料庫內
- 請製作 Student 類別以存放某一學生之個人資料, 在此類別中需動態配置陣列存放學生之姓名與學號,
此外你必須假設學生姓名不超過 10 個字元 (合理的中文姓名),學號為 4 個字元,如此你可以將鍵盤輸入的字元暫時存放在一個固定長度的記憶體陣列內,
另外此類別內需以一個 Grade 類別的私有物件來存放此學生的成績。
- 請製作 Class 的類別來存放所有學生的資料, 並且處理輸入命令的解譯工作,
此類別內要用一個 Student *[100] 指標陣列來存放動態配置的學生物件, 系統最多可存放 100
個學生的資料, 如果使用者要求存入第 101 個學生, 系統會印出如下的錯誤訊息:
>>本資料庫只能容納 100 名學生,目前人數已滿
輸入命令解譯工作由 Class 類別的成員函式 query() 來負責, 此函式為一無窮迴圈, 一直執行到使用者選擇 "結束操作" 為止, 程式的主函式
main 的內容應該如下
void main()
{
Class myClass;
myClass.query();
}
此函式為本程式中唯一不屬於任何物件的函式。
- 讀檔/寫檔請運用二進位 (Binary)
的方法完成 (例如記憶體裡面的一個 int 型態資料存放到檔案裡就是用 sizeof(int) 個位元組來存放, 不需要轉換為十進位之文字格式, 請參考
C++ File I/O page 7 或是
C 檔案輸入與輸出:如何將變數內資料以二進位格式寫入檔案, istream::read,
ostream::write),
請特別注意在資料存檔時不要破壞了每一個物件的封裝特性。 如果想要看輸出的二進位檔案的內容, 你可以用 linux 上常用的工具程式 od.exe
在命令列視窗中打 od -x class1122.dat , 就可以看到以 16 進位的格式列印出來的資料, 例如下面這個檔案裡有 32 個位元組:
0000000 0100 0302 0504 0706 0908 0b0a 0d0c 0f0e
0000020 1110 1312 1514 1716 1918 1b1a 1d1c 1f1e
上面顯示的資料裡, 每一列最左邊是那一列由檔案的第幾個位元組開始, 第一列開始顯示的資料代表檔案裡面第一個位元組是
00, 第二個位元組是 01, 第三個位元組是 02, 第四個位元組是 03 ... 第 32 個位元組是 1f
- 程式請由一開始就撰寫測試程式開始測試, 請以單元測試/assert 的方式來作基礎的測試
請注意: 如果沒有頭緒的話可以參考實習中 3Bags
程式的設計、實習考試稀疏矩陣類別的設計與實作,以及
學校課程資料庫 的設計
除了以上要求與說明外, 你必須自己設計其它需要的資料成員與成員函式 (例如在設計 Class 類別的 addGrade()
函式時,需要 Student 類別也提供 addGrade() 介面,需要在 Class 類別中設計記錄所有班級中學生的指標陣列資料成員,...), 程式撰寫時請注意下列各項
C++ 程式設計的一般要點:
- 如果成員函式不會更改物件狀態與內容的話,請使用 const 成員函式
- 函式如果不會修改參考變數或是陣列參數的話,請使用 const 的參數
- 儘量運用初始化串列 (initialization list) 來撰寫類別的建構元
- 不要讓你的資料成員成為 public,也不要讓不需公開的輔助成員函式成為 public
- 物件所有成員的初始值要在建構元中一併設定完成
- 請替有動態配置記憶體的類別撰寫解構元,拷貝建構元,與設定運算子
- 變數及函式名稱請務必使用有意義的英文或是縮寫
- 每一個成員函式內請務必只放相關的程式碼,不要把不相干的東西都擠在同一個函式內
- 另外,請不要使用全域變數
(global variable) 在函式之間傳遞資料,這不只是程序化程式設計時的大敵,也是物件化程式設計的大敵
額外功能:
- 老師在某一次考試之後輸入成績時,會依照學號逐一輸入學生的成績,但是如果輸入時需要不斷地輸入學生姓名,會非常地不方便,請新增一個功能
9,老師可以選擇 "輸入全班成績",程式會把所有的學生依照學號排序後一一提示學生的姓名並要求輸入其成績
- 老師在考試之後除了記錄成績之外,也會希望記錄考試相關的資料,例如第一個成績是小考的成績,第二次是期中考的成績...,這些資訊希望能夠記錄在一個物件裡面,也希望能夠有一個介面讓老師可以增修這些資訊,也希望能夠在查詢或是列印時將這些資訊一起印出。如果你有製作這個功能的話,請特別說明你的設計
(類別的設計還有與其它類別關係的設計)
程式繳交說明:
- 請於時限內 (113/04/08 (一) 21:00)
上傳程式檔案以及文件檔案 (逾時無法上傳), 上傳tronclass
- 請編輯一個 report.docx (report.doc) 檔案, 說明你的演算法高階的模型, 概念上的作法,
資料結構, 你所完成的功能, 測試結果,... 以及對於此次作業各個部份的問題? (提出問題時請盡量整理你所知道的, 與你所懷疑的,
你所不認同的..., 如此會比空洞的 "我不懂 xxx?", "yyy 是什麼?" 要容易回答, 相對的你也比較容易得到你想要的答案)
- 請運用 StarUML
或是 其它軟體 繪製 類別圖 將圖片匯入 report.docx
(或是 report.doc) 報告檔中, 並且繳交 .cd 或是 .uml 檔案
- report.docx 中請說明你的心得 (心得可以包括你覺得你獲得的觀念, 你 debug 時發現的問題,
你 debug 的心得, 作業的感想, 你自己覺得比較好或是比較特別的設計...)
程式 Demo 說明:
- 程式 demo 時以所上傳的檔案為基準, 必須能夠現場編譯沒有錯誤
- 請說明你的測試方法與測試資料,並操作測試, 請將你要測試的資料先打好,例如 GradeDB2Input.dat,
利用 DOS 的重新導向來測試,例如 GradeDB2.exe < GradeDB2Input.dat > result.log
- 執行助教指定的測試資料
- 請回答你的程式在設計上的相關問題