如何登录? [英] How to log?

查看:31
本文介绍了如何登录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C中,我总是会创建一个log()函数,而不是使用printfs,

以便我可以禁用消息或以其他方式处理它们,所有这些都在

中一个地方。这在一行中用于常量字符串,但不用于

变量值,如:

char s [99];

sprintf (s,值为%d \ n,值);

log(s); // 3行!!


在C ++中,它真的像它一样糟糕吗?如果我使用流:

ostringstream oss;

oss<< 价值是 <<值<< endl;

log(oss.str());

没有更好!


我怀疑答案可能是使用堵塞:

clog<< 价值是 <<值<< endl;

但是我没有看到任何可以在以后定制或禁用的地方。

(我读到clog与cerr相同,但是clog是缓冲的。)


那么,人们如何记录?

In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don''t see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?

推荐答案



" syncman" < HS *** @ hotmail.com>在消息新闻中写道:cc ************************** @ posting.google.c om ...

"syncman" <hs***@hotmail.com> wrote in message news:cc**************************@posting.google.c om...
在C中,我总是会创建一个log()函数而不是使用printfs,

那么,人们如何记录?
In C, I would always make a log() function instead of using printfs,

So, how do people log?




我们有我们自己的功能名为

LogPrintf

我们自己的流名为

LogOut


基于程序员倾向于,他可以使用其中任何一个。



We have our own function called
LogPrintf
And our own stream called
LogOut

Based on the programmers inclination, he can either use either one.


