3

I'm basically looking for a way to automate typing stuff like the following:

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

Something like:

PRINTDBG(a[x][y]);

Ideally this would also work for

PRINTDBG(func(arg1, arg2));

and even

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

(which would print e.g. "if(false) func(5)").

Nonportable hacks welcome too :)

(no, using a debugger isn't the same, it's much less flexible and I find it confusing)

5 Answers5

2

This is an area where the printf style output can be more concise:

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

Of course, this has the limitation of only working for types that printf understands, and it still doesn't address your question.

I get the feeling that there might be something of value in the expression decomposition techniques in Boost, but I am not enough of a template ninja to identify what.

Update: The following almost addresses your question:

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

However, when used as PRINTDBG(a[x][y]) it literally prints:

a[x][y] = 5

which doesn't give the actual values of x and y.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
2

This is, in the way you want it, not possible. If you have if(condition) func(foo); given to a macro, it can stringize that stuff, and it will print if(condition) func(foo);, but not with the actual values of the variables substituted. Remember the preprocessor doesn't know about the structure about that code.

For debugging, i would use some type-safe printf variant like boost.format or some home brew printf with boost.fusion, which make the job of printing stuff like that much more easy:

dprintf("a[%][%] = %", (x, y, a[x][y]));
Community
  • 1
  • 1
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • thanks. i hope you enjoy it. if you are worried about performance (it's around 300ms slow for 1000000 iterations, while printf takes only 40ms), you can use this optimized version for char*: http://codepad.org/8ZQvdoMq . it collects chars, and writes them in one go. takes only 70ms then :) – Johannes Schaub - litb Jan 25 '09 at 17:22
  • it additionally uses a struct, for avoiding passing the end iterator all again, just to pass over the type of it. but here, it's just a game since you use it for debug, time doesn't matter anyway. but maybe you decide to use it for other stuff too. have fun :) – Johannes Schaub - litb Jan 25 '09 at 17:23
0

I typically use a simple, but customizable logger function instead of macros


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

so now you can do

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

add in some loggingtype (i.e. LOG_SCREEN, LOG_FILE) to the function Log() and now you can control where is gets logged to

add in some logginglevel (i.e. WARN, CRIT) to control how it gets displayed, color etc.

Of course there are many, many library's out there that do all this type of stuff already

hope this helps

Tree77
  • 473
  • 3
  • 10
0

In a slight expansion in a different direction to Greg's posting, I've seen some nice C programs that look something like this

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

However you still have a ton of printf's in your program, but at least you can turn them all on and off when you want to.

rlb.usa
  • 14,942
  • 16
  • 80
  • 128
0

you can define operator« for custom classes so you only have to define formatting once:

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)"

this pairs well with redirecting cout or clog to a file (don't recall how std::clog works)

#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;
}
Dustin Getz
  • 21,282
  • 15
  • 82
  • 131