有没有一种方法可以在程序内部使用std :: cout定义/取消定义调试消息?
我知道有像#define,#ifndef这样的东西,但我想知道是否有更简洁的方式来定义一个变量,比如:
# debug ON
这会打印出所有的调试数据(使用std::cout)。因此,我们的调试代码看起来像这样:
#ifndef DEBUG
// do something useful
#endif
当你编写数百个调试代码时,我发现上述代码很麻烦。
谢谢!
Carlo
#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;
}
除非您有复杂的日志记录需求,否则一些日志记录库可能会很重。这里是我刚刚拼凑出来的东西。需要进行一些测试,但可能符合您的要求:
#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;
}
另一个简单的解决方案是,在调试模式下打开对cout
的std::ostream
引用,并在非调试模式下打开/dev/null
,如下所示:
在debug.h文件中:
extern std::ostream &dout;
#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
指向空设备。由于此处引用是全局的,因此它类似于cout
。通过这种方式,您可以将相同的流指向多个输出流,例如日志文件,具体取决于调试标志的值等。虽然这个问题很旧,也有一些好的答案,但我想发布一个解决方案。它类似于Giannis的方法,但不同。而且,我使用了std::cerr而不是std::cout,但你可以很快地更改它。
#include <iostream>
#ifdef DEBUG
# 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; }
// std::endl simple, quick and dirty
log_disabled_output& operator << (log_disabled_output& any, std::ostream&(*)(std::ostream&)) { return any; }
# define DEBUG_LOG log_disabled_output_instance
#endif
int main() {
int x=0x12345678;
DEBUG_LOG << "my message " << x << " " << "\n more information" << std::endl;
};
endl
,是吗? - ephemerr我也想做同样的事情。经过一些研究,我开发了以下内容,并且似乎可以正常工作。如果您发现任何问题,请在评论区留言。
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;
}
这是我使用的代码(在VC++中工作)- 这里“##”用于连接字符串
#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;
我在寻找类似的示例并在下面分享我的示例:
#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;
}
欢迎提出更好的建议。
#ifndef debug
这个条件编译指令。 - Giannido while
的目的是什么? - cYrus