调试输出工具

调试输出工具

一句话工具

debug(a, b, c) 把变量名和值一起输出,让你在本地调试时少写重复的 cerr << ...

适用场景

调试输出工具解决的是一个很小但很高频的问题:程序跑错时,我们通常需要知道某几个变量在某一行的真实值。

普通写法会变成:

cpp
        
1
cerr << "i = " << i << " j = " << j << " ans = " << ans << "\n";

变量一多,代码就又长又容易写错。这个模板把“变量名”和“变量值”绑定在一起输出:

cpp
        
1
debug(i, j, ans);

输出中会带上当前行号,适合快速定位是哪一次调试输出。

核心接口

  • debug(x):输出一个变量。
  • debug(a, b, c):按顺序输出多个变量。
  • debug_line:输出一条分隔线,适合把多轮调试信息隔开。

模板默认输出到 cerr,不会和正常答案的 cout 混在同一个缓冲逻辑里;但在线评测只看标准输出时,仍然建议提交前关闭调试输出。

使用步骤

  1. 把模板放在 main 前面。
  2. 在怀疑出错的位置写 debug(...)
  3. 本地样例调试完成后,删除调试语句,或者用宏开关统一屏蔽。

例如排查双指针时,可以在每次移动指针后输出状态:

cpp
        
1
debug(l, r, sum);

排查图论搜索时,可以在进入节点时输出:

cpp
        
1
debug(u, parent, depth[u]);

代码实现

模板文件位置:/code/utils/log.cpp

cpp
        
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h> using namespace std; #define debug_line cerr << "\n=================\n" #define debug(...) \ do { \ cerr << "LINE:" << __LINE__ << " "; \ string names = #__VA_ARGS__; \ replace(names.begin(), names.end(), ',', ' '); \ stringstream ss(names); \ istream_iterator<string> it(ss); \ debug_print(it, __VA_ARGS__); \ } while (false) void debug_print(istream_iterator<string>) {} template <typename T, typename... Args> void debug_print(istream_iterator<string> it, const T& value, const Args&... args) { cerr << *it << " = " << value << "\n"; debug_print(++it, args...); }

常见改法

提交前关闭调试

如果不想手动删除所有 debug(...),可以给模板加一个编译开关:

cpp
        
1
2
3
#ifdef ONLINE_JUDGE #define debug(...) #endif

本项目的通用竞赛模板里也提供了类似的 NO_DEBUG 开关。

输出容器

当前模板依赖 operator<<intlong longstring 这类类型可以直接输出;vector<int>pair<int,int> 默认不能直接输出。

如果你经常调试容器,可以额外给容器补输出重载:

cpp
        
1
2
3
4
5
6
7
8
9
template <typename T> ostream& operator<<(ostream& os, const vector<T>& a) { os << "["; for (int i = 0; i < (int)a.size(); ++i) { if (i) os << ", "; os << a[i]; } return os << "]"; }

控制输出位置

模板默认用 cerr。如果你的运行环境只方便看标准输出,也可以把 cerr 改成 cout;但这样更容易污染答案输出,提交前必须确认调试已经关闭。

注意事项

  • debug(a, b + c) 可以用;但包含逗号的复杂表达式不适合直接放进去,例如 debug(make_pair(x, y)) 的变量名解析会不准确。
  • 调试输出会影响运行速度,尤其是在循环内部大量输出时。
  • 调试宏只适合本地排错,不应该依赖它产生正式答案。
  • 如果题目要求输出格式严格,提交前要保证没有任何调试信息进入标准输出。

推荐用法

这类工具最好固定放进自己的个人模板。平时保留 debug(...) 接口,比赛时用开关控制是否启用,这样不用在不同题目之间反复复制粘贴调试写法。