onlinegdb online c++ debugging

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; }