🗓️ 2024-03-14 🏷️ #leetcode

leetcode 调试

方法 2

代码拷贝到本地,用 ide/gdb 调试。 比如使用 vim + floaterm + cgdb,效果见后图

对于此法,提供一个 header-only 的头文件 📜 《lc.h》 ,只需要引用此头文件,然后将 Class Solution 复制到本地,加上 main 函数即可运行

功能简介

效果图

另外,推荐使用 vim + floaterm + cgdb 的方式,配合此头文件对 leetcode 代码进行调试,喜欢的点是比较轻量,随时随地能调一下子。效果如下

方法 1

在 leetcode 代码头上定义测试宏,使用 print 大法来调试。

这里我把代码用 vscode 的 join line 合并成一行了,不然有些喧宾夺主。记得提交的时候把 DEBUG 宏关闭就好。格式化后的代码见后文

#define DEBUG 1
#if DEBUG
#include <iostream>
#include <numeric>
#include <string>
#include <type_traits>
template <typename T> struct ListType { template <typename Ptr> static auto test(Ptr ptr) -> decltype(ptr->val, ptr->next, std::true_type{}); template <typename Ptr> static std::false_type test(...); static constexpr bool value = decltype(test<T>(nullptr))::value; }; template <typename T, typename = void> struct Container : std::false_type {}; template <typename T> struct Container<T, std::void_t<typename T::value_type>> : std::true_type {}; const std::string sep = ","; template <typename T> std::string skToString(T c) { if constexpr (ListType<T>::value) { std::string ret = "["; auto p = c; while (p != nullptr && p->next != nullptr) { ret = ret + skToString(p->val) + sep; p = p->next; } if (p != nullptr) { ret += skToString(p->val); } ret += "]"; return ret; } else if constexpr (Container<T>::value && !std::is_convertible_v<T, std::string>) { if (c.empty()) { return "[]"; } return "[" + std::accumulate(std::next(c.begin()), c.end(), skToString(*(c.begin())), [](std::string a, auto b) { return a + sep + skToString(b); }) + "]"; } else if constexpr (std::is_arithmetic_v<T>) { return std::to_string(c); } else if constexpr (std::is_convertible_v<T, std::string>) { return c; } else { return "{" + skToString(c.first) + sep + skToString(c.second) + "}"; } } template <typename... Args> std::string skFmt(std::string_view format, Args... args) { std::string fmtStr(format); return ((fmtStr.replace(fmtStr.find("{}"), 2, skToString(args))), ...); } template <typename... PairTypes> void dumpWithName(PairTypes... args) { ((std::cout << "【" << skToString(std::get<0>(args)) << "】:" << skToString(std::get<1>(args)) << " "), ...); }
#define TO_PAIR(x) std::make_pair(#x, x)
#define DUMP1(x) dumpWithName(TO_PAIR(x))
#define DUMP2(x, ...) dumpWithName(TO_PAIR(x)), DUMP1(__VA_ARGS__)
#define DUMP3(x, ...) dumpWithName(TO_PAIR(x)), DUMP2(__VA_ARGS__)
#define DUMP4(x, ...) dumpWithName(TO_PAIR(x)), DUMP3(__VA_ARGS__)
#define DUMP5(x, ...) dumpWithName(TO_PAIR(x)), DUMP4(__VA_ARGS__)
#define DUMP6(x, ...) dumpWithName(TO_PAIR(x)), DUMP5(__VA_ARGS__)
#define DUMP7(x, ...) dumpWithName(TO_PAIR(x)), DUMP6(__VA_ARGS__)
#define DUMP8(x, ...) dumpWithName(TO_PAIR(x)), DUMP7(__VA_ARGS__)
#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, NAME, ...) NAME
#define OUTV(...) std::cout << skFmt(__VA_ARGS__) << std::endl;
#define DUMP(...) do{GET_MACRO(__VA_ARGS__, DUMP8, DUMP7, DUMP6, DUMP5, DUMP4, DUMP3,DUMP2, DUMP1)(__VA_ARGS__);std::cout << "\n";}while(0)
#else
#define OUTV(...)
#define DUMP(...)
#endif

