C++ V2 · TYPED FOUNDATIONS · 52
Function / Loop / Scope:把 Typed Rule 變成可呼叫、可追蹤的單位
51 的規則還塞在 main。當你要處理 N 筆 score,重複程式碼會立刻出現。這一課用 function signature 表達 input/output contract,用 pass-by-value 建立 caller 與 callee 的 value boundary,再用 loop 套用規則。
Learning outcomes
- 能讀 return type、function name、parameter types。
- 能追蹤 argument → parameter → local state → return。
- 理解 pass-by-value 為何不改 caller object。
- 能用 for/while 處理多筆 typed input。
- 能區分 name scope 與 object lifetime 的基本關係。
1. Why now:重複 Copy/Paste 其實是在複製 Rule
if (score1 >= 60) { ... }
if (score2 >= 60) { ... }
if (score3 >= 60) { ... }
規則應該有一個 canonical implementation,資料則可以有多筆。
2. Mental model:Function Signature 是 Typed Contract
bool isPassed(
int score
) {
return score >= 60;
}
bool
→ caller receives bool
isPassed
→ function identity/name
int score
→ caller supplies int-like argument3. Worked Example A:Caller → Parameter → Return
int input = 72;
bool result =
isPassed(input);
caller input = 72
↓ copy value
parameter score = 72
↓ evaluate
72 >= 60
↓
return true
↓
result = true4. Pass-by-Value:Parameter 是另一個 Object
void addBonus(
int score
) {
score += 5;
}
int main() {
int score = 80;
addBonus(score);
std::cout << score;
// 80
}
function 內 local score 被改,但 caller 的 score object 沒變。
5. Worked Example B:Return 新值,而不是暗中修改 Caller
int withBonus(
int score,
int bonus
) {
int result =
score + bonus;
if (result > 100) {
result = 100;
}
return result;
}
score =
withBonus(
score,
5
);
這種 interface 把 state transition 明確放在 return value。
6. Scope:名稱在哪裡可見
int main() {
int outer = 10;
if (outer > 0) {
int inside = 20;
std::cout
<< inside;
}
// inside not visible here
}
Block scope 結束後,inside 名稱不可見;對 automatic local object,lifetime 通常也在離開 scope 時結束。
7. Worked Example C:for Loop 是 Controlled Repetition
for (
int i = 0;
i < 3;
++i
) {
std::cout
<< i
<< "
";
}
i=0 → condition true → body → ++i
i=1 → condition true → body → ++i
i=2 → condition true → body → ++i
i=3 → condition false → stop8. Loop Invariant:每輪都應維持的事
int passedCount = 0;
for (...) {
int score = 0;
std::cin >> score;
if (isPassed(score)) {
++passedCount;
}
}
每輪結束時,passedCount 應等於「目前已處理輸入中通過的數量」。這種 invariant 是 debug loop 的重要工具。
9. while:當次數不是事前固定
int score = 0;
while (
std::cin >> score
) {
std::cout
<< (isPassed(score)
? "Pass"
: "Fail")
<< "
";
}
這裡 loop condition 直接使用 stream extraction 是否成功。
10. Common mistakes
A. 忘記 return
非 void function 沒有正確 return 會破壞 contract;不要把 undefined behavior 當正常結果。
B. 以為 pass-by-value 會改 caller
caller state 不變是預期語意。
C. Off-by-one
i <= count 與 i < count 差一輪。
D. 在 loop 內重設 accumulator
passedCount 若每輪變回 0,就不再是跨輪 state。
11. Debug evidence:逐輪 Trace 比「看起來有跑」有效
input:
90 55 72
trace:
i score passedCount
0 90 1
1 55 1
2 72 2
Loop bug 時先記錄 iteration index、input、accumulator,而不是亂改 termination condition。
12. Guided exercise:gradeOf
std::string gradeOf(
int score
) {
// TODO
}
回傳 Excellent / Pass / Fail。要求先由 caller 做 0..100 validation,讓 function contract 保持簡單。
13. Independent exercise:N Scores
CLI 先讀 count,再讀 N 個 scores,最後輸出:
processed
passed
failed
把「是否及格」放在 function,不要複製 branch。
14. Challenge:直到 EOF
改成不先輸入 count,直接持續讀 score 直到 EOF。說明這版 loop termination contract 與 count-based loop 的差別。
Project checkpoint:CLI Grade Analyzer · Typed Core v2
main
├─ read input
├─ loop N / EOF
├─ call isPassed()
├─ call gradeOf()
└─ accumulate summary
functions
├─ isPassed(int) -> bool
└─ gradeOf(int) -> string
下一課會把「讀完就消失」的資料保存進 vector,並第一次真正區分 copy、reference 與 address。
15. Vocabulary / Summary
- signature:function 的名稱、參數與 return contract。
- argument:caller 傳入的 expression/value。
- parameter:callee 端接收 argument 的 local binding/object。
- pass-by-value:callee 收到獨立 value copy。
- scope:名稱可見的 source region。
- loop invariant:每輪應持續成立的條件。
16. Further reading
Knowledge check · Mastery
- 畫出 argument → parameter → return trace。
- 解釋 pass-by-value 為何不改 caller。
- 完成 N-score 與 EOF 兩種 loop。
- 完成頁面下方 C++ execution-trace practice。