Today, I was seeing tourist's submissions. He uses a very cool way to print the variables for the purpose of debugging. The function debug_out
lists all variable names, followed by their values. I found it very interesting and convenient.
However, when you would like to print a long list of variables, it might be hard to match variables and their corresponding values. I made a few changes, and I would like to share the code with you. Please note that you need to define XOX
(-D XOX
should do the job). Therefore, when you are submitting your code, you do not need to remove or comment out lines including debug
. Hope you'll find it useful.
#include <bits/stdc++.h>
using namespace std;
vector<string> vec_splitter(string s) {
s += ',';
vector<string> res;
while(!s.empty()) {
res.push_back(s.substr(0, s.find(',')));
s = s.substr(s.find(',') + 1);
}
return res;
}
void debug_out(
vector<string> __attribute__ ((unused)) args,
__attribute__ ((unused)) int idx,
__attribute__ ((unused)) int LINE_NUM) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, int LINE_NUM, Head H, Tail... T) {
if(idx > 0) cerr << ", "; else cerr << "Line(" << LINE_NUM << ") ";
stringstream ss; ss << H;
cerr << args[idx] << " = " << ss.str();
debug_out(args, idx + 1, LINE_NUM, T...);
}
#ifdef XOX
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __LINE__, __VA_ARGS__)
#else
#define debug(...) 42
#endif
int main() {
int x = -1, y = 10000;
double z = 0.2;
string s = "beginner1010";
long long b = 1LL << 60;
debug(x, y, z, s, b);
double aux = 1010.0;
string code = "code";
debug(code + "forces",-aux / 10 * 2.3);
return 0;
}
Results:
Line(34) x = -1, y = 10000, z = 0.2, s = beginner1010, b = 1152921504606846976
Line(39) code + "forces" = codeforces, -aux / 10 * 2.3 = -232.3
UPD 1: The code is further improved to handle the case when an operation is applied to variables in debug
. The line number is added, and spookywooky's suggestion is applied. Please see the examples. Thank you all for your suggestions.
Auto comment: topic has been updated by beginner1010 (previous revision, new revision, compare).
Thankyou beginner1010 for sharing this Cool Debugging trick with us.
Not as cool, but I use simple
#define watch(x) cout << (#x) << " is " << (x) << endl
to debug single variables
Amazing!
void debug_out(vector<string> __attribute__ ((unused)) args, __attribute__ ((unused)) int idx) { cerr << endl; }
to get rid of the compiler warnings caused by -Wunused-parameter
can u please tell me how to handle this debug();
But how to compile with flag -DLOCAL
these are compiler flags , eg
-Wall , -Wshadow
etcjust use
g++ -D LOCAL filenmae.cpp
Thanks a lot.I know a different way.But I added -DLOCAL as a new compiler flag.But I can't delete my reply.
I don't like that it can't print vectors or function calls. See my comment for better debugging template
Auto comment: topic has been updated by beginner1010 (previous revision, new revision, compare).
Can we do some modification in above template so that we can also print STl containers like
map, vector, set, multiset (also map<pair<int,pair<int,int>>, int> type things).
pretty sure you will have to use iterators there (so i dont think it will work by modifying these functions little bit)
maybe use something like this to determine whether its an STL container: https://github.com/cpp-libraries/is_stl_container_type_trait/blob/master/is_stl_container.hpp
then you have to decide if you have to iterate with pairs (for map/unordered_map) also some containers don't have iterators (like queue/deque/stack)
I think the best way to do this is to define a custom
operator<<
for STL containers. The magic sauce here is weeding outstd::string
, but this is relatively easy if you know C++ template metaprogramming.Take a look at this code: 76534814. Notice that I have
print(a);
in main, anda
is defined asstd::vector<std::string>
. This line prints something like this to stderr:It works for any typical STL container, for example you can have something weird like
std::unordered_map<std::pair<int, int>, std::vector<std::string>> b
and printing it is still as easy asprint(b);
This snippet is not printing anything on the console in my PC....No errors, no warnings although... What should I do??
Please help me out!!
same problem with me...
I got the solution
Just before the #ifdef statement just write down "#define XOX" (without quotes) Commenting this statement will stop printing debug output .
That's it....It works fine
or you can simply use
#ifndef ONLINE_JUDGE
instead of
#ifdef XOX
Add
-DXOX
into your compiler flags, so that you don't need to remove anything when you submit your code. :)Yeah some platform like codeforces uses the flag ONLINE_JUDGE while judging the solution but there are a lot of platform like atcoder that don't use the ONLINE_JUDGE flag.
https://atcoder.jp/contests/abc162/rules I understood it as being here, but isn't I?
Here is a function for print any stl container that has begin() and end():
Example:
Work for map too if you overload operator<< for pair
We can get rid of vec_splitter() and debug_out() (they won't work if one ARG of #_VA_ARGS__ contain ',')_
write less code and faster version by using a macro trick
Here what is meant by
Why we defined 42 as debug(...)?
because we dont want to print anything in std err while submitting code.** XOX define at local pc (your pc , we need to define this)**
this will print 10 on std::err , but when you submit on cf XOX is not define so debug(a) replace with 42
Wouldn't it cause any error while replacing debug with 42?
Nice !! (imagine this as, emoji of Laughing)
Because 42 is the answer to Life, Universe, and everything, Duh!
Hello,
When I do:
He sends me back:
How can I display all my board on the line instead of its address?
Thank you
you can't print this type of array becz size is unknown when it's passed through any function so always use
vector
you have to compile it with LOCAl argument
To support STL containers and line number
[x: 10] [y: 11] [v: [1, 2, 3]] [mp: [(12, 13)]] -->Line: 42
just add
-D LOCAL
flagI have put #define LOCAL in the code and run it. What I have got is: [x: 10] [y: 11] [v: [1, 2, 3]] [mp: [(12, 13)]] [~ -->Line: 48] ~~ (~ is replacement for some strange symbol that I could not paste into here) Any idea how to fix it?
It's from the backspace
\b
. I used it to make format the line number a little bit different. you can just remove them from line 34 and line 26.thanks
How to add -D LOCAL flag?
code.cpp
g++ -DLOCAL code.cpp && a.exe
Thanks a lot brother
Kavaliro, Thanks a lot for the great debugging template. Yours is the best debugging template I have come across. What can I do to print the line number in the beginning instead of end of the dbg output ?
Just swap arguments
how can I print the debug output to a file? currently it prints to terminal
Just redirect output to a file :/ (
a.exe > a.out
)thanks I got it
Unfortunately this doesn't work when you debug a function call with more than one argument because the commas trick the vec splitter. Guess I'll go back to my not so cool
I recommend using this debugging template
You can debug function calls, variables, STL containers, almost anything.
Make sure to add -DLOCAL to your compiler arguments. When you write
where
It will print
But for a general debug
it will print
This edbg macro is basically the same as the post. It dosen't work properly for something like this:
because the commas separating the arguments of the function mess up the parsing algorithm. I think Tourist's way (which is essentially the same as your dbg function) is sufficient for me.
Your code is not compile
Thanks a lot.But my problem is I couldn't add compiler flag that is fixed.
wdym. Add -DLOCAL to ur compilation flags.
I added it
Does it work?
Yes bro
I copy and paste your code but it doesn't print anything.
If you add the following line before the aforementioned block, It will work.
I couldn't add XOX as compiler flag
I guess you can replace
with this
Wow!Its work.Thanks a lot brother.I don't need to add any compiler flag with this.
Don't forget to use passing by reference (avoid unnecessary copying):
The length of
args
is not usually so large, but also there is no harm to pass the parameters by the references...It's mostly about
H
andT
variables.One stop to debug template and its usage:
https://cs-mshah.github.io/getting_started_with_cp/#debugging
I used something similar myself, except one day I was bored so I decided to add the functionality to print stuff in different colors lol. It's hardly the most useful feature but does help sometimes with large implementations
The output —
(Don't judge my code too hard, it's a big steaming pile of mess but I don't have to look at it so I never bother to fix it lol)
If you choose to use it, I recommend you turn word wrap off
Sweet.. You may let the implementation decide the color based on the type of the variable. One question: are the color codes OS agnostic?
Ohh, that's a good idea, I'll see if I can do that without too many lines of code.
The codes do work on both windows and Linux but the colors themselves change according to your terminal's theme. For example I use Monokai Pro with some tweaks I made myself, but in Default Dark vscode theme the ORANGE color is printed in blue