把 VS Code 打造成 LeetCode 神器

1. 方案选择

最近发现好久不看算法了,自己的能力有些松懈和退步了,便捡起 LeetCode 刷刷题,在选择IDE时发现:Vim 太简陋,Eclipse 操作太繁杂,VS Code 正合适。我把 VS Code 用于编写小小型C++项目的配置方式记录下来。
VS Code 提供 C/C++ for VS Code 插件,提供下面 C++ 语言方面的支持(Language service):

  • Code Formatting (clang-format) 代码格式化
  • Auto-Completion (experimental) 自动完成
  • Symbol Searching 符号搜索
  • Go to Definition/Declaration 定义跳转
  • Peek Definition/Declaration 定义预览
  • Class/Method Navigation 类/方法 导航
  • Signature Help 帮助提示
  • Quick Info (Hover) 鼠标浮动提示
  • Error Squiggles 错误曲线标识

下面开始配置,仅记录 Linux 环境下的配置:

2. 编译配置

在 VS Code 中打开工具窗口 (Ctrl+Shift+P) ,输入 C/CPP: Edit Configurations 来生成配置文件 c_cpp_properties.json 可以添加一些自定义 include 路径,如果不使用外部的第三方库,默认配置可以直接使用。

C++ 是需要编译的,VS Code 把代码的 linting, building, packaging, testing , deploying 都归结为 Tasks 我们需要配置一个或者多个 Tasks 来完成编译任务