syncman写道:
syncman wrote:
在C中,我总是会做一个日志( )函数而不是使用printfs,
以便我可以禁用消息或以其他方式处理它们,所有这些都在一个地方。对于常量字符串,这有效,但不适用于变量值,如:
char s [99];
sprintf(s,"值为%d \ n,value);
log(s); // 3行!!

在C ++中,它真的像它一样糟糕吗?如果我使用流:
ostringstream oss;
oss<< 价值是 <<值<< endl;
log(oss.str());
没有更好的!

我怀疑答案可能是使用clog:
clog<< 价值是 <<值<<但是我没有看到任何可以在以后定制或禁用的地方。
(我读到clog与cerr相同,但clog是缓冲的。)
In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don''t see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?




我过去曾使用过像这样的方案。实际的日志记录类

比下面的更灵活,但是这个例子给你一个想法。


接口是通过宏LOG来实现的。并且你传递了一个记录级别

和一个标题。实际的水平应该是枚举,但为了简单起见,我在这里只使用了一个int

(在实际系统中我会使用面具)。


LOG创建一个名为lout的对象在销毁时会输出

的日志字符串。





LOG(ERROR_LEVEL,这是错误日志);




LOG(WARNING_LEVEL,这是一个警告)

{

lout.attr(" oil_level")<< oil_level<< "太低了;

} //<<<消息字符串在此处发送


如果未启用日志记录,则根本不会创建任何消息。


如果将WARNING_LEVEL值设置为0 ,编译器将完全消除

警告级别的日志记录代码。


我用这种技术看到的唯一问题是

其他人错过了;在结束时,当日志记录打开时,代码可以正常工作,而不是它失败了....可爱的


我玩弄改变了接口:


LOG(LOG_LEVEL,Title)END_LOG


消除这种错误的可能性,但我''我仍然没有

肯定这是最好的答案。简单性更好。


.....这是一个例子....


#include< sstream>

#include< iostream>


#define LOG(LEVEL,TITLE)\

if(int x_level =(LEVEL)) \

if(Logger lout = x_level)\

if(lout.Title(TITLE))

// end


struct LoggerContext

{

std :: ostringstream m_oss;

int m_level;

mutable int m_count;


LoggerContext(int l_level)

:m_level(l_level),

m_count(1)

{

}


};


struct Logger

{

LoggerContext * m_context;


static int min_level;


Logger(int l_level)

:m_context(l_level> = min_level?new LoggerContext(l_level)

:0)

{

}


bool标题(const char * l_title)

{

m_context-> m_oss<< l_title<< " :" ;;

返回m_context;

}


模板< typename T>

记录仪和运算符<< (const T& value)

{

m_context-> m_oss<<价值;

返回*这个;

}


Logger& attr(const char * s_attr)

{

m_context-> m_oss<< " " << s_attr<< " =" ;;

返回* this;

}


~Logger()

{

if(m_context)

{

- m_context-> m_count;

if(m_context-> ; m_count == 0)

{

m_context-> m_oss<< " \ n";

///在此写日志

std :: cout<< m_context-> m_oss.str();

删除m_context;

}

}

}


运算符bool()

{

返回m_context;

}

Logger(const Logger& l_rhs)

:m_context(l_rhs.getref())

{

}


LoggerContext * getref()const

{

++(m_context-> m_count);

返回m_context;

}

};

int Logger :: min_level = 2;

int main( )

{

LOG(3,Thing 1);


LOG(4," Thing 2" )

{

lout<< 真的 << 33;

lout.attr(" Some value")<< 54;

lout.attr(" Some other value")<< 99.33;

}


LOG(1,Thing 3)

{

lout<< 不是真的;

}


}



I''ve used a scheme like this one in the past. The actual logging class
was far more flexible than the one below but this example gives you an idea.

The interface is through the macro "LOG" and you pass it a logging level
and a title. The actual levels should be an enum but I just used an int
here for sake of simplicity (in a real system I would use mask).

LOG creates an object named "lout" which upon destruction will output
the log string.

i.e.

LOG( ERROR_LEVEL, "This is an error log" );

of

LOG( WARNING_LEVEL, "This is a warning" )
{
lout.attr( "oil_level" ) << oil_level << " is too low";
} // <<< message string is sent here

If logging is not enabled, no messages are created at all.

If you set the WARNING_LEVEL value to 0, the compiler will eliminate the
warning level logging code entirely.

THE one and only problem I''ve seen with this technique is that
occationally someone misses the ";" at the end and when logging is
turned on, the code works and when it is not it fails .... cute

I toyed with changing the interface to:

LOG( LOG_LEVEL, "Title" ) END_LOG

to eliminate this possibility of this kind of error but I''m still not
sure it''s the best answer. Simplicity is better.

..... here is an example ....

#include <sstream>
#include <iostream>

#define LOG( LEVEL, TITLE ) \
if ( int x_level = (LEVEL) ) \
if ( Logger lout = x_level ) \
if ( lout.Title(TITLE) )
// end

struct LoggerContext
{
std::ostringstream m_oss;
int m_level;
mutable int m_count;

LoggerContext( int l_level )
: m_level( l_level ),
m_count( 1 )
{
}

};

struct Logger
{
LoggerContext * m_context;

static int min_level;

Logger( int l_level )
: m_context( l_level >= min_level ? new LoggerContext( l_level )
: 0 )
{
}

bool Title( const char * l_title )
{
m_context->m_oss << l_title << " : ";
return m_context;
}

template <typename T>
Logger & operator << ( const T & value )
{
m_context->m_oss << value;
return * this;
}

Logger & attr( const char * s_attr )
{
m_context->m_oss << " " << s_attr << " = ";
return * this;
}

~Logger()
{
if ( m_context )
{
-- m_context->m_count;
if ( m_context->m_count == 0 )
{
m_context->m_oss << "\n";
/// write log here
std::cout << m_context->m_oss.str();
delete m_context;
}
}
}

operator bool()
{
return m_context;
}

Logger( const Logger & l_rhs )
: m_context( l_rhs.getref() )
{
}

LoggerContext * getref() const
{
++ ( m_context->m_count );
return m_context;
}
};
int Logger::min_level = 2;
int main()
{
LOG( 3, "Thing 1" );

LOG( 4, "Thing 2" )
{
lout << "Really " << 33;
lout.attr( "Some value" ) << "54";
lout.attr( "Some other value" ) << 99.33;
}

LOG( 1, "Thing 3" )
{
lout << "Not really";
}

}


" Gianni马里亚尼" < GI ******* @ mariani.ws>在消息中写道

news:bu ******** @ dispatch.concentric.net ...
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:bu********@dispatch.concentric.net...
syncman写道:
syncman wrote:
在C中,我总是会创建一个log()函数,而不是使用printfs,
这样我就可以在一个地方禁用消息或以其他方式处理它们。对于常量字符串,这有效,但不适用于变量值,如:
char s [99];
sprintf(s,"值为%d \ n,value);
log(s); // 3行!!

在C ++中,它真的像它一样糟糕吗?如果我使用流:
ostringstream oss;
oss<< 价值是 <<值<< endl;
log(oss.str());
没有更好的!

我怀疑答案可能是使用clog:
clog<< 价值是 <<值<<但是我没有看到任何可以在以后定制或禁用的地方。
(我读到clog与cerr相同,但clog是缓冲的。)
我过去曾使用过这样的方案。实际的日志记录类比下面的更灵活,但是这个例子给你一个
In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don''t see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?
I''ve used a scheme like this one in the past. The actual logging class
was far more flexible than the one below but this example gives you an



的想法。
界面是通过宏LOG来实现的。并且你传递了一个日志级别
和标题。实际级别应该是一个枚举,但为了简单起见,我在这里使用了一个int
(在一个真实的系统中我会使用mask)。
LOG创建一个名为lout的对象。破坏后会输出日志字符串。

LOG(ERROR_LEVEL,这是一个错误日志);

{
lout.attr(" oil_level")<< oil_level<< "太低了;
} //<<<消息字符串在此处发送

如果未启用日志记录,则根本不会创建任何消息。

如果将WARNING_LEVEL值设置为0,编译器将消除
我用这种技术看到的唯一问题是,有些人错过了;。在最后,当打开日志时,代码可以正常工作,当它没有失败时....可爱

我玩弄了将界面更改为:
<记录(LOG_LEVEL,标题)END_LOG

要消除这种错误的可能性,但我仍然没有确定这是最好的答案。简单性更好。

....这是一个例子......

#include< sstream>
#include< iostream>

#define LOG(LEVEL,TITLE)\
if(int x_level =(LEVEL))\
if(Logger lout = x_level)\
if( lout.Title(TITLE))
//结束

结构LoggerContext
{
std :: ostringstream m_oss;
int m_level;
mutable int m_count;

LoggerContext(int l_level)
:m_level(l_level),
m_count(1)
{
}
<结构记录器
{
LoggerContext * m_context;

static int min_level;

记录器( int l_level)
:m_context(l_level> = min_level?new LoggerContext(l_level)
:0)
{
}

bool标题(const char * l_title)
{
m_context-> m_oss << l_title<< " :" ;;
返回m_context;
}

模板< typename T>
Logger&运算符<< (const T& value)
{
m_context-> m_oss<<价值;
返回*这个;
}

Logger& attr(const char * s_attr)
{
m_context-> m_oss<< " " << s_attr<< " =" ;;
返回*这个;
}
〜记录器()
{
if(m_context)
{
- m_context-> m_count;
if(m_context-> m_count == 0)
{
m_context-> m_oss<< " \ n";
///在这里写日志
std :: cout<< m_context-> m_oss.str();
删除m_context;
}
}


operator bool()
{
return m_context;
}
记录器(const Logger& l_rhs)
:m_context(l_rhs.getref())



LoggerContext * getref()const
{
++(m_context-> m_count);
返回m_context;
}

};

int Logger :: min_level = 2;

int main()
{LOG> 3,Thing 1" ;);

LOG(4,Thing 2)
{
lout<< 真的 << 33;
lout.attr(" Some value")<< 54;
lout.attr(一些其他值)<< 99.33;
}
LOG(1,Thing 3)
{
lout<< 不是真的;
}

}


idea.
The interface is through the macro "LOG" and you pass it a logging level
and a title. The actual levels should be an enum but I just used an int
here for sake of simplicity (in a real system I would use mask).

LOG creates an object named "lout" which upon destruction will output
the log string.

i.e.

LOG( ERROR_LEVEL, "This is an error log" );

of

LOG( WARNING_LEVEL, "This is a warning" )
{
lout.attr( "oil_level" ) << oil_level << " is too low";
} // <<< message string is sent here

If logging is not enabled, no messages are created at all.

If you set the WARNING_LEVEL value to 0, the compiler will eliminate the
warning level logging code entirely.

THE one and only problem I''ve seen with this technique is that
occationally someone misses the ";" at the end and when logging is
turned on, the code works and when it is not it fails .... cute

I toyed with changing the interface to:

LOG( LOG_LEVEL, "Title" ) END_LOG

to eliminate this possibility of this kind of error but I''m still not
sure it''s the best answer. Simplicity is better.

.... here is an example ....

#include <sstream>
#include <iostream>

#define LOG( LEVEL, TITLE ) \
if ( int x_level = (LEVEL) ) \
if ( Logger lout = x_level ) \
if ( lout.Title(TITLE) )
// end

struct LoggerContext
{
std::ostringstream m_oss;
int m_level;
mutable int m_count;

LoggerContext( int l_level )
: m_level( l_level ),
m_count( 1 )
{
}

};

struct Logger
{
LoggerContext * m_context;

static int min_level;

Logger( int l_level )
: m_context( l_level >= min_level ? new LoggerContext( l_level )
: 0 )
{
}

bool Title( const char * l_title )
{
m_context->m_oss << l_title << " : ";
return m_context;
}

template <typename T>
Logger & operator << ( const T & value )
{
m_context->m_oss << value;
return * this;
}

Logger & attr( const char * s_attr )
{
m_context->m_oss << " " << s_attr << " = ";
return * this;
}

~Logger()
{
if ( m_context )
{
-- m_context->m_count;
if ( m_context->m_count == 0 )
{
m_context->m_oss << "\n";
/// write log here
std::cout << m_context->m_oss.str();
delete m_context;
}
}
}

operator bool()
{
return m_context;
}

Logger( const Logger & l_rhs )
: m_context( l_rhs.getref() )
{
}

LoggerContext * getref() const
{
++ ( m_context->m_count );
return m_context;
}
};
int Logger::min_level = 2;
int main()
{
LOG( 3, "Thing 1" );

LOG( 4, "Thing 2" )
{
lout << "Really " << 33;
lout.attr( "Some value" ) << "54";
lout.attr( "Some other value" ) << 99.33;
}

LOG( 1, "Thing 3" )
{
lout << "Not really";
}

}




所有你需要做的就是这样:


// log.h

#ifdef LOG_ON

#define LOGNAME" debuglog.txt"

#定义LOG(_S_){lstream<< _S_; }

extern std :: ofstream lstream;

#else

#define LOG(_S_)

#endif


//////////////////

// log.cpp

#include" log.h"

#ifdef LOG_ON

#include< fstream>

std :: ofstream lstream(LOGNAME) ;

#endif

// somefile.cpp

#include" log.h"

void func (int n)

{

LOG(" func with"<<<<<< std :: endl);

}

你需要做的就是开启/关闭日志记录定义(或不​​关闭

日志记录)LOG_ON

-Chris



all you have to do is somehting like this:

// log.h
#ifdef LOG_ON
#define LOGNAME "debuglog.txt"
#define LOG( _S_) { lstream << _S_; }
extern std::ofstream lstream;
#else
#define LOG( _S_)
#endif

//////////////////
// log.cpp
#include "log.h"
#ifdef LOG_ON
#include <fstream>
std::ofstream lstream( LOGNAME );
#endif
// somefile.cpp
#include "log.h"
void func( int n )
{
LOG( "func called with " << n << std::endl );
}
all you have to do to turn logging on/ off is define ( or not, to turn off
logging ) LOG_ON

-Chris


这篇关于如何登录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