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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 12:42:13  来源:igfitidea点击:

C++ enable/disable debug messages of std::couts on the fly

c++debugging

提问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: iostreamis only included if cerris used. This will reduce the amount of inclusion if you don't have it already included.-edit: not with std::endlsupport).
If DEBUGis defined cerris used to print the error. Otherwise the dummy class log_disabled_outputis 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 DEBUGis 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::ostreamreference to coutin debug mode, and /dev/nullin 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/nullpoints to a null device. Since the doutreference 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.

更好的建议总是受欢迎的。