功能简介

效果图

进行了一波小更新,DUMP 可以将传入的变量(最多 8 个)按照【name】: value 的格式打印出来,省去了写 format 字串的麻烦,更方便一些。

(LOGF就是现在的宏OUTV,下面的图是更新前的老名字。这里只是为了展示可以支持哪些类型)

附:

格式化后的代码,供诸君参考

#define DEBUG 1
#if DEBUG
#include <iostream>
#include <numeric>
#include <string>
#include <type_traits>
template <typename T>
struct ListType {
    template <typename Ptr>
    static auto test(Ptr ptr) -> decltype(ptr->val, ptr->next,
                                          std::true_type{});
    template <typename Ptr>
    static std::false_type test(...);
    static constexpr bool value = decltype(test<T>(nullptr))::value;
};
template <typename T, typename = void>
struct Container : std::false_type {};
template <typename T>
struct Container<T, std::void_t<typename T::value_type>> : std::true_type {};
const std::string sep = ",";
template <typename T>
std::string skToString(T c) {
    if constexpr (ListType<T>::value) {
        std::string ret = "[";
        auto p = c;
        while (p != nullptr && p->next != nullptr) {
            ret = ret + skToString(p->val) + sep;
            p = p->next;
        }
        if (p != nullptr) {
            ret += skToString(p->val);
        }
        ret += "]";
        return ret;
    } else if constexpr (Container<T>::value &&
                         !std::is_convertible_v<T, std::string>) {
        if (c.empty()) {
            return "[]";
        }
        return "[" +
               std::accumulate(std::next(c.begin()), c.end(),
                               skToString(*(c.begin())),
                               [](std::string a, auto b) {
                                   return a + sep + skToString(b);
                               }) +
               "]";
    } else if constexpr (std::is_arithmetic_v<T>) {
        return std::to_string(c);
    } else if constexpr (std::is_convertible_v<T, std::string>) {
        return c;
    } else {
        return "{" + skToString(c.first) + sep + skToString(c.second) + "}";
    }
}
template <typename... Args>
std::string skFmt(std::string_view format, Args... args) {
    std::string fmtStr(format);
    return ((fmtStr.replace(fmtStr.find("{}"), 2, skToString(args))), ...);
}
template <typename... PairTypes>
void dumpWithName(PairTypes... args) {
    ((std::cout << "【" << skToString(std::get<0>(args))
                << "】:" << skToString(std::get<1>(args)) << " "),
     ...);
}
#define TO_PAIR(x) std::make_pair(#x, x)
#define DUMP1(x) dumpWithName(TO_PAIR(x))
#define DUMP2(x, ...) dumpWithName(TO_PAIR(x)), DUMP1(__VA_ARGS__)
#define DUMP3(x, ...) dumpWithName(TO_PAIR(x)), DUMP2(__VA_ARGS__)
#define DUMP4(x, ...) dumpWithName(TO_PAIR(x)), DUMP3(__VA_ARGS__)
#define DUMP5(x, ...) dumpWithName(TO_PAIR(x)), DUMP4(__VA_ARGS__)
#define DUMP6(x, ...) dumpWithName(TO_PAIR(x)), DUMP5(__VA_ARGS__)
#define DUMP7(x, ...) dumpWithName(TO_PAIR(x)), DUMP6(__VA_ARGS__)
#define DUMP8(x, ...) dumpWithName(TO_PAIR(x)), DUMP7(__VA_ARGS__)
#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, NAME, ...) NAME
#define OUTV(...) std::cout << skFmt(__VA_ARGS__) << std::endl;
#define DUMP(...)                                                        \
    do {                                                                 \
        GET_MACRO(__VA_ARGS__, DUMP8, DUMP7, DUMP6, DUMP5, DUMP4, DUMP3, \
                  DUMP2, DUMP1)                                          \
        (__VA_ARGS__);                                                   \
        std::cout << "\n";                                               \
    } while (0)
#else
#define OUTV(...)
#define DUMP(...)
#endif

Comment