(2021 最新) 用 VSCode 寫 C++ 教學 - Part 2

上一篇教學有教大家怎麼自己建立簡單的 C++ 環境了。
但你以為就只有這樣嗎?其實這樣根本不夠,我打競賽根本不只安裝這些東西呢!

(競賽我會用的應該會放在 Part 3)

今天來介紹常用的 IntelliSense 跟 GDB 吧!

IntelliSense 設定

IntelliSense 其實就是 Code Auto-Completion,也就是程式碼自動完成,打上一些關鍵字就可以知道你想做什麼。

安裝 C/C++ 延伸套件

上次教學連 C/C++ 官方套件都還沒裝呢!不過它還不錯用喔,趕快裝起來吧

安裝完後就會發現

欸?都用好了?
我完全不用設定欸!

但這樣篇幅有點少,我完全不能湊字數

按下 ctrl + shift + p 打開命令選擇區,打上 c/c++: edit,選擇 編輯組態 (UI)

這時候就會跳出來 C/C++ Configuration,同時在 .vscode 資料夾裡面多了 c_cpp_properties.json

我就針對基礎選項來做一些介紹。

IntelliSense 選項介紹

設定名稱:就保持它原本的 Win32 就好,想改好像也不影響,不要改成其他的特殊識別項就好了。

編譯器路徑:找你的 gccg++ 在哪,這裡我會改成 g++.exe,為了整合方便就選擇 g++.exe

編譯器引數:需要額外為編譯器加哪些參數。但這裡也不需要特別動它。

如果有需要編譯成 32 bit 需求,也可以打在這裡,如果打上 -m32,下面的選項會發出 Warning 已自動切換 IntelliSense 模式,需要注意一下。

IntelliSense 模式:這裡也要選好,系統才知道你要套用什麼樣的 Code Auto-Completion,也要跟剛剛上述所說的設定相符。

Windows 系統,g++ 編譯器,64 位元,當然就選它啦。

上面編譯器路徑選 g++,這裡如果直接選擇 msvc,系統會直接說不相容。

包含路徑:這裡就是專門給自訂路徑的標頭檔,E.g. #include 'testlib.h',這種非原本編譯器所提供的,讓 IntelliSense 不會隨便就跳出找不到檔案,基本上也不需要動它。

定義:這裡你也可以先 Define 一些東西,這個在有些競賽程式模板也會常常用。

入門、基礎的不需要動它也沒關係。
已經進階知道模版的用法可以直接在這裡打上你要的 Local Define。

C 標準 / C++ 標準:就是選擇標準版本。

剛入門的不需要動它也沒關係。
主流的 Online Judge 都有支援 C++ 11/14/17,就直接選 gnu++ 後面所對應的版本即可。

進階設定的選項,我也用不太到,有需要的人就自行 Google 啦!

設定完後,你的 .vscode/c_cpp_properties.json 大概會長得像這樣子,根據各自需求去調整即可。

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "compilerPath": "C:/TDM-GCC-64/bin/g++.exe",
            "cStandard": "gnu17",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "windows-gcc-x64"
        }
    ],
    "version": 4
}

GDB

接下來就來設定 VSCode + GDB 除錯工具吧

BTW 這裡開始都是參考 VSCode 的官方教學,文章下面會附上連結。

設定 Build 工作

檔案選擇任意 C++ 程式檔案,按下上方選單終端機,裡面有個選項叫做設定預設組件工作。

這裡就會跳出 cppg++ 選項,其實這裡沒差,確保前後一致就選 g++

選擇完後就會多一個檔案,.vscode/tasks.json,長的類似這樣。

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe 建置使用中檔案",
            "command": "C:/TDM-GCC-64/bin/g++.exe",
            "args": [
                "-g",
                "${file}",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe"
            ],
            "options": {
                "cwd": "C:/TDM-GCC-64/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "編譯器: C:/TDM-GCC-64/bin/g++.exe"
        }
    ]
}

補充說明:選擇 C++ 標準版本、參數

如果照 VSCode 設定,他沒有不會寫版本,沒有指定版本就照編譯器的預設。
想要指定版本可以在 args 加入你要的編譯版本 "-std=c++14"
如果想打開所有警告跟額外警告,就分別加上 "-Wall""-Wextra"

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe 建置使用中檔案",
            "command": "C:/TDM-GCC-64/bin/g++.exe",
            "args": [
                "-g",
                "${file}",
                "-std=c++14",
                "-Wall", 
                "-Wextra",
                "-O2",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe"
            ],
            "options": {
                "cwd": "C:/TDM-GCC-64/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "編譯器: C:/TDM-GCC-64/bin/g++.exe"
        }
    ]
}

補充說明:多檔案編譯

這裡的 tasks.json 是給單檔案編譯用的,如果想要改成寫 C++ 專案,也可以直接調整 args 的參數。

Line 10 的 ${file} 改為 ${workspaceFolder}\\*.cpp,就會把你該資料夾底下的 cpp 都拿進來編譯。
Line 12 的 ${fileDirname}\\${fileBasenameNoExtension}.exe 也可以直接改為 ${fileDirname}\\Main.exe,把編譯完成後的執行檔指定名字。’

