beginner1010's blog

By beginner1010, history, 4 months ago, In English,

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.

 
 
 
 
  • Vote: I like it
  • +147
  • Vote: I do not like it

»
4 months ago, # |
  Vote: I like it +3 Vote: I do not like it

Auto comment: topic has been updated by beginner1010 (previous revision, new revision, compare).

»
4 months ago, # |
  Vote: I like it +10 Vote: I do not like it

Not as cool, but I use simple

#define watch(x) cout << (#x) << " is " << (x) << endl

to debug single variables

»
4 months ago, # |
  Vote: I like it +15 Vote: I do not like it

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

»
4 months ago, # |
Rev. 3   Vote: I like it 0 Vote: I do not like it
it's better, isn't it?
  • »
    »
    4 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    can u please tell me how to handle this debug();

    • »
      »
      »
      4 months ago, # ^ |
      Rev. 2   Vote: I like it 0 Vote: I do not like it
      1. Compile with flag -DLOCAL
      2. Call debug() with some arguments, it will print argname = argvalue
  • »
    »
    5 weeks ago, # ^ |
    Rev. 2   Vote: I like it 0 Vote: I do not like it

    I don't like that it can't print vectors or function calls. See my comment for better debugging template

»
4 months ago, # |
  Vote: I like it +8 Vote: I do not like it

Auto comment: topic has been updated by beginner1010 (previous revision, new revision, compare).

»
4 months ago, # |
  Vote: I like it 0 Vote: I do not like it

cool

»
4 months ago, # |
  Vote: I like it 0 Vote: I do not like it

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).

  • »
    »
    4 months ago, # ^ |
      Vote: I like it +6 Vote: I do not like it

    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)

  • »
    »
    4 months ago, # ^ |
    Rev. 2   Vote: I like it +1 Vote: I do not like it

    I think the best way to do this is to define a custom operator<< for STL containers. The magic sauce here is weeding out std::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, and a is defined as std::vector<std::string>. This line prints something like this to stderr:

    [154873296, 386592714, 729641835, 863725149, 975314628, 412968357, 631457982, 598236471, 247189563]

    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 as print(b);

»
4 months ago, # |
  Vote: I like it 0 Vote: I do not like it

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!!

  • »
    »
    4 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    same problem with me...

    • »
      »
      »
      4 months ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      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

      • »
        »
        »
        »
        4 months ago, # ^ |
          Vote: I like it +3 Vote: I do not like it

        or you can simply use

        #ifndef ONLINE_JUDGE

        instead of

        #ifdef XOX

        • »
          »
          »
          »
          »
          4 months ago, # ^ |
          Rev. 2   Vote: I like it 0 Vote: I do not like it

          Add -DXOX into your compiler flags, so that you don't need to remove anything when you submit your code. :)

»
4 months ago, # |
Rev. 4   Vote: I like it +12 Vote: I do not like it

Here is a function for print any stl container that has begin() and end():

Spoiler

Example:

vector<int> vec{1,2,3,4,5,6};
cout << vec << endl;
set<int> s{3,4,5,6};
cout << s << endl;
//Output
//[1, 2, 3, 4, 5, 6]
//[3, 4, 5, 6]

Work for map too if you overload operator<< for pair

Spoiler
//
map<int,string> m = {
 {1, "awesome"},
 {2, "c++"}
};
cout << m << endl;
//[{1, awesome}, {2, c++}]
map<pair<int,int>,pair<bool,float>> m2 = {
 {{1, 2}, {true, 3.0}},
 {{3, 4}, {false, 9.f}}
};
cout << m2 << endl;
//[{{1, 2}, {1, 3}}, {{3, 4}, {0, 9}}]


  • »
    »
    4 months ago, # ^ |
    Rev. 2   Vote: I like it 0 Vote: I do not like it

    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

    Spoiler
»
4 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it
#ifdef XOX
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __LINE__, __VA_ARGS__)
#else
#define debug(...) 42
#endif

Here what is meant by

#define debug(...) 42 ???

Why we defined 42 as debug(...)?

  • »
    »
    4 months ago, # ^ |
    Rev. 2   Vote: I like it 0 Vote: I do not like it

    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)**

    int a = 10;
    debug(a);
    

    this will print 10 on std::err , but when you submit on cf XOX is not define so debug(a) replace with 42

    int a = 10;
    42;
    
  • »
    »
    4 months ago, # ^ |
      Vote: I like it +8 Vote: I do not like it

    Because 42 is the answer to Life, Universe, and everything, Duh!

»
4 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Hello,

When I do:

int test[10] = {0};
debug(test);

He sends me back:

test = 0x7fffed0acd20

How can I display all my board on the line instead of its address?

Thank you

  • »
    »
    4 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    you can't print this type of array becz size is unknown when it's passed through any function so always use vector

    code

    you have to compile it with LOCAl argument

»
4 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

To support STL containers and line number

code
output

just add -D LOCAL flag

  • »
    »
    4 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    I 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?

    • »
      »
      »
      4 months ago, # ^ |
      Rev. 2   Vote: I like it 0 Vote: I do not like 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.

»
6 weeks ago, # |
  Vote: I like it 0 Vote: I do not like it

how can I print the debug output to a file? currently it prints to terminal

»
5 weeks ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like 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

#define debug(x) cerr << "Line " << __LINE__ << ": " << #x << " = " << to_string(x) << endl
  • »
    »
    5 weeks ago, # ^ |
    Rev. 2   Vote: I like it 0 Vote: I do not like it

    I recommend using this debugging template

    Code

    You can debug function calls, variables, STL containers, almost anything.

    Make sure to add -DLOCAL to your compiler arguments. When you write

    edbg(a, b);
    

    where

    a = 5;
    b = "Codeforces";
    

    It will print

    [a]: [5]
    [b]: [Codeforces]
    

    But for a general debug

    dbg(a, b);
    

    it will print

    [a, b]: [5, Codeforces]
    
    • »
      »
      »
      5 weeks ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      This edbg macro is basically the same as the post. It dosen't work properly for something like this:

      *min_element(diff.begin() + 2, diff.end())
      

      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.

»
5 weeks ago, # |
  Vote: I like it 0 Vote: I do not like it

may anyone explain in simple word what is the debug code is and how to use the above code in program

thanks a lot in advance ...