打开工具窗口 (Ctrl+Shift+P) → 输入 Tasks: Configure Task Runner,弹出窗口中选择 Others 在新打开的tasks.json中配置如下:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build-release",
            "type": "shell",
            "command": "g++",
            "args": [
                "*.cpp",
                "-o${workspaceRootFolderName}"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [
                "$gcc"
            ]
        },
        {
            "label": "build-debug",
            "type": "shell",
            "command": "g++",
            "args": [
                "-g",
                "*.cpp",
                "-o${workspaceRootFolderName}"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [
                "$gcc"
            ]
        },
        {
            "label": "make default",
            "type": "shell",
            "command": "make",
            "args": [
                "default"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "label": "make all",
            "type": "shell",
            "command": "make",
            "args": [
                "all"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [
                "$gcc"
            ]
        },
        {
            "label": "make clean",
            "type": "shell",
            "command": "make",
            "args": [
                "clean"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [
                "$gcc"
            ]
        }
    ]
}

3. 调试配置

配置完成后可以使用 Ctrl+Shift+B 快捷键来执行编译,编译成功后就是调试运行(debug) ,VS Code 的调试有专用的模块,进入调试模块,选择 C++(GDB/LLDB) 此时会生成调试配置文件 launch.json,输入下面的配置信息:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch direct",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/${workspaceRootFolderName}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        },
        {
            "name": "(gdb) Launch makefile",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/debug/${workspaceRootFolderName}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

然后就可以使用快捷键 F5 进行调试了。

4. Makefile 模板

下面列出了一个简易的 Makefile 模板:

# Fork from https://github.com/TheNetAdmin/Makefile-Templates
# tool marcros
CC := g++
CCFLAG := -std=c++14
DBGFLAG := -g
CCOBJFLAG := $(CCFLAG) -c

# path marcros
BIN_PATH := bin
OBJ_PATH := obj
LIB_PATH := lib
SRC_PATH := src
DBG_PATH := debug

# compile marcros
TARGET_NAME := $(shell pwd | awk -F '/' '{printf $$(NF)}')
ifeq ($(OS),Windows_NT)
    TARGET_NAME := $(addsuffix .exe,$(TARGET_NAME))
endif
TARGET := $(BIN_PATH)/$(TARGET_NAME)
TARGET_DEBUG := $(DBG_PATH)/$(TARGET_NAME)

# src files & obj files
SRC := $(foreach x, $(SRC_PATH), $(wildcard $(addprefix $(x)/*,.c*)))
OBJ := $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
OBJ_DEBUG := $(addprefix $(DBG_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))

# clean files list
DISTCLEAN_LIST := $(OBJ) \
                  $(OBJ_DEBUG)
CLEAN_LIST := $(TARGET) \
              $(TARGET_DEBUG) \
              $(DISTCLEAN_LIST)

# default rule
default: arch

# non-phony targets
$(TARGET): $(OBJ)
	$(CC) $(CCFLAG) -o $@ $?

$(TARGET_DEBUG): $(OBJ_DEBUG)
	$(CC) $(CCFLAG) $(DBGFLAG) $? -o $@

$(OBJ_PATH)/%.o: $(SRC_PATH)/%.c*
	$(CC) $(CCOBJFLAG) -o $@ $<

$(DBG_PATH)/%.o: $(SRC_PATH)/%.c*
	$(CC) $(CCOBJFLAG) $(DBGFLAG) -o $@ $<

# phony rules
.PHONY: arch
arch:
	@mkdir -p src obj lib bin debug

.PHONY: all
all: $(TARGET) $(TARGET_DEBUG)

.PHONY: debug
debug: $(TARGET_DEBUG)

.PHONY: clean
clean:
	@echo CLEAN $(CLEAN_LIST)
	@rm -f $(CLEAN_LIST)

.PHONY: distclean
distclean:
	@echo CLEAN $(CLEAN_LIST)
	@rm -f $(DISTCLEAN_LIST)

5. 参考示例

下面是一个简易的链表逆序的算法实现,可以作为运行调试的例子:

#include <iostream>

using namespace std;

struct ListNode
{
    int value;
    ListNode *next;
};

void ReversePrint(ListNode *pHead) //递归实现逆序打印(不改变链表结构)
{
    if (pHead != NULL)
    {
        if (pHead->next != NULL)
            ReversePrint(pHead->next);
        cout << pHead->value << " ";
    }
}

ListNode *ReverseList1(ListNode *pHead) //头插法(改变链表结构)
{
    if (pHead == NULL)
        return NULL;
    ListNode *p = pHead->next;
    ListNode *newHead = pHead;
    while (p != NULL)
    {                          //将p结点移到链表最前方
        pHead->next = p->next; //头结点指向p的下一个结点
        p->next = newHead;     //p插入链表最前方
        newHead = p;           //链表新头结点更新为p
        p = pHead->next;       //处理下一个结点,该结点位于头结点后
    }
    return newHead;
}

ListNode *ReverseList2(ListNode *pHead) //依次改变指针方向(改变链表结构)
{
    ListNode *prev = NULL;
    ListNode *next = NULL;
    while (pHead != NULL)
    {
        next = pHead->next; //保存剩余链表
        pHead->next = prev; //断开剩余链表头结点pHead,指向pre
        prev = pHead;       //pre更新
        pHead = next;       //head更新
    }
    return prev;
}

int main() //主函数
{
    int n;
    cout << endl
         << "请输入链表元素个数: " << endl;
    cin >> n; //输入元素个数
    ListNode *head = NULL;
    ListNode *p = NULL;
    ListNode *q = NULL;
    cout << endl
         << "请依次输入链表元素: " << endl;
    for (int i = 0; i < n; i++) //分配内存,依次输入元素
    {
        q = new ListNode;
        cin >> q->value;
        if (head == NULL)
        {
            head = q;
            p = head;
        }
        else
        {
            p->next = q;
            p = p->next;
        }
    }
    if (head == NULL)
        return 0;
    p->next = NULL;
    //验证
    cout << "递归逆序打印: " << endl;
    ReversePrint(head);
    cout << endl
         << "头插法反转链表: " << endl;
    ListNode *reverseHead;
    reverseHead = ReverseList1(head);
    p = reverseHead;
    while (p != NULL)
    {
        cout << p->value << " ";
        p = p->next;
    }
    cout << endl
         << "改变指针方向反转链表(将链表再次反转): " << endl;
    p = ReverseList2(reverseHead); //改变指针方向反转链表
    while (p != NULL)
    {
        cout << p->value << " ";
        q = p;
        p = p->next;
        delete q; //释放内存
    }
    cout << endl;
    return 0;
}

6. Windows 环境配置

Windows环境下是非常不方便进行 GNU/C++ 编译的,但是极端情况下也是可以用的,记录一下 Mingw-w64 (GCC for Windows 64 & 32 bits) 环境的搭建和 VS Code 的相关配置,使用 Mingw-builds 进行安装,如果需要配套的命令行工具可以使用 Msys2 , Cygwin是运行于Windows平台的POSIX子系统编译出来的程序需要dll依赖,这里并不推荐使用。

Mingw-w64安装:
mingw

安装完成后使用 sysdm.cpl 修改环境变量
sysdm.cpl
然后将 %MINGW_HOME%\bin 附加到 Path 变量后面,这样就可以在系统环境下直接调用 GNU/GCC 工具。

在 VS Code 中打开工具窗口 (Ctrl+Shift+P) ,输入 C/CPP: Edit Configurations 来生成配置文件 c_cpp_properties.json 添加 MinGW-w64 的 include 路径:

        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}",
                "${env:MINGW_HOME}/x86_64-w64-mingw32/include",
                "${env:MINGW_HOME}/x86_64-w64-mingw32/include/c++",
                "${env:MINGW_HOME}/x86_64-w64-mingw32/include/c++/tr1",
                "${env:MINGW_HOME}/x86_64-w64-mingw32/include/c++/backward",
                "${env:MINGW_HOME}/x86_64-w64-mingw32/include/c++/x86_64-w64-mingw32",
                "${env:MINGW_HOME}/include"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE",
                "__GNUC__=5",
                "__cdecl=__attribute__((__cdecl__))"
            ],
            "intelliSenseMode": "msvc-x64",
            "browse": {
                "path": [
                    "${workspaceFolder}",
                    "${env:MINGW_HOME}/x86_64-w64-mingw32/include",
                    "${env:MINGW_HOME}/x86_64-w64-mingw32/include/c++",
                    "${env:MINGW_HOME}/x86_64-w64-mingw32/include/c++/tr1",
                    "${env:MINGW_HOME}/x86_64-w64-mingw32/include/c++/backward",
                    "${env:MINGW_HOME}/x86_64-w64-mingw32/include/c++/x86_64-w64-mingw32",
                    "${env:MINGW_HOME}/include"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            },
            "cStandard": "c11",
            "cppStandard": "c++17"
        }

其他的使用就和Linux一样了,如果MinGW64体验不够好可以使用 MSVC, 这里就不介绍了。

7. 备注

下面是 VS Code 中的 预定义变量(Predefined variables) :

  • ${workspaceRoot} 当前打开的文件夹的绝对路径+文件夹的名字
  • ${workspaceRootFolderName} 当前打开的文件夹的名字
  • ${file} 当前打开正在编辑的文件名,包括绝对路径,文件名,文件后缀名
  • ${relativeFile} 从当前打开的文件夹到当前打开的文件的路径
  • ${fileBasename} 当前打开的文件名+后缀名,不包括路径
  • ${fileBasenameNoExtension} 当前打开的文件的文件名,不包括路径和后缀名
  • ${fileDirname} 当前打开的文件所在的绝对路径,不包括文件名
  • ${fileExtname} 当前打开的文件的后缀名
  • ${cwd} 同 pwd , 当前绝对路径
  • ${lineNumber} 当前打开的文件,光标所在的行数

参考文档

  1. VS Code 配置 C/C++ 环境
  2. C++链表反转、链表逆序打印
  3. Visual Studio Code (vscode)编译C++
  4. Cygwin 和MinGW 的区别与联系
  5. Microsoft/vscode-cpptools/Documentation/LanguageServer/MinGW.md
  6. Visual Studio Code 配置C/C++环境
  7. Visual Studio Code Variables Reference
  8. what-is-the-difference-between-includepath-and-browsepath
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页