Традиционный дебаг
Наверное, каждый спортивный программист хотя бы раз выводил в консоль содержимое контейнера, массива или просто значение переменной во время дебага. В этот момент появляются такие вот уродливые конструкции:
vector<int> a[4][6] = {{{2,3}, {4}}, {{6,2}, {4,5}}};
for(int i = 1; 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ы вместо пустых ячеек...
Дебаг с dbg()
Мне надоело бесконечно набивать эти циклы, поэтому я написал несколько строчек, которые могут напечатать значения практически чего угодно, хранящего встроенные типы. Вывод сделан в стиле питона. Конечно, у этого кода есть некоторые ограничения, но в целом он мне нравится. В большой степени он основан на этой посылке tourist.
Вы можете найти мой код здесь.
Компактная версия сгенерирована из развернутой на сайте http://removelinebreaks.net/
Как работает dbg()
Допустим, у нас есть вложенные друг в друга контейнеры(vector, string, bitset, set, map
) или массивы, которые мы можем для простоты рассматривать как просто многомерный массив со специфическими измерениями. dbg()
может аккуратно вывести название и границы подмассива такого массива, а потом и сам подмассив.
Например:
string g[2][2] = {{"ghdgh", "5445w"}, {"fghd", "sd3535f"}};
dbg(g,0,1,0,1,0,1);
// вывод:
[g,0,1,0,1,0,1]:
[["gh","54"],
["fg","sd"]]
Чтобы она сделала это, вы передаете ей по [две закрытые границы] для каждого измерения, причем можно опустить несколько последних границ. Если они слишком большие, dbg()
уменьшает их, чтобы они были внутри массива. По умолчанию начальная и конечная граница для каждого измерения устанавливаются на начало и конец каждого измерения.
ВНИМАНИЕ!
++Если вы передаете границы [l, r]
в измерение, которое map
или set
, вывод начинается с l-ного по возрастанию ключей элемента и заканчивается r-ным или последним(если граница r
слишком большая) элементом контейнера.
++dbg()
работает с c-массивами, чьи размеры измерений константны и известны на этапе компиляции.
++Если вы устанавливаете неправильные границы, вместо содержимого контейнера печатается пустая строка. /*-----------------------------------------------*/
Допустим, нужно посмотреть элементы в контейнере с 1го по 2ой.
map<vector<int>, vector<string>> a = {{{3,4},{"sauron"}}, {{1,2},{"gandalf", "the", "gray"}}, {{5},{"frodo","bilbo"}}};
// традиционная версия
auto l = begin(a), r = begin(a);
advance(l,1), advance(r, min(int(a.size()), 4));
for(; l != r; ++l){
cout << "{"; for(auto &ff : (*l).first) cout << ff << ","; cout << "}";
cout << "{"; for(auto &ff : (*l).second) cout << ff << ","; cout << "}\n\n";
} cout << "\n";
// вывод:
{3,4,}{sauron,}
{5,}{frodo,bilbo,}
// dbg():
dbg(a,1,2);
// вывод:
[a,1,2]:
[([3, 4], ["sauron"]), ([5], ["frodo", "bilbo"])]
Допустим, нужно вывести несколько переменных
int t = 5; char u = 'R';
pair<pair<double, unsigned int>, pair<int, string>> v = {{234.34534, 42}, {133, "IOI"}};
// традиционная версия:
#define fi first
#define se second
cout << t << " | " << u << " | " << "{ { " << v.fi.fi << "," << v.fi.se << " }{ " << v.se.fi << "," << v.se.se << " }\n";
// вывод:
5 | R | { { 234.345,42 }{ 133,IOI }
// dbg
dbg(t), dbg(u), dbg(v);
// вывод
[t]: 5
[u]: R
[v]: ((234.345340,42),(133,"IOI"))
/*-----------------------------------------------*/
Надеюсь, этот код сохранит немного вашего бесценного времени на контестах.
UPD: исправлен грубый баг с выводом bitset