Printing detailed debugging output easily? - c++

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)

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

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.

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

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.

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

Related

How do I stream into a string without creating a named stringstream?

I often end up writing code like this:
SomeStreamableType x;
std::stringstream ss;
ss << "Value is: " << x;
log(ss.str());
The extra line needed to generate the stringstream feels superfulous. I can do this, but it's equally cumbersom:
SomeStreamableType x;
const std::string str = "Value is: " + boost::lexical_cast<std::string>(x);
log(str);
I want to be able to do this:
SomeStreamableType x;
log(std::stringstream() << "Value is: " << x);
Have others encountered this issue and come up with a workaround? I don't want to create any helper functions or classes.
Your code will work without modifications, as long as log accepts an ostream& reference:
void log(ostream& o) {
stringstream* s = dynamic_cast<stringstream*>(&o);
if (s) {
cout << s->str() << endl;
}
}
int main() {
int x = 5, y = 6;
log(stringstream() << "x=" << x << ", y=" << y);
return 0;
}
Demo.
To solve this problem I have often simply done something like this:
#define LOG(m) do{std::ostringstream oss;oss<<m;std::cout<<oss.str()<<'\n';}while(0)
// ...
LOG("some text: " << value1 << ' ' << value2); // no need for '\n'
Now I tend to use a more sophisticated class based solution that has an even nicer interface and doesn't use a horrible macro.

Structured output

I recently started programming in c++ and I've bumped into a small problem. If I want my output to be structured (let's say that every line starts with a name and then a number) in a way that the names are written normally to the screen (every first letter of every name starts at the beginning of each new line) and I want the numbers that follow to be lined up in a column, how would I do this? I want the programs output to look like this:
Gary 0
LongName 0
VerylongName 0
I want my program to print something in the way above, but with different lengths of names (and the '0' in this case, lined up in a column).
Try the following: if you know the maximum length of all the names you intend to print (e.g. 20), then use the C++ i/o manipulators to set the width of the output (and left-justification). This will force the output to take up max characters.
Code snippet:
#include <iostream>
#include <iomanip>
...
// for each entry
std::cout << std::setw(20) << std::left << "Gary" << 10 << "\n";
...
std::cout << std::flush;
Here's some more information...
I'm shooting in the dark here since you haven't really included much information... HOWEVER one way you can do this is to make sure that you create the columns with padding around the name - and not worry about the numbers. Formatted output is one case where C has an advantage over C++ (IMHO). In C++ you can also do this with something like this:
cout << setw(15) << name << number << "\n";
Bonus points if you figure out ahead of time the maximum length of the name you have and add, say, 4 to it.
Not in the C++ standard library, but still worth mentioning: boost::format. It will let you write printf-like format strings while still being type-safe.
Example:
#include <boost/format.hpp>
#include <iostream>
#include <string>
struct PersonData
{
std::string name;
int age;
};
PersonData persons[] =
{
{"Gary", 1},
{"Whitney", 12},
{"Josephine ", 101}
};
int main(void)
{
for (auto person : persons)
{
std::cout << boost::format("%-20s %5i") % person.name % person.age << std::endl;
}
return 0;
}
Outputs:
Gary 1
Whitney 12
Josephine 101
struct X
{
const char *s;
int num;
} tab[] = {
{"Gary",1},
{"LongName",23},
{"VeryLongName",456}
};
int main(void)
{
for (int i = 0; i < sizeof(tab) / sizeof(struct X); i++ )
{
// C like - example width 20chars
//printf( "%-20s %5i\n", tab[i].s, tab[i].num );
// C++ like
std::cout << std::setw(20) << std::left << tab[i].s << std::setw(5) << std::right << tab[i].num << std::endl;
}
getchar();
return 0;
}

How to print a bunch of integers with the same formatting?

