← 12/17|期末筆試(範圍 Ch 1–12、Ch 14) | 回總覽 | 附錄 →
這是主課佔學期 40% 的關鍵一場,通常直接決定學期成績(實驗課的期末上機考是另一場、另外算分,題型見文末〈實驗課期末上機考模擬〉)。而且還有一個好消息:
期末上機比期中考進步 30 分以上,學期總成績可以加 1 到 3 分(依課程大綱)。
也就是說,期中考砸了也還有救,這場好好考回來,分數與加分一起拿。
當天的流程
流程與期中完全一樣,〈11/05 期中上機考〉的「上機考當天的流程」那五步請照著做:開場先搭 Makefile 架子 → 先掃過所有題目 → 每題寫完就 make 並跑範例 → 剩 15 分鐘停止寫新功能、make clean && make 確認乾淨重編 → 打包後找助教確認。
期末這場只有三點不同:
- 題數與時間依課堂公告為準,這份模擬考照六題 120 分鐘設計。時間是總量參考、不是順序(順序照上面第 2 步,從最有把握的開始):Q5 約 10 分鐘,Q2、Q4 各 15 分鐘,Q1、Q3 各 20 分鐘,Q6 最久 25 分鐘,留 15 分鐘機動與重編打包。題數一多,「先掃過所有題目再決定順序」就比期中更重要——把會的先寫完,比卡在一題硬想划算得多。
- 範圍涵蓋 Ch1–Ch12 與 Ch14,題目很可能要你同時用到類別、指標與檔案 I/O。看到題目先想「這題要用哪幾樣」,再動手。
- 可能出現多檔案題(把類別拆成
.h/.cpp)。那種題目的 Makefile 規則跟平常的模組化版本不同,〈11/26 分離編譯與命名空間〉的「多檔案的 Makefile」那一節有可以直接抄的寫法(注意.o規則一定要把.h列進相依),考前務必確認自己寫得出來。〈環境設置〉那份 Makefile 是「一題兩行」,Q6 有兩個.cpp要先各自編成.o再一起連結,照〈11/26〉的寫法多寫幾條規則(附錄有可以直接抄的版本)。
模擬上機考(建議計時 120 分鐘)
比照正式規則:只用文字編輯器、附 Makefile、零警告。單檔題的檔名是 Q1.cpp ~ Q5.cpp、執行檔同名;Q6 是多檔案題,檔案是 Student.h/Student.cpp/main.cpp,Makefile 要能編出名為 Q6 的執行檔。
Q1. 分數類別與運算子重載
寫 class Fraction,支援 +、-、*、/、==、<,以及 <<、>>。結果一律化為最簡分數,負號放分子;分母為 0(包括除以 0)時印 zero denominator 並結束程式。輸入的分子分母都在 int 範圍內,中間乘積要用 long long 算。讀入兩個分數後,依序輸出四則運算結果、是否相等(equal / not equal)、以及大小比較(a < b / a >= b),共六行。
1 | 輸入: 1 2 1 3 |
Q2. 動態陣列類別
寫 class IntList,內部用 int* 動態配置,支援 add(int)(容量不足自動加倍)、remove(int value)(刪除第一個符合的)、get(int index)、size(),並正確實作三法則。
輸入是一連串指令,ADD x 加入 x、DEL x 刪掉第一個等於 x 的元素、END 結束。DEL 找不到就印一行 not found。全部讀完後把串列內容印成一行,數字之間用一個空格隔開。
1 | 輸入: |
Q3. 檔案統計
讀取 grades.txt(每列:姓名 國文 英文 數學),輸出到 report.txt:每人的各科成績、總分與平均(兩位小數、欄位對齊),最後一列印全班各科平均。
1 | grades.txt: |
Q4. 字串處理
讀入一整行英文句子,輸出:
- 單字數
- 把每個單字的首字母改成大寫後的句子
- 反轉整個句子的單字順序
1 | 輸入: hello world from nsysu |
Q5. 繼承:商品
Product 有名稱與價格(整數),提供 describe()。派生 Food(多保存天數)與 Gadget(多保固月數),各自覆寫 describe()。先讀一行 名稱 價格 保存天數(Food),再讀一行 名稱 價格 保固月數(Gadget),各自印出描述。
1 | 輸入: |
Q6. 綜合:學生管理系統
把 class Student(姓名、學號、三科成績)拆成 Student.h / Student.cpp,main.cpp 先讀 n,再讀 n 列 姓名 學號 國文 英文 數學,依平均由高到低排序後,每人印一列:姓名、學號、總分、平均(兩位小數、欄位對齊)。必須用 Makefile 編譯多檔案專案,make 要能產生執行檔 Q6、make clean 要清乾淨。
1 | 輸入: |
Q1 參考解答
1 |
|
Q2 參考解答
1 |
|
Q3 參考解答
1 |
|
Q4 參考解答
1 |
|
用 istringstream 拆單字比自己逐字元判斷空白乾淨得多,而且多個連續空白也能自動處理。
Q5 參考解答
1 |
|
Q6 參考解答
Student.h
1 |
|
Student.cpp
1 |
|
main.cpp
1 |
|
Makefile
1 | CC = g++ |
實驗課期末上機考模擬(另一場考試)
實驗課的期末考是另一場(佔實驗課成績 40%,時間看助教公告),題型照每週練習題的形狀與我看過的幾份歷年考古題出(題目敘述、資料與解答是我重寫的,不是原題):括號配對、翻牌順序、讀檔排序、字典統計、通訊錄管理。五題建議 120 分鐘,同樣要求 Makefile 與零警告;Q3、Q5 會讀寫檔案,測試檔請自己照範例建立。
Q1. 括號配對
反覆讀入只含 ()[]{} 的字串直到輸入結束,判斷括號有沒有正確配對(左右同型別、順序正確)。必須自己用鏈結串列實作堆疊(11/19 Q7 那個),不能用 vector 代替。
1 | 輸入: |
Q2. 翻牌順序
一疊牌上寫著互不相同的整數。翻牌規則:翻開最上面一張並拿走;若還有牌,把下一張移到牌堆最底;重複直到翻完。請輸出一種牌的初始排列,使翻出來的順序是由小到大。
1 | 輸入: |
Q3. 學生檔多鍵排序
students.txt 每行「學號 姓名 國文 英文 數學」(姓名不含空白):
1 | B113040007 Ivy 88 92 75 |
讀入 struct 陣列後,反覆讀入模式:1 依學號遞增、2 依姓名 A→Z、3/4/5 依國/英/數遞減,0 結束;每次用氣泡排序排好後印出全部。交換要透過接收 Student* 的函式完成。
1 | 輸入: 1 2 5 0 |
Q4. 單字字典
讀入一段只含英文字母與空白的文字(讀到輸入結束),大小寫視為同一個字,統計每個不同單字出現幾次,依字母順序印出(全部小寫),最後印不同單字的數量。不能用 map。
1 | 輸入: Tea tea COFFEE milk Milk tea juice |
Q5. 通訊錄管理
contacts.txt 每行「編號 姓名 年齡 電話」。反覆讀入指令:1 編號 姓名 年齡 電話 新增(編號重複印 id exists)、2 編號 刪除、3 姓名 搜尋並印出符合者、4 編號 姓名 年齡 電話 修改、5 列出全部、0 結束;找不到就印 Not found。每個動作都要先從檔案讀、改完寫回檔案,程式重跑後資料還在。
1 | contacts.txt(初始): |
Q1 參考解答
1 |
|
考點與常見扣分:三種不合法要分開想——右括號來了但堆疊是空的、型別對不上、字串掃完堆疊還有東西。pop 之前一定先 empty(),否則對 nullptr 解參考直接 Segmentation fault。堆疊類別跟 11/19 Q7 幾乎相同,只是 pop 改成回傳彈出的字元。
Q2 參考解答
1 |
|
考點與常見扣分:這題直接想「初始排列」很難,換個角度:翻牌的規則其實是在決定「第幾張會在什麼位置被翻到」,跟牌面無關。所以用一個位置的清單 pos 模擬翻牌(拿走第一個、把下一個移到最後),依序把最小的牌填進被翻到的位置就好。erase(begin()) 加 push_back 就是「把第一個移到最後」。
Q3 參考解答
1 |
|
完整輸出:
1 | sorted by mode 1: |
考點與常見扣分:五種排序共用同一個氣泡排序,只把「這兩個順序有沒有錯」抽成 outOfOrder(x, y, mode),不要複製五份排序程式。swapStudent(&v[i], &v[i+1]) 取的是 vector 元素的位址,函式裡用 *a、*b 整包交換。字串的 > 直接就是字典序比較。
Q4 參考解答
1 |
|
考點與常見扣分:「不同單字」的表用 vector<Entry> 自己維護:每讀一個字先線性搜尋有沒有出現過,有就 count++、沒有就 push_back。for (char& c : w) 的 & 讓迴圈能改到原字串裡的字元,少了 & 轉小寫會轉在複本上。排序的比較條件是 dict[j].word < dict[i].word,string 的 < 就是字母順序。
Q5 參考解答
1 |
|
考點與常見扣分:把「讀檔」「寫檔」「找編號」各抽成函式後,五個指令每個只剩三四行。寫回檔案時用 ofstream 預設模式整個重寫(不是 ios::app),才不會愈寫愈長。load() 對不存在的檔案不會報錯、只是讀不到東西,所以第一次執行也能用。這個題型出自我看過的一份主課期末考考古題(敘述與資料是重寫的),也是這門課「struct + vector + 檔案 + 選單」四樣東西的總結。
對完答案之後
六題全對、make 零警告、make clean && make 乾淨重編,這場就穩了。哪一題寫不出來,回去補對應的那一篇:
- Q1 → 11/12 運算子重載、friend 與 string:
+ - * /、比較運算子、<<與>>只能是非成員函式(用 friend 直接讀 private,或透過 getter 都可以) - Q2 → 11/19 指標、動態記憶體與 C 風格字串:
new[]/delete[]與三法則 - Q3 → 12/03 檔案輸入輸出:
ifstream/ofstream、開檔檢查、setw對齊 - Q4 → 同上(
istringstream拆單字)+ 11/12:string的操作 - Q5 → 12/10 繼承:
protected、建構子怎麼串、覆寫成員函式 - Q6 → 11/26 分離編譯與命名空間:
.h/.cpp拆檔、include guard、多檔案 Makefile
說些什麼吧!