Блог пользователя Sanitator

Автор Sanitator, история, 6 лет назад, По-русски

Хотели когда-нибудь посмотреть в консоли на переменные, которые вы используете? Встречайте пару дебаг-функций!

dbg()

DeBuG

Допустим, у вас есть вложенные друг в друга контейнеры(vector, string, bitset, set, map) или массивы, которые вы будете для простоты рассматривать как многомерный массив со специфическими измерениями. dbg() может аккуратно вывести название и границы подмассива такого массива, а потом и значения из этого подмассива с автоматической проверкой границ.

Например:

    int j[2][2][3] = {{{4,5,6},{10,11,12}}, {{1,2,3}, {7,8,9}}};
    dbg(j);
    dbg(j, 0,0, 0,1, 0,1);
    
    вывод: 
    [[[4, 5, 6],
      [10, 11, 12]],
     [[1, 2, 3],
      [7, 8, 9]]]
      
    [[[4, 5],
      [10, 11]]]


Другой пример:

Вы передаете функции по [две закрытые границы] для каждого измерения, причем можно опустить несколько последних границ. Если они слишком большие, dbg() уменьшает их. По умолчанию начальная и конечная граница для каждого измерения устанавливаются на начало и конец каждого измерения.

+Если вы передаете границы [l, r] в измерение, которое map или set, вывод начинается с l-ного по возрастанию ключей элемента и заканчивается r-ным или последним(если граница r слишком большая) элементом контейнера.

+dbg() работает с c-массивами, чьи размеры измерений константны и известны на этапе компиляции.

первый пример
второй пример


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

dbgm()

DeBuG Multiple

Вы можете вывести названия нескольких переменных, а потом их значения:

    string s = {"codeforces"};
    int t = 5; char u = 'R';
    pair<pair<double, unsigned int>, pair<int, string>> v = {{234.34534, 42}, {133, "IOI"}};

    dbgm(s,t,u,v);
    
    вывод:
        
    [s,t,u,v]: "codeforces" | 5 | R | ((234.345340, 42), (133, "IOI")) |

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


Здесь мой код. Он в значительной мере вдохновлен этой посылкой by tourist.

Компактная версия получена из extended при помощи http://removelinebreaks.net/.


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

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

Спасибо за этот пост и за это предложение HosseinYousefi

Полную версию dbg-библиотеки вы можете найти здесь. Код для вывода кортежей взят отсюда.

UPD1: добавлена ссылка на всю библиотеку с тестами
UPD2: добавлен вывод кортежей(tuple)

  • Проголосовать: нравится
  • +39
  • Проголосовать: не нравится

»
6 лет назад, # |
  Проголосовать: нравится +66 Проголосовать: не нравится

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

»
6 лет назад, # |
  Проголосовать: нравится +157 Проголосовать: не нравится

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

»
6 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

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

»
6 лет назад, # |
  Проголосовать: нравится +33 Проголосовать: не нравится

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.

  • »
    »
    6 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится -16 Проголосовать: не нравится

    Moses said

  • »
    »
    6 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +8 Проголосовать: не нравится

    While I agree with the sentiment that C++ is changing too slowly in some areas where it should be changing faster, code you linked can be trivially written to support any number of args without copypaste

    • »
      »
      »
      6 лет назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится

      You are right, the strange addition to testlib.h could perhaps be rewritten as a recursive template to accept any number of arguments. And it will be cleaner and shorter. And it may look trivial once it's done.

      However, the mere existence of this commit shows that doing it "right" still requires some effort: learning a bit more of C++ features and/or making sure the result compiles on a bunch of compiler versions.

      Alright, there's no point I'm trying to make here, just an observation.

»
6 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

А почему Вы просто не перегружаете ostream& operator<<(const T& t)?
В результате остаётся ((cout << args), ...);, forward-declaration операторов вывода для всех желаемых типов и, собственно, сами перегруженные операторы, реализацию которых можно не обфусцировать и запихать после main.
Если не заморачиваться как я (47750843), чтобы всё выводилось красиво без лишних пробелов, можно уложиться едва ли не в реальные четыре строчки.

»
6 лет назад, # |
Rev. 2   Проголосовать: нравится +9 Проголосовать: не нравится

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

Thanks a lot.

»
6 лет назад, # |
  Проголосовать: нравится +25 Проголосовать: не нравится
let x = vec![vec![1, 2, 3], vec![4, 5]];
println!("{:?}", x);

laughs in rust

»
6 лет назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

That code is heavily obfuscated

»
6 лет назад, # |
Rev. 6   Проголосовать: нравится -34 Проголосовать: не нравится

I left my team

»
6 лет назад, # |
  Проголосовать: нравится +14 Проголосовать: не нравится

Anyway, you will never have this in a formal competition.

»
6 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

.

»
6 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

Sanitator, Its very helpful. I came across a bug, hope you fix it soon.

code
output
  • »
    »
    6 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится +5 Проголосовать: не нравится

    though it has some limitations

    Frankly speaking, currently I can't come up with idea how to not manually pass the sizes of dimensions of a variable sized array to dbg(), so the only thing I could suggest is to set constant sizes of dimensions of arrays at compile time. Any ideas without specific functions for 2D, 3D... arrays?

    first option
    first option
»
6 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

I wonder where were LanceTheDragonTrainer

»
6 лет назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится

I got notified of this post because you tagged me in it today.

Since it's not practical to actually type this code, we should have it somewhere in our template and use it in online contests like codeforces.

So why not using a complete header file like PrettyPrint?

Put it in your directory and then add couple of lines in your code, something like:

#if !defined(ONLINE_JUDGE)
#include "prettyprint.hpp"
#endif
»
5 лет назад, # |
Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

Note: GDB has built-in pretty-printing of data structures. So if you know how to use GDB it would be much easier.

Using GDB also have the advantage of being able to print user-defined struct without defining operator<< for them.

It's recommended to check the environment before the real contest day, because it's possible that you need to explicitly turn them on to use them, or there are multiple versions of GDB installed and not all of them have the feature. (See for example https://stackoverflow.com/questions/4985414/how-to-enable-gdb-pretty-printing-for-c-stl-objects-in-eclipse-cdt . However if gdb_printers can't be found in the machine then you're out of luck)

»
5 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

C++ macro debug support color, line number, print pair, stl container...

  int n = 5;
  vector<int> v = {1,2,3,4};
  pair<int,string> p = {1, "codeforces"};
  debug(n, v, p);

For linux, windows 10 enable virtual terminal processing

Spoiler