Pretty and powerful 4-line code for debugging (C++17 edition)

Правка en22, от Sanitator, 2019-02-20 03:06:00

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

Теги tricks, debug, c++, dbg

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
en47 Английский Sanitator 2019-04-24 07:31:49 76
ru35 Русский Sanitator 2019-04-24 07:28:00 58
ru34 Русский Sanitator 2019-04-24 07:18:39 82
en46 Английский Sanitator 2019-04-23 19:51:03 576
ru33 Русский Sanitator 2019-04-23 19:46:43 38
ru32 Русский Sanitator 2019-04-23 19:45:30 38
ru31 Русский Sanitator 2019-04-23 19:43:47 607 Мелкая правка: ' с тестами\n**UPD2**' -> ' с тестами<br>\n**UPD2**'
en45 Английский Sanitator 2019-03-26 07:30:53 100
ru30 Русский Sanitator 2019-03-26 07:29:17 143
ru29 Русский Sanitator 2019-03-25 20:54:41 80
en44 Английский Sanitator 2019-03-25 20:53:58 79
en43 Английский Sanitator 2019-03-25 20:51:05 28
ru28 Русский Sanitator 2019-03-25 20:50:48 28 Мелкая правка: '/permlink/pXG09igiUEuyljHW). Он в зн' -> '/permlink/LMm2u1XmJcp929A1). Он в зн'
ru27 Русский Sanitator 2019-03-25 14:07:10 108
en42 Английский Sanitator 2019-03-25 14:05:28 77
ru26 Русский Sanitator 2019-03-25 11:56:21 395 Мелкая правка: 'ler>\n\nСпсибо за [э' -> 'ler>\n\nСпасибо за [э'
en41 Английский Sanitator 2019-03-25 11:53:18 382 Tiny change: '">\n~~~~~ void dbgs(' -> '">\n~~~~~ \nvoid dbgs('
ru25 Русский Sanitator 2019-03-25 11:34:02 14
ru24 Русский Sanitator 2019-03-25 11:33:25 7824 Мелкая правка: ' границ.\n \n~~~~~\n ' -> ' границ.\n\nНапример:\n\n~~~~~\n '
en40 Английский Sanitator 2019-03-25 11:22:03 2 Tiny change: 'e? Meet three helper f' -> 'e? Meet these helper f'
en39 Английский Sanitator 2019-03-25 11:20:15 34 (published)
en38 Английский Sanitator 2019-03-25 10:31:59 556 Tiny change: '-----*/`\n\n[Here's ' -> '-----*/`\n<br>\n[Here's '
en37 Английский Sanitator 2019-03-25 09:39:55 1
en36 Английский Sanitator 2019-03-25 09:39:31 2667 Tiny change: '---\n**D**e**B**u**G**\n\nS' -> '---\n**D** e **B** u **G**\n\nS'
en35 Английский Sanitator 2019-03-25 08:35:39 998
en34 Английский Sanitator 2019-03-25 07:07:59 690 (saved to drafts)
en33 Английский Sanitator 2019-03-09 11:24:19 65
ru23 Русский Sanitator 2019-03-09 11:22:17 84
en32 Английский Sanitator 2019-02-23 11:30:12 2
ru22 Русский Sanitator 2019-02-23 11:30:01 78
en31 Английский Sanitator 2019-02-23 11:28:48 2 Tiny change: 'n**UPD**: dbgs() added, en' -> 'n**UPD**: `dbgs()` added, en'
en30 Английский Sanitator 2019-02-23 11:28:13 59
en29 Английский Sanitator 2019-02-23 09:33:05 72
ru21 Русский Sanitator 2019-02-22 21:08:03 613
en28 Английский Sanitator 2019-02-22 20:54:23 17 Tiny change: 'sions are known' -> 'sions are constant and are known'
en27 Английский Sanitator 2019-02-22 20:51:52 10 Tiny change: 'ays whose dimension' -> 'ays whose sizes of dimension' (published)
en26 Английский Sanitator 2019-02-22 20:48:04 486 (saved to drafts)
en25 Английский Sanitator 2019-02-22 15:26:18 4
ru20 Русский Sanitator 2019-02-22 14:25:56 0 (опубликовано)
en24 Английский Sanitator 2019-02-22 14:25:45 3422 Tiny change: 'Hope this code saves you' -> 'Hope this function saves you' (published)
ru19 Русский Sanitator 2019-02-22 13:19:21 468 Мелкая правка: 'рована из полной на сайт' -> 'рована из развернутой на сайт'
ru18 Русский Sanitator 2019-02-21 21:00:57 26 Мелкая правка: '/permlink/IZ7rE5yhOTON3Q8f).\n\nКомп' -> '/permlink/ZuU99yZRY9fB852G).\n\nКомп'
en23 Английский Sanitator 2019-02-21 21:00:22 417 (saved to drafts)
ru17 Русский Sanitator 2019-02-21 20:48:44 297
ru16 Русский Sanitator 2019-02-21 19:48:46 3666 (сохранено в черновиках)
en22 Английский Sanitator 2019-02-20 03:06:00 763
ru15 Русский Sanitator 2019-02-20 02:48:59 1026 (опубликовано)
ru14 Русский Sanitator 2019-02-19 15:29:34 159 (сохранено в черновиках)
en21 Английский Sanitator 2019-02-19 11:38:06 21
ru13 Русский Sanitator 2019-02-19 11:37:04 6 Мелкая правка: 'есконечно писать эти ци' -> 'есконечно набивать эти ци'
ru12 Русский Sanitator 2019-02-19 11:34:06 100
en20 Английский Sanitator 2019-02-19 11:30:00 27
ru11 Русский Sanitator 2019-02-19 11:29:45 1417 Мелкая правка: '\n\n\n\n\nDebugging with `n_dbg()`' -> '\n\n\n\n\nДебаг с `n_dbg()`'
en19 Английский Sanitator 2019-02-19 11:11:58 50 (published)
en18 Английский Sanitator 2019-02-19 10:56:50 1015 Tiny change: '~~~~\n\n\n`/*-' -> '~~~~\n\n\n\n`/*-' (saved to drafts)
ru10 Русский Sanitator 2019-02-18 11:03:17 3 Мелкая правка: ' я сделал четырехстрочни' -> ' я сделал трехстрочни'
ru9 Русский Sanitator 2019-02-18 10:58:49 2
ru8 Русский Sanitator 2019-02-18 10:58:21 1092 (опубликовано)
en17 Английский Sanitator 2019-02-18 10:40:54 63
en16 Английский Sanitator 2019-02-18 10:37:16 4
en15 Английский Sanitator 2019-02-18 10:36:09 6 Tiny change: 'compiler. 3-line ve' -> 'compiler. \nThe 3-line ve'
en14 Английский Sanitator 2019-02-18 10:34:08 2
en13 Английский Sanitator 2019-02-18 09:49:25 1303 Tiny change: '~~\n\n\n\nf_dbg() output\n\' -> '~~\n\n\n\n`f_dbg()` output\n\'
ru7 Русский Sanitator 2019-02-18 08:08:49 316 (сохранено в черновиках)
en12 Английский Sanitator 2019-02-17 19:19:24 89
ru6 Русский Sanitator 2019-02-17 19:18:38 144
en11 Английский Sanitator 2019-02-17 19:15:47 56
en10 Английский Sanitator 2019-02-17 18:07:17 4
en9 Английский Sanitator 2019-02-17 17:54:08 2 Tiny change: '\noutput: s: `Hello worl' -> '\noutput: `s: Hello worl'
en8 Английский Sanitator 2019-02-17 17:52:14 5 Tiny change: '\nDebugging ' -> 'Debugging ' (published)
en7 Английский Sanitator 2019-02-17 17:50:17 278 (saved to drafts)
ru5 Русский Sanitator 2019-02-17 17:32:03 1622
en6 Английский Sanitator 2019-02-17 16:55:03 3 Tiny change: 'n#### How my formatted' -> 'n#### How formatted'
en5 Английский Sanitator 2019-02-17 16:52:30 1 Tiny change: 're reached You know ' -> 're reached. You know '
en4 Английский Sanitator 2019-02-17 16:50:38 1982 Tiny change: 'ly. \n\n\n----------------------\nDebuggin' -> 'ly. \n\n\nDebuggin'
ru4 Русский Sanitator 2019-02-17 14:06:48 3 Мелкая правка: 'IhQ5iUeQ).\nP.P.S. Е' -> 'IhQ5iUeQ). \n\nP.P.S. Е'
en3 Английский Sanitator 2019-02-17 14:04:51 0 (published)
ru3 Русский Sanitator 2019-02-17 14:04:21 0 (опубликовано)
en2 Английский Sanitator 2019-02-17 14:03:49 0 (saved to drafts)
ru2 Русский Sanitator 2019-02-17 14:02:12 1722 (сохранено в черновиках)
en1 Английский Sanitator 2019-02-17 13:45:05 1502 Initial revision for English translation
ru1 Русский Sanitator 2019-02-17 12:22:11 1502 Первая редакция (опубликовано)