Удобный и мощный 4-строчник для дебага (C++17 эдишн)

Revision ru14, by Sanitator, 2019-02-19 15:29:34

Традиционный дебаг

Наверное, каждый спортивный программист хотя бы раз выводил содержимое контейнера, массива или просто значение переменной во время дебага. В этот момент появляются такие вот уродливые конструкции:

    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 << ' ';
            }
        }
    }

О, господи, да еще и гарантированная проверка, что счетчик не выходит за пределы массива! 2D, 3D, какая разница, если это нелья записать кратко?! Да еще эти endlы вместо пустых ячеек.

Дебаг с f_dbg()

Мне надоело бесконечно набивать эти циклы, поэтому я написал несколько строчек, которые могут напечатать значения практически чего угодно, хранящего встроенные типы. Вывод сделан в стиле питона. Конечно, у этого кода есть некоторые ограничения, но в целом он мне нравится.

Вы можете найти его здесь. Он использует некоторые фичи c++17, поэтому выберите правильный компилятор.

Компактная версия сгенерирована из полной на сайте http://removelinebreaks.net/

Как работает форматированный вывод

Назовем массивом c-массив, вектор, дек, array. Тогда f_dbg() может вывести подмассив. Чтобы она сделала это, вы передаете ей по [две закрытые границы] для каждого измерения, причем можно опустить несколько последних границ. Если они слишком большие, f_dbg() уменьшает их, чтобы они были внутри подмассива. По умолчанию начальная и конечная граница для каждого измерения устанавливаются на начало и конец каждого измерения.

Если тип элементов в массиве тоже какой-то массив, f_dbg() вызывается рекурсивно от этого элемента, пока не достигнет элементарного типа — int, char, double и т.д. Это значение выводится, и все, собственно.

Другие структуры данных вроде map, set не имеют индексов, и поэтому выводятся полностью: от начала до конца. В map f_dbg() вызывается и от ключа, и от значения.

Пары выводятся так же: рекурсивно вызывается f_dbg() от первого элемента, потом от второго.

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

Сравните:

    // традиционная версия(изменена для похожести на 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);

традиционная версия выводит:

2 3 
4 


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

f_dbg() выводит:

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

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

Дебаг с n_dbg()

Вы когда-нибудь мечтали о том, чтобы выводить названия скольки угодно переменных и их значения без этих << "my_var" << my_var?

Взгляните на named debug

Можно использовать макрофункцию:

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

Она будет просто подставлять вместо только переменной ее имя, двоеточие, значение и запятую. Теперь можно написать функцию, которая будет вызывать f_dbg() от каждого подставленного аргумента. Назовем такую функцию n_dbg(). Нужно только писать _() вокруг каждого аргумента, который вы ей передаете.

Сравните:

    string a = "dfs"; pair<int, string> b = {123, "ksdf"};
    
    auto sum = [](auto l, auto r){return l + r;};
    
    cout << "a " << a << " | " << "b " << b.first << " " << b.second << " | " << "sum "  << sum(3,4) << endl;
    
    n_dbg(_(a), _(b), _(sum(3,4)));

традиционная версия выводит:

a dfs | b 123 ksdf | sum 7

n_dbg() выводит:

[a: dfs, b: [123,ksdf], sum(3,4): 7, ]

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

Надеюсь, этот код сохранит немного вашего бесценного времени во время контеста.

P.S. Если вы захотите адаптировать код к c++11/14, я не возражаю, если вы склонируете этот блог для (c++11/14 эдишн). Или вы можете предложить ваш код, и я добавлю его сюда, чтобы все версии были вместе.

UPD1: добавлен вывод unsigned int, long long, unsigned long long, long double, double

UPD2: добавлен вывод bitset

UPD3: Немного изменен интерфейс и описание интерфейса функций

UPD4: добавлена функция n_dbg()

UPD5: оказалось, что n_dbg() можно передавать функции

Tags tricks, debug, c++, dbg

History

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