① Windows 同學分流:只跑課程 notebook → 走 PART 04 的路線 0(kernel 自動裝 g++);要在 VS Code 寫作業 → 走路線 A/B,直到 g++ --version 與 gdb --version 都有輸出。
② 照用途選工具:課程 notebook 走 PART 01;作業程式接著讀 00C。
③ 完成 PART 05 環境驗收:指令或 include 失敗就回到對應步驟。
④ 最後翻 關鍵詞彙卡,能不看答案講出定義才算過關。
Python 的直譯器讀一行執行一行;C++ 要先編譯成執行檔才能跑。所以你至少需要一個編譯器(g++);想下中斷點除錯,還需要 gdb。
VS Code 是編輯器,微軟的 C/C++ 擴充套件提供語法上色、IntelliSense 與除錯介面,兩者都不包含 compiler 或 debugger。Windows 同學分流:只跑課程 notebook → 走 PART 04 的路線 0(kernel 自動裝 g++);要在 VS Code 寫作業 → 走路線 A/B,直到 g++ --version 與 gdb --version 都有輸出。
這門課有兩種工作:講義是 Jupyter notebook;作業則是一般的 .cpp 專案。它們共用同一套 compiler,但操作介面不同:
| 方法 | 時間 | 能跑課程 notebook | 適合誰 |
|---|---|---|---|
| ① Jupyter + C++ kernel 講義用 | 15 分鐘 | ✅ 可以 | 執行課程 notebook、逐格練習 |
| ② Windows VS Code + g++/gdb 作業首選 | 20–30 分鐘 | ❌ 編譯一般 .cpp | 寫作業、編譯多檔、執行與除錯 |
| ③ 線上編譯器 | 0 分鐘 | ❌ 完全不行 | 臨時想試一小段、或電腦不能裝東西 |
Python 課可以用 Google Colab 免安裝,C++ 不行 —— Colab 只提供 Python kernel,裝不了 C++ kernel。所以本課的講義 notebook 一定要在本機跑。這也是為什麼方法①值得花那 15 分鐘。
需要三樣東西:g++、Python 與 pip、以及 JupyterLab。Linux 與 WSL 通常已經有 g++;macOS 裝 Xcode Command Line Tools;Windows 請先看 PART 04。裝完之後,講義 notebook 只要下載 .ipynb 一個檔案就能跑:課程標頭內建在 kernel 裡,測驗題目從 GitHub 線上載入。
jupyterquiz 與 jupytercards 分別供測驗與詞彙卡使用。pip install --user,Jupyter 找不到安裝的 kernelspec,kernel 選單就不會出現 C++。%LOCALAPPDATA%\jupyter-cpp-kernel\mingw64,並寫入使用者 Path;不必操作 PART 04。上游版本的編譯指令少了 -I.。kernel 會把每個 cell 寫進一個暫存檔再編譯,而 #include "pythonds3/cppds/stack.hpp" 這種帶引號的相對 include,g++ 是相對「原始檔所在目錄」去找 —— 也就是暫存目錄,當然找不到。課程從第 06 章起大量使用這種寫法,所以要用補過這一行的版本。
差異只有一行,原始碼在 phonchi/jupyter-cpp-kernel(nsysu-math208 分支),fork 自 shiroinekotfs 的原專案,MIT 授權。
這個 kernel 套件沒有宣告任何相依套件。只裝它而沒裝 JupyterLab 的話,一 import 就會噴 ModuleNotFoundError: No module named 'ipykernel'。裝完 jupyter kernelspec list 應該會看到 cpp03 到 cpp23 一整排,這門課用 cpp17。
建一個沒有中文與空白的資料夾當教材目錄(例如 C:\ds208),之後 jupyter lab 一律從這裡啟動。每週從課程網站 Lectures 頁下載當週的 .ipynb(GitHub 頁面右上角 Download raw file)放進去,就這樣。
不用另外抓任何東西:講義 #include "pythonds3/cppds/stack.hpp" 用到的課程標頭已經內建在 C++ kernel 套件裡(kernel 編譯時自動加 -I),選擇題與詞彙卡則從 GitHub 線上載入(執行時要有網路)。
想在終端機或 VS Code 直接編譯用到課程標頭的 .cpp(notebook 以外),才需要 git clone https://github.com/phonchi/pythonds3 到 .cpp 同一層,並以 g++ -std=c++17 -I. main.cpp 編譯;標頭在 pythonds3/cppds/*.hpp,就是課程網站 Resources 指的那個 repo。
這個 kernel 在編譯每一個 cell 之前,都會自動先加上一份共用標頭
gcpph.hpp。所以有些標準函式庫不寫 #include 也能用 —— 但不是全部,
分清楚哪些有帶、哪些要自己寫:
| 狀態 | 標頭 | 影響 |
|---|---|---|
| ✅ 自動帶入 | <iostream> <string> <vector> <algorithm> <cmath> <sstream> <fstream> <iomanip> <stdexcept> | cout、string、vector、sort、sqrt、setw、例外型別…不寫 include 就能用;ctype.h/stdlib.h 等 C 標頭也在內,所以 isdigit、rand 也直接可用 |
| ❌ 要自己寫 | <map> <set> <unordered_map> <unordered_set> <stack> <queue> <deque> <chrono> <climits> | 忘了寫會得到 'map' was not declared 這類編譯錯誤 —— 講義從第 06 章起常用,cell 裡都有示範寫法 |
講義的 cell 大多仍把 #include 寫好寫滿 —— 那是刻意的:同一段程式碼貼到 VS Code 或線上編譯器也要能動。自己寫作業時請比照辦理,不要依賴 kernel 的自動帶入。完整清單見
gcpph.hpp 原始碼。
#include,就要自己寫 main()kernel 的規則是看 cell 裡有沒有 main(:沒有的話,它會把整格內容自動包進
int main() { … return 0; } 再編譯 —— 所以講義很多格只寫兩三行敘述就能跑。
但這也表示:如果你的 cell 有 #include 卻沒寫 main,那行 include 會被包進 main 的身體裡,
整個標頭檔的內容被塞進函式中,編譯直接噴出一長串看不懂的錯誤。
| 你的 cell 長怎樣 | 怎麼寫 |
|---|---|
幾行小片段,只用到自動帶入的東西(cout、vector…) | 不用 main,直接寫敘述(kernel 幫你包) |
有任何 #include(如 <map>、課程標頭) | 寫完整程式:include 放最上面+自己的 int main() |
講義 cell 兩種形態都有,照抄不會錯;自己開新 cell 實驗時記得這條規則。
① 開終端機,cd 到放 .ipynb 的教材資料夾(之後要在終端機自己編譯的同學,先看下面的警告框)。
② 執行 jupyter lab。
③ 開啟 .ipynb,右上角 kernel 選 C++ 17,按 Shift + Enter 執行第一格。
症狀:cell 一執行就跳出 Windows 對話框「無法找到程序輸入點 …seekpos… 在動態連結程式庫 …\Temp\tmp_xxxx.out」。原因是 conda 在 activate 時會把 anaconda3\Library\mingw-w64\bin 插到 Path 最前面,裡面有一份舊的 libstdc++-6.dll,蓋掉你在 PART 04 裝的那套。編譯用的是新 g++,執行時卻載到舊 DLL,所以對不上。這是執行期插隊,在「環境變數」設定裡把 bin 排到最前面也沒用。
診斷:在啟動 Jupyter 的那個視窗執行 where.exe libstdc++-6.dll。第一筆必須是你在 PART 04 確認過的那個 bin;如果第一筆在 anaconda3 底下,就是這個問題。
解法擇一(下面的 C:\mingw64\bin 請換成你自己的 bin):
① 臨時:啟動前先 set PATH=C:\mingw64\bin;%PATH%,再執行 jupyter lab。
② 永久:在 <conda 根目錄>\etc\conda\activate.d\ 新增 mingw64.bat,內容一行 @set PATH=C:\mingw64\bin;%PATH%。根目錄用 conda info --base 查;若是用具名環境啟動 Jupyter,路徑改為 envs\<環境名>\etc\conda\activate.d\。重開 Anaconda Prompt 後再跑一次 where.exe 確認順序。
不要為了這件事移除 conda 的 mingw-w64 套件,它們是其他 conda 套件的相依。
一般同學不需要這一段,直接在 notebook 裡讀跟執行就好。若你想像上課那樣切成投影片模式,注意舊版 RISE(pip install rise)只支援 classic Notebook 6 以下,在 Notebook 7 與 JupyterLab 4 裡不會出現 View → Cell Toolbar → Slideshow,也沒有投影片按鈕 —— 不是你漏設定,是擴充套件架構換掉了。改裝新版:pip uninstall rise 再 pip install jupyterlab_rise(需 JupyterLab ≥ 4.1.2),然後重新啟動 Jupyter。新版的設定方式也不同:選取 cell 後在右側 Property Inspector(齒輪圖示)指定 slide / subslide / fragment,再按 Ctrl+R(Mac 是 Option+R)進入投影片模式。
作業常有多個 .cpp、自己的標頭檔、命令列參數與資料檔,不能只按「執行目前檔案」。本站把完整流程獨立成 00C · Windows VS Code 作業實戰:從開資料夾、設定三份 JSON,到編譯、執行與中斷點除錯都會實做。
① C/C++ 擴充套件不含 g++ 或 gdb。
② 寫作業要在 VS Code 開啟整個資料夾,不是只點開某一個 .cpp。
③ 多檔作業要明列需要編譯的 .cpp;完整範例與三份 JSON 請讀 00C。
-Wall 是學習期最划算的一個旗標它會把「編譯得過但很可疑」的地方講出來:用了未初始化的變數、把陣列當指標算 sizeof、有分支沒回傳值。這些正是 C++ 最容易安靜出錯的地方。P1 會教怎麼讀這些訊息。
想臨時試一小段語法、或手邊電腦不能安裝東西時很好用。但它只能跑單一檔案:課程的 pythonds3/cppds/*.hpp 沒辦法 include,notebook 更不用說。
| 工具 | 強項 |
|---|---|
| Compiler Explorer | 看得到編譯出來的組合語言,也能同時比對不同編譯器與最佳化等級。想知道「編譯器到底幫我做了什麼」就用它。 |
| OnlineGDB | 附一個真的除錯器,可以下中斷點、單步、看變數。學指標時很有用。 |
| C++ Tutor | 把記憶體畫出來給你看:堆疊、堆積、指標的箭頭。P4 會整頁靠它。 |
Windows 沒有內建 GNU C++ 工具鏈。只跑 notebook 的人走路線 0,什麼都不用手動裝;筆電要寫作業、或想自選版本的人,從路線 A/B 選一條即可,不要兩套都裝,以免 Path 先後順序互相打架。
照 PART 01 執行 python -m jcppkernel.setup_cli(這一步負責註冊 kernel、不可省;g++ 的下載才可以延後到第一個 cell)。kernel 找不到 g++ 時,會自動下載課程精簡版的 winlibs GCC 12.1(UCRT)到 %LOCALAPPDATA%\jupyter-cpp-kernel\mingw64——在你的使用者資料夾裡,不需要管理員權限——約 100 MB 下載(8 條連線分段抓,有進度條)、解開後約 450 MB。精簡版只拿掉 Fortran、Objective-C 與文件,C/C++ 編譯與 gdb 完整;抓不到時會自動退回 winlibs 官方的 198 MB 原版。之後 kernel 一律用完整路徑呼叫這套 g++,並把它的 bin 排在子行程 Path 最前面,所以 Anaconda 那份舊 DLL 也蓋不到它。同時會把這個 bin 寫進使用者層的 Path,新開的終端機與 VS Code 就能直接用 g++、gdb。
電腦上已經有 g++(路線 A/B 或別的來源)的話,kernel 會直接用現成的,不會重複下載。想強制指定某一套:設環境變數 JCPP_GXX 指到 g++.exe 的完整路徑。
整班同時下載時校內對外頻寬可能塞住。可以先用別的網路(或請同學分享)抓好檔案,再自己放進去,kernel 會自動偵測,完全不用碰系統槽(C:\):
① 下載 zip:課程精簡版(100 MB),或 winlibs 官方 12.1.0 UCRT r3 的 winlibs-x86_64-posix-seh-gcc-12.1.0-mingw-w64ucrt-10.0.0-r3.zip(198 MB)。
② 解壓後會得到一個 mingw64 資料夾,把它放到 C:\Users\你的帳號\mingw64(也就是 %USERPROFILE%\mingw64),確認裡面有 bin\g++.exe。
③ 重新執行 python -m jcppkernel.setup_cli,或直接開 notebook。它會印出「使用現有 g++:…\mingw64\bin」,不會再下載。
這種放法 kernel 找得到,但不會幫你寫進 Path;要在終端機或 VS Code 用的話,照路線 B 的步驟把那個 bin 加進使用者 Path。
① 安裝 MSYS2,保留預設位置 C:\msys64。
② 在剛開啟的 MSYS2 終端執行 pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain,按 Enter 接受整組套件,再輸入 Y。
③ 完成後工具通常在 C:\msys64\ucrt64\bin;確認裡面真的有 g++.exe 與 gdb.exe。
① 到 winlibs.com 下載 64-bit GCC + MinGW-w64 套件。
② 解壓到沒有中文與空白的路徑。若解壓後是 C:\mingw64\bin\g++.exe,要加進 Path 的就是 C:\mingw64\bin;不要憑印象猜資料夾。
③ 同一個 bin 裡也必須看到 gdb.exe,否則只能編譯、不能照 00C 除錯。
Path →「編輯」→「新增」。bin 完整路徑,連按「確定」關閉視窗。where.exe 可能列出多筆。真正會被使用的是第一筆;00C 三份 JSON 裡的路徑也要指向同一套工具鏈。
電腦教室若已有 Dev-C++,可以臨時開舊專案;但版本與內附 compiler 常較舊,設定方式也和本課作業支援不同。自己電腦上的作業請優先使用 Windows VS Code。
系統管理員 PowerShell 執行 wsl --install,重開機後在 Ubuntu 裡安裝 g++、gdb 與 Python。VS Code 還要安裝 WSL extension,並從 WSL 資料夾執行 code .。Windows 路徑與 WSL 路徑是兩個環境;初學者不要混用。
先確認 g++ --version 與 gdb --version 都成功;再把下面這段存成 check.cpp(或貼進一個 notebook cell)執行。沒有噴錯、而且印出五行,才代表編譯環境與課程標頭都就緒。
C++ 標準 : 201703 (201703 = C++17) g++ 版本 : 13.3 Stack : pop=7 peek=42 size=1 LinkedList: size=2 search(31)=1 環境檢查通過,可以開始第 01 章。
版本號跟你的不一樣沒關係,C++17 以上都可以。重點是兩個課程標頭都 include 成功——在 notebook 裡那代表 kernel 裝的是課程 fork(標頭內建);在終端機編譯則要先 clone pythonds3 到同一層並加 -I.:g++ -std=c++17 -I. check.cpp -o check。
四項都打勾後,執行 notebook 的同學可進 第 01 章 · C++ 導論;準備寫作業的同學接著完成 00C · Windows VS Code 作業實戰。
第 01 章的第一個 cell 就會 #include 課程的標頭檔。這一節過不了,那一章一行都跑不動。
這個 kernel 把每一個 cell 當成一支獨立的完整程式去編譯執行。理解這一句,下面六個坑就都說得通了。
cell 之間沒有共用狀態。每個 cell 各自編譯成一支程式,跑完就結束。所以 class 定義和用到它的 main() 必須寫在同一格。這也是課程講義把「類別定義 + 示範」合併成一格的原因。
cout 編不過[編譯失敗]
cell.cpp: In function ‘int main()’:
cell.cpp:2:5: error: ‘cout’ was not declared in this scope
2 | cout << "hello" << endl;沒有寫 main() 的 cell 會被 kernel 自動包進一個 main(),但那個包裝不會幫你加 using namespace std;。短 cell 自己在開頭寫一行,或全部用 std::cout 前綴。
map、set 說沒宣告錯誤訊息長這樣:error: ‘map’ was not declared in this scope——kernel 自動帶入的標頭裡沒有這一個,要自己寫 #include。哪些有帶、哪些要自己寫的清單,見 PART 01 的「kernel 已經幫你 include 的標頭」卡。
沒有 main( 的 cell 會被整段包進 main(),函式定義變成「函式裡面的函式」、template 類別變成區域類別(區域類別不能是 template),錯誤訊息像 error: a function-definition is not allowed here。規則與寫法見 PART 01 的「cell 裡寫了 #include,就要自己寫 main()」框。
//kernel 在編譯前會用正規表示式把註解剝掉,而它看不出來 // 是在字串裡面,會從那裡整行切斷。所以別把網址寫進字串字面值。真的需要就拆成 "https:/" "/example.com" 兩段接起來——重點是讓兩個斜線不相鄰。
#include "pythonds3/cppds/…" 找不到檔案在 notebook 裡:課程標頭隨課程版 kernel 一起安裝。遇到找不到標頭的錯誤,先確認安裝來源是 phonchi/jupyter-cpp-kernel 的 nsysu-math208 分支,再依 PART 01 的方式重裝課程版 kernel(pip install --force-reinstall --no-deps "https://github.com/phonchi/jupyter-cpp-kernel/archive/refs/heads/nsysu-math208.zip"),重啟 JupyterLab。
在終端機用 g++ 編譯:要先 git clone https://github.com/phonchi/pythonds3 到 .cpp 同一層,並加 -I.。測驗與詞彙卡的題目是從 GitHub 線上抓的,與目錄無關;沒出現時先確認有網路。
接著檢查 Windows 的 DLL 載入路徑與 Jupyter 啟動網址。
執行任何 cell 都跳出 Windows 錯誤對話框,訊息裡有一長串 _ZNSt15basic_streambuf…seekpos… 和 Temp\tmp_xxxx.out——這是執行時載到另一套較舊的 libstdc++-6.dll。診斷與處理方式見 PART 01 的「注意 Anaconda 的舊 libstdc++」警告框。在 notebook 遇到時,先重裝課程版 kernel 並重啟 JupyterLab;若仍出現錯誤,再依該說明檢查 DLL 路徑。
執行 jupyter lab 後瀏覽器自動開啟,卻顯示「無法存取你的檔案,檔案可能已遭到移動、編輯或刪除 ERR_FILE_NOT_FOUND」。先看網址列:正常應該是 http://localhost:8888/lab(Notebook 7 則是 /tree),如果是 file:///C:/Users/… 開頭就是這個問題 —— Jupyter 用來自動開頁的暫存 HTML 沒被瀏覽器正確接手,使用者名稱含中文、或從 Google Drive/OneDrive 同步資料夾啟動時特別常見。Jupyter 本身其實已經在跑:回到終端機,把它印出來的 http://localhost:8888/lab?token=… 整行複製貼進瀏覽器網址列即可。
00A 說過:AI 要當助教,不要當代工。C++ 這門課有一個特別適合用 AI 的場合 —— 翻譯編譯錯誤訊息。template 出錯時 g++ 可以吐出兩百行,那不是給人讀的。
不管你用 VS Code 的 Copilot、還是網頁版的模型,把這段設成常駐指令:
最後兩行是這門課的重點。讓它每次都順便講複雜度與記憶體歸屬,你會被動地養成這兩個反射。
AI 給的程式碼你要為它負責。作業與考試考的是你會不會,不是它會不會。把它當成隨時在旁邊的助教:可以問、可以吵,但最後那一行要自己按下去。
| 資源 | 用途 |
|---|---|
| jupyter-cpp-kernel(課程 fork) | 補過 -I. 的 C++ kernel,PART 01 用的就是它。 |
| VS Code · Using GCC with MinGW | 微軟官方的 MSYS2、Path、編譯與除錯教學。 |
| MSYS2/WinLibs | Windows 原生 GCC/GDB 的兩種安裝來源。 |
| cppreference | C++ 標準函式庫的權威文件,含各操作的複雜度保證。 |
| cppds 教科書原文 | 本站每章 §徽章對應的章節。 |
| nsysu-math208 | 課程講義、投影片與 notebook。 |
| C++ Tutor | 逐行視覺化記憶體與指標,不需要安裝任何東西。 |
先看正面術語,心中默想定義再翻面對答案;洗牌後再過一輪,直到每張都能不假思索說出來。