I would like to print a bunch of integers on 2 fields with '0' as fill character. I can do it but it leads to code duplication. How should I change the code so that the code duplication can be factored out?
#include <ctime>
#include <sstream>
#include <iomanip>
#include <iostream>
using namespace std;
string timestamp() {
time_t now = time(0);
tm t = *localtime(&now);
ostringstream ss;
t.tm_mday = 9; // cheat a little to test it
t.tm_hour = 8;
ss << (t.tm_year+1900)
<< setw(2) << setfill('0') << (t.tm_mon+1) // Code duplication
<< setw(2) << setfill('0') << t.tm_mday
<< setw(2) << setfill('0') << t.tm_hour
<< setw(2) << setfill('0') << t.tm_min
<< setw(2) << setfill('0') << t.tm_sec;
return ss.str();
}
int main() {
cout << timestamp() << endl;
return 0;
}
I have tried
std::ostream& operator<<(std::ostream& s, int i) {
return s << std::setw(2) << std::setfill('0') << i;
}
but it did not work, the operator<< calls are ambigous.
EDIT I got 4 awesome answers and I picked the one that is perhaps the simplest and the most generic one (that is, doesn't assume that we are dealing with timestamps). For the actual problem, I will probably use std::put_time or strftime though.
In C++20 you'll be able to do this with std::format in a less verbose way:
ss << std::format("{}{:02}{:02}{:02}{:02}{:02}",
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec);
and it's even easier with the {fmt} library that supports tm formatting directly:
auto s = fmt::format("{:%Y%m%d%H%M%S}", t);
You need a proxy for your string stream like this:
struct stream{
std::ostringstream ss;
stream& operator<<(int i){
ss << std::setw(2) << std::setfill('0') << i;
return *this; // See Note below
}
};
Then your formatting code will just be this:
stream ss;
ss << (t.tm_year+1900)
<< (t.tm_mon+1)
<< t.tm_mday
<< t.tm_hour
<< t.tm_min
<< t.tm_sec;
return ss.ss.str();
ps. Note the general format of my stream::operator<<() which does its work first, then returns something.
The "obvious" solution is to use a manipulator to install a custom std::num_put<char> facet which just formats ints as desired.
The above statement may be a bit cryptic although it entirely describes the solution. Below is the code to actually implement the logic. The first ingredient is a special std::num_put<char> facet which is just a class derived from std::num_put<char> and overriding one of its virtual functions. The used facet is a filtering facet which looks at a flag stored with the stream (using iword()) to determine whether it should change the behavior or not. Here is the code:
class num_put
: public std::num_put<char>
{
std::locale loc_;
static int index() {
static int rc(std::ios_base::xalloc());
return rc;
}
friend std::ostream& twodigits(std::ostream&);
friend std::ostream& notwodigits(std::ostream&);
public:
num_put(std::locale loc): loc_(loc) {}
iter_type do_put(iter_type to, std::ios_base& fmt,
char fill, long value) const {
if (fmt.iword(index())) {
fmt.width(2);
return std::use_facet<std::num_put<char> >(this->loc_)
.put(to, fmt, '0', value);
}
else {
return std::use_facet<std::num_put<char> >(this->loc_)
.put(to, fmt, fill, value);
}
}
};
The main part is the do_put() member function which decides how the value needs to be formatted: If the flag in fmt.iword(index()) is non-zero, it sets the width to 2 and calls the formatting function with a fill character of 0. The width is going to be reset anyway and the fill character doesn't get stored with the stream, i.e., there is no need for any clean-up.
Normally, the code would probably live in a separate translation unit and it wouldn't be declared in a header. The only functions really declared in a header would be twodigits() and notwodigits() which are made friends in this case to provide access to the index() member function. The index() member function just allocates an index usable with std::ios_base::iword() when called the time and it then just returns this index. The manipulators twodigits() and notwodigits() primarily set this index. If the num_put facet isn't installed for the stream twodigits() also installs the facet:
std::ostream& twodigits(std::ostream& out)
{
if (!dynamic_cast<num_put const*>(
&std::use_facet<std::num_put<char> >(out.getloc()))) {
out.imbue(std::locale(out.getloc(), new num_put(out.getloc())));
}
out.iword(num_put::index()) = true;
return out;
}
std::ostream& notwodigits(std::ostream& out)
{
out.iword(num_put::index()) = false;
return out;
}
The twodigits() manipulator allocates the num_put facet using new num_put(out.getloc()). It doesn't require any clean-up because installing a facet in a std::locale object does the necessary clean-up. The original std::locale of the stream is accessed using out.getloc(). It is changed by the facet. In theory the notwodigits could restore the original std::locale instead of using a flag. However, imbue() can be a relatively expensive operation and using a flag should be a lot cheaper. Of course, if there are lots of similar formatting flags, things may become different...
To demonstrate the use of the manipulators there is a simple test program below. It sets up the formatting flag twodigits twice to verify that facet is only created once (it would be a bit silly to create a chain of std::locales to pass through the formatting:
int main()
{
std::cout << "some-int='" << 1 << "' "
<< twodigits << '\n'
<< "two-digits1='" << 1 << "' "
<< "two-digits2='" << 2 << "' "
<< "two-digits3='" << 3 << "' "
<< notwodigits << '\n'
<< "some-int='" << 1 << "' "
<< twodigits << '\n'
<< "two-digits4='" << 4 << "' "
<< '\n';
}
Besides formatting integers with std::setw / std::setfill or ios_base::width / basic_ios::fill, if you want to format a date/time object you may want to consider using std::put_time / std::gettime
For convenient output formatting you may use boost::format() with sprintf-like formatting options:
#include <boost/format.hpp>
#include <iostream>
int main() {
int i1 = 1, i2 = 10, i3 = 100;
std::cout << boost::format("%03i %03i %03i\n") % i1 % i2 % i3;
// output is: 001 010 100
}
Little code duplication, additional implementation effort is marginal.
If all you want to do is output formatting of your timestamp, you should obviously use strftime(). That's what it's made for:
#include <ctime>
#include <iostream>
std::string timestamp() {
char buf[20];
const char fmt[] = "%Y%m%d%H%M%S";
time_t now = time(0);
strftime(buf, sizeof(buf), fmt, localtime(&now));
return buf;
}
int main() {
std::cout << timestamp() << std::endl;
}
operator<<(std::ostream& s, int i) is "ambiguous" because such a function already exists.
All you need to do is give that function a signature that doesn't conflict.

Writing a macro for logging

I'm writing a logging class at the moment. The Logger works with streams and also prints the object which is logging at the moment. Here is the macro:
#define OBJLOG(DL, what) DL <= this->Logger->getDebugLevel() ? *this->Logger << DL << "[" << this->Name << "]: "<< what << std::endl : this->Logger->doNothing();
The pseudo code Variant for better overview:
#define OBJLOG(debuglevel, what) debuglevel <= logger.debuglevel ? logger.log(what) : logger.doNothing()
Is there any way to get around the doNothing function call, like doing nothing at all?
#define OBJLOG(DL, what) do { if(DL <= this->Logger->getDebugLevel()) *this->Logger << DL << "[" << this->Name << "]: "<< what << std::endl; } while(0)
See Why use apparently meaningless do-while and if-else statements in macros? for an explanation. (The do {} while(0) isn't strictly necessary here, but I would prefer not to leak an ostream.)
Also, you should always wrap macro argument uses in parentheses, like:
#define OBJLOG(DL, what) do { if((DL) <= this->Logger->getDebugLevel()) *this->Logger << (DL) << "[" << this->Name << "]: "<< (what) << std::endl; } while(0)
Finally, you should move this code into a function and call that in your macro (if you really insist on using a macro) to avoid evaluating your macro arguments more than once.
Have your logger.log() function return a boolean.
Connect your predicates with an and like this: debuglevel <= logger.debuglevel && logger.log
That should do the trick.
If you want an expression that does nothing, try (void)0.

TOUGH: Dealing with deeply nested pointers in C++

I define this structure:
struct s_molecule
{
std::string res_name;
std::vector<t_particle> my_particles;
std::vector<t_bond> my_bonds;
std::vector<t_angle> my_angles;
std::vector<t_dihedral> my_dihedrals;
s_molecule& operator=(const s_molecule &to_assign)
{
res_name = to_assign.res_name;
my_particles = to_assign.my_particles;
my_bonds = to_assign.my_bonds;
my_angles = to_assign.my_angles;
my_dihedrals = to_assign.my_dihedrals;
return *this;
}
};
and these structures:
typedef struct s_particle
{
t_coordinates position;
double charge;
double mass;
std::string name;
std::vector<t_lj_param>::iterator my_particle_kind_iter;
s_particle& operator=(const s_particle &to_assign)
{
position = to_assign.position;
charge = to_assign.charge;
mass = to_assign.mass;
name = to_assign.name;
my_particle_kind_iter = to_assign.my_particle_kind_iter;
return *this;
}
} t_particle;
struct s_bond
{
t_particle * particle_1;
t_particle * particle_2;
std::vector<t_bond_param>::iterator my_bond_kind_iter;
s_bond& operator=(const s_bond &to_assign)
{
particle_1 = to_assign.particle_1;
particle_2 = to_assign.particle_2;
my_bond_kind_iter = to_assign.my_bond_kind_iter;
return *this;
}
};
and then in my code I return a pointer to an s_molecule (typedef'd to t_molecule, but still).
Using this pointer I can get this code to work:
for (unsigned int i = 0;
i < current_molecule->my_particles.size();
i++)
{
std::cout << "Particle "
<< current_molecule->my_particles[i].name << std::endl
<< "Charge: "
<< current_molecule->my_particles[i].charge << std::endl
<< "Mass: "
<< current_molecule->my_particles[i].mass << std::endl
<< "Particle Kind Name: "
<< (*current_molecule->my_particles[i].my_particle_kind_iter).atom_kind_name
<< std::endl
<< "x: " << current_molecule->my_particles[i].position.x
<< " y: " << current_molecule->my_particles[i].position.y
#ifdef USE_3D_GEOM
<< "z: " << current_molecule->my_particles[i].position.z
#endif
<< std::endl;
}
If I replace it with:
for (std::vector<t_particle>::iterator it = current_molecule->my_particles.begin();
it !=current_molecule->my_particles.end();
it++)
{
std::cout << "Particle "
<< (*it).name << std::endl
<< "Charge: "
<< (*it).charge << std::endl
<< "Mass: "
<< (*it).mass << std::endl
<< "Particle Kind Name: "
<< (*(*it).my_particle_kind_iter).atom_kind_name
<< std::endl
<< "x: " << (*it).position.x
<< " y: " << (*it).position.y
#ifdef USE_3D_GEOM
<< "z: " << (*it).position.z
#endif
<< std::endl;
}
I now get nasty segfaults...
Not to put too much here, but I'm also getting segfaults when I tried to do this:
std::cout << "Bond ATOMS : "
<< (*current_molecule).my_bonds[0].particle_1->name
<< std::endl
Again, current_molecule is a pointer to a s_molecule structure, which contains arrays of structures, which in turn either directly have vars or are pointers. I can't get these multiple layers of indirection to work. Suggestions on fixing these segfaults.
FYI I'm compiling on Linux Centos 5.4 with g++ and using a custom makefile system.
#sbi Thanks for the good advice! I believe you are right -- the assignment overloaded operator is unnecessary and should be scrapped.
I've followed the approach of commenting out stuff and am very confused. Basically in the function that passes the pointer to my particular molecule to the main function to print, I can see all the data in that molecule (bonds, particles, name, etc) perfectly, printing with cout's.
Once I pass it to the main as a ptr, if I use that ptr with an iterator I get a segfault. In other words. Also for some reason the bond data (which I can freely print in my funct that returns to the pointer) also segfaults if I try to print it, even if I use the [] to index the vector of bonds (which works for the particle vector).
That's the best info I can give for now.
A wild guess: Are you using shared libraries. I remember having difficulties passing STL-containers back and forth across shared library boundaries.
Jason (OP) was asked in a comment by David Rodríguez:
Are you returning a pointer to a local variable?
Jason answered:
No its a ptr to a class variable. The class is very much in existence (it contains the function that returns the molecule).
Unless you're talking of a true class variable (qualified as static), the fact that the class exists doesn't have much to do with it. Instances of a class exist, and they might have ceased to exist even if you just called a function on them.
As such, the question is:
Does the instance of the class that returned the pointer current_molecule still exist?
Or is current_molecule qualified as static, i.e. being a true class variable?
If the answer to both questions is "no", you're in Undefined County.
At this point, it becomes very important that you post source code that can be used by us here to actually reproduce the problem; it might well be located in source you aren't showing us.
Again, this issue was answered here:
Weird Pointer issue in C++
by DeadMG. Sorry for the double post.