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

Автор ilyaraz, 13 лет назад, По-русски

Все олимпиадники делятся на два лагеря: те, кто отлаживает в отладчике, и те, кто отлаживает отладочным выводом. Можно бесконечно спорить о том, какой метод удобнее, но факт остается фактом -- и таких, и таких людей полным-полно. Я отношусь ко второму лагерю: во многих ситуациях применение отладчика невозможно, поэтому хочется быть от него независимым. Более того, лично для меня отладочный вывод удобнее (я использую отладчик только для того, чтобы понять, где именно программа упала).

Так о чем же этот пост? Большинство минусов отладочного вывода на C++ происходит из того, что, к примеру, чтобы вывести вектор, нужно написать довольно много байтов кода. Это не слишком удобно. Чтобы бороться с подобными проблемами, я написал маленькую библиотеку, которая лежит здесь. Если вы напишете такой код: http://pastebin.com/9t87jmdp, то в результате в stderr выведется следующее:

file "test.cpp" line 14: a = {(0, {1, 2}), (1, {})}
file "test.cpp" line 18: aa = {'a', 'b'}
file "test.cpp" line 19: 2 * 2 = 4

Если же вы хотите убрать отладочный вывод, то нужно закомментировать строку #define DEBUG_OUTPUT в test.cpp. В первой версии выводятся следующие переменные:
  • которые можно вывести с помощью оператора <<;
  • у которых есть .begin() и .end() (коллекции, например);
  • std::pair.
Код в debug_output.h использует забавный хак C++, который называется SFINAE.

P.S. Код использует C++11 (поддержка которого есть, к примеру, в g++ 4.6 и Visual Studio 2010). Но, отключив отладочный вывод, можно компилировать код и более старыми компиляторами.

UPD В новой версии C++11 больше не нужен, также поправлен баг, который заметил Петросян.
  • Проголосовать: нравится
  • +73
  • Проголосовать: не нравится

»
13 лет назад, # |
  Проголосовать: нравится +13 Проголосовать: не нравится
Представляю команды, которые кроме шаблона в начале контеста вбивают и эту библиотеку перед началом, скажем, полуфинала :)

А вообще да, может оказаться довольно удобным на практике. Я помню участника с TopCoder (кажется, bladerunner), который перегружал оператор "запятая" для подобных целей :) Кажется в самом деле DEBUG (именно так, большими буквами) не очень удобен для скоростного набора, лучше использовать какой-то шорткат попроще.
  • »
    »
    13 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +16 Проголосовать: не нравится

    Ну, это теоретически можно использовать для всяких топкодеров, CF и прочих локальных контестов. К тому же, это можно использовать и для отладки промышленного кода.


    После того, как я наткнулся на макросы Arc, min и max в windows.h, я опасаюсь давать своим макросам короткие названия.
»
13 лет назад, # |
Rev. 3   Проголосовать: нравится +11 Проголосовать: не нравится

При отключенном дебаге твоя библиотечка сломает код такого плана:

if (что_то_случилось) DEBUG(a);
else ...

Лучше взять в круглые скобки

# define DEBUG(a) ({})

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

    ничего не сломает.

    я помню макрос

    #define for if (0) ; else

    для подавления идиотизма компилятора MS VS 6.0

    если пару раз подрят написать циклы (не вложенные):

    for (int i = 0; ...)

    for (int i = 0; ... )

    то во второй строке будет ошибка о том, что i уже объявлена.

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      В MS VS 7.0 круче было. Если написать
      for (int i=0;i<2;i++)
      а потом не вложенно
      int i = 0;
      assert(i == 0);
      будет assertion failed. Ну, или что-то с чем-то местами поменять.
    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Попробуй откомпилировать мой пример вместе с хедером Ильи, и ты поймешь о чём я
      • »
        »
        »
        »
        13 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        ну да, ты прав. просто я не мог предположить что при отключенном дебаге там такая лажа.

        вот это

        #define DEBUG(x)
        int main()
        {
         if (0) DEBUG(34); else ;
        return 0;
        }

        спокойно компилится

        Илье следует заменить

        #else
        #define DEBUG(x) {}
        #endif

        на

        #else
        #define DEBUG(x) 
        #endif

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Гы, помню ещё в "рекомендациях по оформлению исходников" какой-то конторы видел предложение вместо:

    {...}

    в дефайнах писать

    do {...} while(0)

    Ужас, ужас... %)
    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Это не ужас.
      Как раз для случая
      if (что_то_случилось) DEBUG(a);
      else

      Иначе приходится помнить, что точку с запятой ставить не надо.
»
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
upd ок, оно просто хочет с++ох
»
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Ловите небольшой аддон
»
13 лет назад, # |
Rev. 2   Проголосовать: нравится +8 Проголосовать: не нравится

Студия не поддерживает новый for, поэтому этой библиотекой смогут пользоваться только программирующие на g++.

Хотя исправить for не проблема :)

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Эм... Как раз студия в отличие от g++ поддерживает такого рода фичи c++11 безо всяких дополнительных опций компиляции (если конечно это не слишком старая студия).
    • »
      »
      »
      13 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +9 Проголосовать: не нравится

      Вообще-то нет - такой for она не поддерживает. Более того, поддержка нового стандарта в целом студией (даже 2011 developer preview) оставляет желать лучшего. Пруф.

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Хм, действительно... Какая студия оказывается ущербная.