有没有办法在程序内部使用std :: cout定义/取消定义调试消息?
我知道有像#define,#ifnf这样的东西,但是我觉得有一个更简洁的方法让变量说:
# debug ON
打印我的所有调试数据(使用std :: cout)。因此,我们将为调试提供类似的代码:
#ifndef DEBUG
// do something useful
#endif
当你编写100多个调试代码时,我发现上面的代码很麻烦。
谢谢!
卡罗
答案 0 :(得分:32)
#ifdef DEBUG
#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
#else
#define DEBUG_MSG(str) do { } while ( false )
#endif
int main()
{
DEBUG_MSG("Hello" << ' ' << "World!" << 1 );
return 0;
}
答案 1 :(得分:7)
除非您有复杂的日志记录需求,否则某些日志库非常重要。这是我刚碰到的东西。需要进行一些测试,但可能符合您的要求:
#include <cstdio>
#include <cstdarg>
class CLog
{
public:
enum { All=0, Debug, Info, Warning, Error, Fatal, None };
static void Write(int nLevel, const char *szFormat, ...);
static void SetLevel(int nLevel);
protected:
static void CheckInit();
static void Init();
private:
CLog();
static bool m_bInitialised;
static int m_nLevel;
};
bool CLog::m_bInitialised;
int CLog::m_nLevel;
void CLog::Write(int nLevel, const char *szFormat, ...)
{
CheckInit();
if (nLevel >= m_nLevel)
{
va_list args;
va_start(args, szFormat);
vprintf(szFormat, args);
va_end(args);
}
}
void CLog::SetLevel(int nLevel)
{
m_nLevel = nLevel;
m_bInitialised = true;
}
void CLog::CheckInit()
{
if (!m_bInitialised)
{
Init();
}
}
void CLog::Init()
{
int nDfltLevel(CLog::All);
// Retrieve your level from an environment variable,
// registry entry or wherecer
SetLevel(nDfltLevel);
}
int main()
{
CLog::Write(CLog::Debug, "testing 1 2 3");
return 0;
}
答案 2 :(得分:5)
可能不是。我建议使用日志库。我不确定C ++的最佳选择是什么,但我过去使用log4cpp并发现它非常好。
编辑:我假设在运行中意味着@运行时。如果您只需要它是编译时标志,那么Gianni's answer可能最容易实现。日志库为您提供了很大的灵活性,并允许重新配置@ runtime。
答案 3 :(得分:3)
虽然问题很老,而且有一些好的答案,但我想发布一个解决方案。这就像Giannis的方法,但不同。而且,我使用std :: cerr而不是std :: cout,但你可以很快地改变它。
#ifdef DEBUG
# include <iostream>
# define DEBUG_LOG std::cerr
#else
class log_disabled_output {};
static log_disabled_output log_disabled_output_instance;
template<typename T>
log_disabled_output& operator << (log_disabled_output& any, T const& thing) { return any; }
# define DEBUG_LOG log_disabled_output_instance
#endif
int main() {
int x=0815;
DEBUG_LOG << "my message " << x << " " << x/M_PI << "\n";
};
现在您可以像输出流一样使用它。
注意:仅在使用iostream
时才会包含cerr
。如果您还没有包含,这将减少包含量。如果定义DEBUG
,则使用cerr
来打印错误。否则,静态实例化空类log_disabled_output
,并将operator<<
重载为任何类型。这里的事情是;如果禁用日志记录,聪明的编译器会注意到与流无关并优化整个&#34;行&#34;离开,所以如果DEBUG
被禁用,你就不会有任何开销。
答案 4 :(得分:2)
我试图做同样的事情。经过一些研究,我开发了以下内容,它似乎有效。如果您发现任何错误,请发表评论。
ostream DbgMsg(NULL);
enum {
DBGMSG_NONE,
DBGMSG_DEFAULT,
DBGMSG_VERBOSE
} DbgLvl = DBGMSG_DEFAULT;
ostream &DbgMsgDefault(ostream &stream) {
return (DbgLvl>=DBGMSG_DEFAULT) ? cout : stream;
}
ostream &DbgMsgVerbose(ostream &stream) {
return (DbgLvl>=DBGMSG_VERBOSE) ? cout : stream;
}
void main() {
DbgMsg<<DbgMsgDefault<<"default:default"<<endl;
DbgMsg<<DbgMsgVerbose<<"default:verbose"<<endl;
DbgLvl = DBGMSG_NONE;
DbgMsg<<DbgMsgDefault<<"none:default"<<endl;
}
答案 5 :(得分:1)
一件干净的事情就是使用cerr。
“cerr”基本上表现为“cout”,但总是刷新输出(顺便说一下,对于调试很有用)。如果您需要删除所有消息,可以使用简单的查找和替换(cerr into // cerr)注释掉所有cerr消息。
甚至可能有更好的方法来使用cerr并彻底地将其去活(它写入一个特殊的流,错误流,因此名称)。 我希望这会有所帮助。
答案 6 :(得分:1)
这是我使用的(使用VC ++) - 这里&#34; ##&#34;用于连接
#ifdef DEBUG
#define pout cout
#else
#define pout / ## / cout
#endif
对于其他编译器,请使用:
#ifdef DEBUG
#define pout cout
#else
#define pout 0 && cout
#endif
用法:
pout << "hello world" << endl;
答案 7 :(得分:0)
另一个简单的解决方案涉及在调试模式下打开std::ostream
cout
引用,在非调试模式下打开/dev/null
,如下所示:
在debug.h中:
extern std::ostream &dout;
在debug.c中
#ifdef DEBUG
std::ostream &dout = cout;
#else
std::ofstream dev_null("/dev/null");
std::ostream &dout = dev_null;
#endif
然后:
dout << "This is a debugging message";
当然,这只适用于/dev/null
指向空设备的任何系统。由于此处dout
引用是全局的,因此它非常类似于cout
。通过这种方式,您可以将相同的流指向多个输出流,例如指向日志文件,具体取决于调试标志的值等。
答案 8 :(得分:0)
我正在寻找类似的示例,并在下面分享我的示例:
#include <iostream>
enum debug_option
{
DEBUG_DISABLE,
DEBUG_ENABLE
};
class debug
{
public:
debug_option debug_state;
debug() : debug_state(DEBUG_ENABLE) {} // constr
debug(debug_option state) : debug_state(state) {} // constr
template<typename T>
debug & operator<< (T input)
{
if (this->debug_state == DEBUG_ENABLE)
std::cout << input;
return *this;
}
};
int main()
{
debug log, log_lev2(DEBUG_DISABLE);
log << "print 1..\n" << 55 << " over\n";
log.debug_state = DEBUG_DISABLE;
log << "print 2..\n" << 3 << "over\n";
log_lev2 << "print 3..\n" << 4 << "over\n";
log_lev2.debug_state = DEBUG_ENABLE;
log_lev2 << "print 5..\n";
std::cout << "std::cout << print..\n";
return 0;
}
总是欢迎提出更好的建议。