改完後就會長像這樣

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe 建置使用中檔案",
            "command": "C:/TDM-GCC-64/bin/g++.exe",
            "args": [
                "-g",
                "${workspaceFolder}\\*.cpp",
                "-o",
                "${fileDirname}\\Main.exe"
            ],
            "options": {
                "cwd": "C:/TDM-GCC-64/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "編譯器: C:/TDM-GCC-64/bin/g++.exe"
        }
    ]
}

這樣就可以改成類似 C++ 專案編譯了,不過為了方便 Demo 起見,我還是改為原本的 tasks.json

把 GDB 掛上 Debugger

按下上方執行,有個選項叫做新增組態

選擇後會有兩個選項,因為我們是用 GDB,當然就選擇 GDB。

跑 Demo 的時候,其實我也沒頭緒為何會有兩個組態,選下面會再多出一個版本,遇到有重複的就選上面吧!

選擇完以後,VSCode 就會進入除錯器模式了,看到底下變橘色,就已經成功一半了。

同時也多了一個 .vscode/launch.json 檔案

注意事項:開 GDB 時,資料夾或檔案名稱不要有任何中文

有些人到這裡就會跳出下列錯誤

這裡推測原因是 GDB 不能接受中文文字的關係。
編譯有中文字是可以編譯,也可以執行,但要開啟 GDB 除錯模式就會直接報 Error。

請確定你的資料夾跟檔案不要命名成中文,上層的資料夾也不要有任何中文(像是桌面、文件資料夾),有中文字換掉就好,不需要重做上面的步驟。

如果有人解開這 Unicode 問題麻煩再底下留言跟我說吧。

測試 GDB Debugger 1

首先拿出我們的測試程式

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string name;
    cin >> name;
    cout << "Hello " << name << "!" << endl;
    return 0;
}

我們在輸出 Line 8 前設個中斷點,往數字旁停過去就會有小紅點,按一下就會有實心小紅點了。

按下 F5 啟動偵錯。

跑完後就會像是這樣子。

輸入一段文字吧,範例使用 Jerry,按下 Enter 後,就會看到它停留在中斷點了。

這裡能看的東西真的很多,連 CPU Register 都可以看(基本上 GDB 常用的東西都會在這裡出現)

那就來加入一些稍微複雜的 Code,這段 Code 是來自官方教學的。

測試 GDB Debugger 2

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"};

    for (const string& word : msg)
    {
        cout << word << " ";
    }
    cout << endl;
}

Line 9 & 13 上中斷點,按下 F5 開始除錯吧!

它在 Line 9 停下來,這時候 msg 還沒被建立,按下上方第二個按鈕不進入函式(Step over)。

這時候你就會看到它停留在下一行的 for,你也可以看到它的 msg 建立出來了。

也可以在監看這裡打上區域變數 word 來看看變化情況。

按下上方第三個按鈕逐步執行(Step into)。

就會看到程式跳進去 STL 的變化情形喔。

按下上方第一個按鈕繼續(Continue),就會繼續跑,直到下一個中斷點。

好了,這邊很基礎的 GDB 設定就是這樣啦,就可以來好好除錯,不要再用什麼 printf / cout Debug 了,GDB 很香的

簡介 Debugger 按鈕作用

在上面範例中,我稍微講一下這些按鈕在做啥。

第一個按鈕:繼續(Continue),按下去後會持續跑,直到下個中斷點。
第二個按鈕:不進入函式(Step over),按下去後,會到在目前這 Function 跑到下一個敘述。
第三個按鈕:逐步執行(Step into),按下去後,會進入到每一部 Function 執行敘述並中斷。
第四個按鈕:逐步執行(Step out),按下去後,會直接把 Function 執行完並中斷。
第五個按鈕:重新起動,重跑 GDB 偵錯。
第六個按鈕:停止,停止 GDB 偵錯。

FAQ

上一篇用 Code Runner 編譯出來的程式能直接使用 GDB 嗎?

不行,Code Runner 的編譯參數沒有 -g,是不會有 Debug 資訊。
基本上我會想把「一般執行」跟「除錯執行」分開,「一般執行」給 Code Runner,「除錯執行」給 VSCode Debugger。
畢竟 VSCode Debugger 已經留好位置給 GDB 了,就不需要再拿到命令列執行了。

總結

看到這裡,恭喜你,你的 VSCode C++ 有了自動完成,也有了一般 IDE 常有的除錯功能,而且不用裝到像 Visual Studio 這麼肥的工具包,是不是很棒呢?

下一篇會介紹我在競賽中常用的延伸功能,可能為這系列的最後一篇。

如果覺得這篇很讚,麻煩就在文章下方左下角按多一點的 Like,並且幫我分享出去給需要的朋友看吧!

也可以順便在右上角按下 RSS 訂閱追蹤我,那就下一篇文章見,ㄅㄅ!

References


本部落格所有文章除非特別說明以外,均採用 CC BY-SA 3.0協議 。轉載請註明出處!