Легко печатать подробный вывод отладочной информации? - PullRequest
3 голосов
/ 21 января 2009

Я в основном ищу способ автоматизировать ввод текста наподобие следующего:

cout << "a[" << x << "][" << y << "] =\t" << a[x][y] << endl;

Что-то вроде:

PRINTDBG(a[x][y]);

В идеале это также будет работать для

PRINTDBG(func(arg1, arg2));

и даже

PRINTDBG(if(condition) func(foo););

(который будет печатать, например, "if (false) func (5)").

Также приветствуются непортативные хаки:)

(нет, использование отладчика не то же самое, оно гораздо менее гибкое, и я нахожу это непонятным)

Ответы [ 5 ]

2 голосов
/ 21 января 2009

Это, как вы хотите, невозможно. Если у вас есть if (условие) func (foo); , данное макрокоманде, он может структурировать этот материал и вывести if (условие) func (foo); , но не с заменой фактических значений переменных. Помните, что препроцессор не знает о структуре этого кода.

Для отладки я бы использовал какой-нибудь безопасный для печати вариант printf, такой как boost.format или домашний напиток printf с boost.fusion , который значительно упростил бы задачу печати таких вещей:

dprintf("a[%][%] = %", (x, y, a[x][y]));
2 голосов
/ 21 января 2009

Это область, где вывод в стиле printf может быть более кратким:

cout << "a[" << x << "][" << y << "] =\t" << a[x][y] << endl;
printf("a[%d][%d] =\t%d\n", x, y, a[x][y]);

Конечно, это ограничивает работу только для типов, которые printf понимает, и все равно не отвечает на ваш вопрос.

У меня такое ощущение, что в методах разложения выражений в Boost может быть что-то ценное, но мне не хватает ниндзя-шаблона, чтобы определить, что именно.

Обновление : Следующее почти отвечает на ваш вопрос:

#define PRINTDBG(x) cout << #x << " =\t" << x << endl;

Однако, когда он используется как PRINTDBG(a[x][y]), он буквально печатает:

a[x][y] = 5

, который не дает фактических значений x и y.

0 голосов
/ 21 января 2009

Вы можете определить оператор «для пользовательских классов, поэтому вам нужно определить форматирование только один раз:

struct point3 {
      int x,y,z;
      point3(int a, int b, int c){x=a;y=b;z=c;}
};

std::ostream& operator << (std::ostream& os, const point3& f) {
      return os << "(" << f.x << "," << f.y << "," << f.z << ")";
}

point3 p(1,2,3);
std::cout << p; // prints "(1,2,3)"

это хорошо сочетается с перенаправлением cout или clog в файл (не помню, как работает std :: clog)

#include <iostream>
#include <fstream>

int main() {
      std::ofstream file("log.txt");
      std::streambuf *filebuf = file.rdbuf();
      std::cout.rdbuf(filebuf);

      std::cout << "This is written to the file";

      filestr.close();
      return 0;
}
0 голосов
/ 21 января 2009

В небольшом расширении, отличном от публикации Грега, я видел несколько хороших программ на Си, которые выглядят примерно так

#DEFINE DEBUG_MODE 1
//...
if( DEBUG_MODE)
  printf("methodX() says: y=%i, var1=%i", y, var1);

Однако у вас все еще есть тонна printf в вашей программе, но, по крайней мере, вы можете включать и выключать их все, когда захотите.

0 голосов
/ 21 января 2009

Обычно я использую простую, но настраиваемую функцию регистрации вместо макросов


Log(const char *format, ...)
{
    char buffer[MAX_BUFFER_SIZE];
    va_list args;

    //get arguements into a list
    va_start(args, format);

    //printf formated arguement into a string
    vsnprintf(buffer, sizeof(buffer), format, args);

    va_end(args);

    printf("%s", buffer);
  }

так что теперь вы можете сделать

<code>Log("a[%d][%d] =\t%d\n", x, y, a[x][y])
<code>Log("if(%s) func(%d) ;", (condition) ? "true" : "False", func(foo))

добавьте некоторый тип ведения журнала (например, LOG_SCREEN, LOG_FILE) в функцию Log (), и теперь вы можете контролировать, где он регистрируется в

добавить некоторый уровень входа в систему (например, WARN, CRIT) для управления отображением, цветом и т. Д.

Конечно, есть много, много библиотек, которые уже делают все эти вещи

надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...