C++ 动态启用/禁用 std::couts 的调试消息
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3371540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ enable/disable debug messages of std::couts on the fly
提问by Carlo del Mundo
Is there a way to define/undefine debug messages using std::cout whenever inside a program?
有没有办法在程序内部使用 std::cout 定义/取消定义调试消息?
I am aware that there are such things such as #define, #ifndef, but I was thinking is there a cleaner way to having a variable say:
我知道有诸如#define、#ifndef 之类的东西,但我在想是否有一种更简洁的方法来让变量说:
# debug ON
That prints all of my debug data (using std::cout). Consequently, we'll have code like this for debug:
这会打印我所有的调试数据(使用 std::cout)。因此,我们将有这样的代码用于调试:
#ifndef DEBUG
// do something useful
#endif
I find the above code cumbersome when you write 100s of debug code.
当你编写 100 多段调试代码时,我发现上面的代码很麻烦。
Thanks!
谢谢!
Carlo
卡罗
采纳答案by Michael J
Some logging libraries are pretty heavy weight unless you have complex logging needs. Here's something I just knocked together. Needs a little testing but might meet your requirements:
除非您有复杂的日志记录需求,否则某些日志记录库非常重要。这是我刚刚拼凑出来的东西。需要一些测试,但可能满足您的要求:
#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;
}
回答by Gianni
#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;
}
回答by NG.
Probably not. I would recommend using a logging library. I'm not sure what the best option is for C++ anymore, but I've used log4cppin the past and found it pretty good.
可能不是。我建议使用日志库。我不确定 C++ 的最佳选择是什么,但我过去使用过log4cpp并发现它非常好。
EDIT:I assume on the fly means @ runtime. If you just need it to be a compile time flag, then Gianni's answeris probably easiest to implement. Logging libraries give you a lot of flexibility and allow reconfiguration @ runtime though.
编辑:我假设即时意味着@运行时。如果您只需要它作为编译时标志,那么Gianni 的答案可能最容易实现。日志库为您提供了很大的灵活性,并允许重新配置@runtime。
回答by user1810087
Although the question is old, and there are some good answers, i want to post also a solution to this. It is like Giannis approach but different. And also, i used std::cerr instead of std::cout, but you can change this really quick.
虽然这个问题很老,并且有一些很好的答案,但我也想发布一个解决方案。这就像扬尼斯的方法,但不同。而且,我使用 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;
};
Now you can use it just like a output stream.
现在您可以像使用输出流一样使用它。
(Note: -edit: not with iostream
is only included if cerr
is used. This will reduce the amount of inclusion if you don't have it already included.std::endl
support).
If DEBUG
is defined cerr
is used to print the error. Otherwise the dummy class log_disabled_output
is instantiated statically and operator<<
is overloaded to any type. The vantage is; If you disable the logging, a clever compiler will notice that there is nothing to do with the stream and optimize the entire "line" away, so you don't have any overhead if DEBUG
is disabled.
(注意:。-编辑:不iostream
仅在cerr
使用时才包含。如果您尚未包含它,这将减少包含量std::endl
支持)。
如果DEBUG
定义cerr
用于打印错误。否则,虚拟类log_disabled_output
将静态实例化并operator<<
重载为任何类型。优势在于;如果您禁用日志记录,聪明的编译器会注意到与流无关并优化整个“行”,因此如果DEBUG
被禁用,您就没有任何开销。
回答by tangbotu
I was trying to do the same thing. After some research, I developed the following, and it seems to work. Please comment if you see anything wrong.
我试图做同样的事情。经过一番研究,我开发了以下内容,它似乎有效。如果您看到任何错误,请发表评论。
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;
}
回答by forumulator
Another simple solution, involves opening a std::ostream
reference to cout
in debug mode, and /dev/null
in non-debug mode, like so:
另一个简单的解决方案是在调试模式和非调试模式下打开对的std::ostream
引用,如下所示:cout
/dev/null
In debug.h:
在 debug.h 中:
extern std::ostream &dout;
In debug.c
在 debug.c
#ifdef DEBUG
std::ostream &dout = cout;
#else
std::ofstream dev_null("/dev/null");
std::ostream &dout = dev_null;
#endif
And then:
进而:
dout << "This is a debugging message";
Of course, this would only work on any system where /dev/null
points to a null device. Since the dout
reference is global here, it would much like cout
. In this way, you can point the same stream to multiple output streams, for example to a log file, depending of the value of debug flags, etc.
当然,这仅适用于/dev/null
指向空设备的任何系统。由于dout
这里的引用是全局的,因此它很像cout
. 通过这种方式,您可以将同一流指向多个输出流,例如指向日志文件,具体取决于调试标志的值等。
回答by fplandes
A clean thing to do would be to use cerr.
一件干净的事情是使用 cerr。
"cerr" acts essentially as "cout", but always flushes the output (useful for debugging, by the way). If you need to remove all the messages, you can comment out all the cerr messages with a simple find-and-replace (cerr into //cerr).
“cerr”本质上充当“cout”,但总是刷新输出(顺便说一下,对于调试很有用)。如果需要删除所有消息,可以使用简单的查找和替换(将 cerr 转换为 //cerr)注释掉所有 cerr 消息。
There are probably even better ways to use cerr and to desactivate it cleanly (which writes into a special stream, the error stream, hence the name). I hope this helps.
可能有更好的方法来使用 cerr 并彻底停用它(它写入一个特殊的流,错误流,因此得名)。我希望这有帮助。
回答by Reno
This is what I used (worked with VC++) - here "##" is used for concatennation
这是我使用的(与 VC++ 一起使用) - 这里“##”用于连接
#ifdef DEBUG
#define pout cout
#else
#define pout / ## / cout
#endif
For other compilers use this :
对于其他编译器使用这个:
#ifdef DEBUG
#define pout cout
#else
#define pout 0 && cout
#endif
Usage :
用法 :
pout << "hello world" << endl;
回答by Mithun B
I was looking for similar example and sharing my example below:
我正在寻找类似的例子并在下面分享我的例子:
#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;
}
Better suggestions are always welcome.
更好的建议总是受欢迎的。