This is Google's cache of https://codeforces.com/blog/entry/65311. It is a snapshot of the page as it appeared on Feb 20, 2019 00:20:37 GMT. The current page could have changed in the meantime. Learn more.
Full versionText-only versionView source
Tip: To quickly find your search term on this page, press Ctrl+F or ⌘-F (Mac) and use the find bar.
Pretty and powerful 4-line code for debugging (C++17 edition) - Codeforces
By Sanitator, history, 3 days ago, translation, In English,

Debugging the traditional way

Virtually every competitive programmer sometimes needs to print the values from some container, or array, or just a variable during debugging. This is where appear those ugly nested loops which take several minutes to write:

    vector<int> a[4][6] = {{{2,3}, {4}}, {{6,2}, {4,5}}};

    for(int i = 0; i < size(a); ++i, cout << endl){
        for(int j = 0; j < size(a[i]); ++j, cout << endl){
            for(int k : a[i][j]){
                cout << k << ' ';
            }
        }
    }

OMG, and bound checking for simple output of an array of vectors? 2D, 3D, it doesn't matter anymore if we can't write it concisely. And those stupid endls for empty cells...

Debugging with f_dbg()

I was fed up with traditional this and wrote a simple several-liner for printing almost everything one might want. The output is in python style. It has some limitations, but generally I like it.

You can find it here. My code exploits C++17 features, so choose the appropriate compiler.

The compact version is created from extended by means of http://removelinebreaks.net/

How formatted debug works

Let me call c-array, vector, deque, array just arr. Then, basically, f_dbg() can output sub-arr. You just need to pass the name of arr and [two closed bounds] for each dimension, or omit several last bounds. If they are too large, f_dbg() reduces them so that they are inside the arr. By default the bounds are set on start and end of each dimension.

If type of element of arr is some other arr-type, f_dbg() is recursively called with this element as argument until the simplest types are reached. You know them: int, char, double, and so on. They are then neatly printed, and that's all.

Other data structures like maps, sets don't have any indices, that's why they are printed from begin to end. In maps, f_dbg()is called both from the key and the value.

Pairs are printed the same way — recursive f_dbg() from the first element and from the second.

/*-----------------------------------------------*/

Compare:

    // traditional way(modified for similarity with f_dbg())
    int x1 = 0;
    int x2 = size(a)-1;
    for(int i = x1; i <= x2; ++i, cout << endl){
        int y1 = 0;
        int y2 = size(a[i])-1;
        for(int j = y1; j <= y2; ++j, cout << endl){
            for(int k : a[i][j]){
                cout << k << ' ';
            }
        }
    }

    // f_dbg()
    f_dbg(a,0,1);

traditional version outputs:

2 3 
4 


6 2 
4 5 
/*...endls...*/

f_dbg() outputs:

[[[2,3],[4],[]]
 [[6,2],[4,5],[]]]

/*-----------------------------------------------*/

Debugging with n_dbg()

Ever dreamt of printing names of variables and their values the readable way without << "my_var" << my_var?

Look at named debug

We can make use of macro functions. Let's do this:

#define _(x) #x, ": ", x, ", "

It just substitutes the bare argument with its name, colon, value, and comma. We can now create a function n_dbg() that takes arbitrary number of arguments and calls f_dbg() with each. Then if you want to get more info about an argument in output, you put it into _(), if just its value, simply type name_of_argument comma ", " (to separate it from the next argument). By default after this block of output endl is printed.

Compare:

    string t = "dfs"; pair<int, string> u = {123, "ksdf"};

    auto v = [](int l, int r){return l + r;};

    cout << t << "| " << "u " << u.first << " " << u.second << "| " <<  "v " << v(3,4) << "| " << v(3,4) << endl;
    
    n_dbg(t, ", ", _(u), _(v(3,4)), v(3,4));

traditional version outputs:

dfs| u 123 ksdf| v 7| 7

n_dbg() outputs:

[dfs, u: [123,ksdf], v(3,4): 7, 7]

/*-----------------------------------------------*/

Hope this code saves your precious minutes during contests. Enjoy.

P.S. If you want to adapt this code to c++11 or 14, I don't mind if you clone this blog for (c++11/14 edition). Alternatively, you can suggest me your code to add to this post, so that all versions are together.

UPD1: I added into the n_dbg() section an example of the raw output of an argument, of output of a function

UPD2: In Wandbox I put the names of debug functions in the begin of the block of code for copying so that you don't forget them.

UPD3: const char* output added

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

»
3 days ago, # |
  Vote: I like it +53 Vote: I do not like it

I'd rather use my shitty debugging skills which I understand than using something cryptic like this.

  • »
    »
    3 days ago, # ^ |
    Rev. 3   Vote: I like it +20 Vote: I do not like it

    true , lol but still we should appreciate the poster for trying to help community.

  • »
    »
    3 days ago, # ^ |
    Rev. 2   Vote: I like it +21 Vote: I do not like it

    Well, I just wanted to share my shitty debugging skills

»
2 days ago, # |
  Vote: I like it +149 Vote: I do not like it

One of your "four lines" has more than 2000 characters...

  • »
    »
    35 hours ago, # ^ |
      Vote: I like it +16 Vote: I do not like it

    I would also like to thank MikeMirzayanov for the great Codeforces Custom invocation which doesn't have automatic line breaking

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

    It's my inline library. Haven't you ever wanted combinatorics inline library, with P, C, A, ready modular multiplication, division, addition and binpow working always properly and occupying only one line? You all may consider it a challenge

»
2 days ago, # |
  Vote: I like it +8 Vote: I do not like it

While your function seems to work, why did you obfuscate everything in a single line? Good luck changing the function in case you have a bug or want to add something new to it...

  • »
    »
    2 days ago, # ^ |
    Rev. 6   Vote: I like it +13 Vote: I do not like it

    Because I provided extended code in the post. And it's easier to copy-paste 4 lines of code, than 42

»
2 days ago, # |
  Vote: I like it +33 Vote: I do not like it

Every time I see the things people use to debug in C++ (how did this ever pass review I wonder?), I'm glad I switched to D quite a while ago.

example

Perhaps in 20 years, the C++ committee will agree on a feasible means of debug output to have in the standard library. But life, or ICPC eligibility, or whatever other contests, they are here and now.

  • »
    »
    11 hours ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Codeforces society could have created this new shit a long ago instead of waiting for academics to adopt std::dbg

    Anyway, now I feel C++ is almighty

»
40 hours ago, # |
Rev. 2   Vote: I like it +9 Vote: I do not like it

You are gonna save a lot of time of guys like us, in the upcoming journey of CP.

Thanks a lot.

»
31 hour(s) ago, # |
  Vote: I like it +17 Vote: I do not like it
let x = vec![vec![1, 2, 3], vec![4, 5]];
println!("{:?}", x);

laughs in rust