← C++ Learning Path

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

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 argument

3. 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 = true

4. 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 → stop

8. 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

16. Further reading

Knowledge check · Mastery

  1. 畫出 argument → parameter → return trace。
  2. 解釋 pass-by-value 為何不改 caller。
  3. 完成 N-score 與 EOF 兩種 loop。
  4. 完成頁面下方 C++ execution-trace practice。