onlinegdb - online gdb c++
C++ habilita/deshabilita los mensajes de depuraciĆ³n de std:: couts sobre la marcha (9)
Algunas bibliotecas de registro son bastante pesadas a menos que tenga necesidades de registro complejas. Aquí hay algo que acabo de golpear juntos. Necesita un poco de prueba, pero podría cumplir con sus requisitos:
#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;
}
¿Hay una manera de definir / undefine mensajes de depuración usando std :: cout siempre dentro de un programa?
Soy consciente de que hay cosas como #define, #ifndef, pero estaba pensando que hay una forma más limpia de decir una variable:
# debug ON
Eso imprime todos mis datos de depuración (usando std :: cout). En consecuencia, tendremos un código como este para la depuración:
#ifndef DEBUG
// do something useful
#endif
Encuentro el código anterior engorroso cuando escribes 100s de código de depuración.
¡Gracias!
Carlo
Aunque la pregunta es antigua y hay algunas buenas respuestas, también quiero publicar una solución para esto. Es como el enfoque de Giannis pero diferente. Y también, usé std :: cerr en lugar de std :: cout, pero puedes cambiar esto realmente rápido.
#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";
};
Ahora puedes usarlo como un flujo de salida.
Nota: iostream
solo se incluye si se usa cerr
. Esto reducirá la cantidad de inclusión si aún no lo tiene incluido. Si DEBUG
está definido, cerr
se utiliza para imprimir el error. De lo contrario, una clase vacía log_disabled_output
se log_disabled_output
una instancia estática y el operator<<
se sobrecarga a cualquier tipo. La cosa aquí es; Si deshabilita el registro, un compilador inteligente notará que no hay nada que hacer con la transmisión y que se optimizará la "línea" completa, por lo que no tendrá ningún gasto DEBUG
si DEBUG
está deshabilitado.
Estaba buscando un ejemplo similar y compartiendo mi ejemplo a continuación:
#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;
}
Mejores sugerencias son siempre bienvenidas.
Estaba tratando de hacer lo mismo. Después de algunas investigaciones, desarrollé lo siguiente, y parece funcionar. Por favor comenta si ves algo mal.
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;
}
Esto es lo que usé (trabajado con VC ++) - aquí se usa "##" para la concatenación
#ifdef DEBUG
#define pout cout
#else
#define pout / ## / cout
#endif
Para otros compiladores usa esto:
#ifdef DEBUG
#define pout cout
#else
#define pout 0 && cout
#endif
Uso
pout << "hello world" << endl;
Otra solución simple, consiste en abrir una referencia std::ostream
para cout
en modo de depuración, y /dev/null
en modo de no depuración, así:
En debug.h:
extern std::ostream &dout;
En debug.c
#ifdef DEBUG
std::ostream &dout = cout;
#else
std::ofstream dev_null("/dev/null");
std::ostream &dout = dev_null;
#endif
Y entonces:
dout << "This is a debugging message";
Por supuesto, esto solo funcionaría en cualquier sistema donde /dev/null
apunte a un dispositivo nulo. Como la referencia de dout
es global aquí, le gustaría mucho cout
. De esta manera, puede apuntar la misma secuencia a varias secuencias de salida, por ejemplo, a un archivo de registro, dependiendo del valor de las marcas de depuración, etc.
Probablemente no. Recomendaría el uso de una biblioteca de registro. Ya no estoy seguro de cuál es la mejor opción para C ++, pero en el pasado usé log4cpp y lo encontré bastante bien.
EDITAR: Supongo que al vuelo significa @ runtime. Si solo necesita que sea un indicador de tiempo de compilación, entonces la respuesta de Gianni es probablemente la más fácil de implementar. Sin embargo, las bibliotecas de registro le dan mucha flexibilidad y permiten la reconfiguración en tiempo de ejecución.
Una cosa limpia para hacer sería usar cerr.
"cerr" actúa esencialmente como "cout", pero siempre vacía la salida (por cierto, útil para la depuración). Si necesita eliminar todos los mensajes, puede comentar todos los mensajes de cerr con un simple buscar y reemplazar (cerr in // cerr).
Probablemente hay formas incluso mejores de usar cerr y desactivarlo limpiamente (que se escribe en una secuencia especial, la secuencia de error, de ahí el nombre). Espero que esto ayude.
#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;
}