2010-09-22 5 views
34

¡Hola!Agregar mensaje para afirmar

Estoy buscando una manera de agregar mensajes personalizados para afirmar declaraciones. Encontré estas preguntas Add custom messages in assert? pero el mensaje es estático allí. Quiero hacer algo como esto:

assert((0 < x) && (x < 10), std::string("x was ") + myToString(x)); 

Cuando la afirmación falla, quiero la salida normal más, por ejemplo, "x era 100".

+5

Creo que aquí tiene mejor [respuesta] (http://stackoverflow.com/questions/3692954/add-custom-messages-in-assert) –

+2

Ugly hack: 'if (fail_condition) assert (!" Mi mensaje ");' –

+0

@MarkKCowan, creo que tu "hack feo" es mucho mejor que el parche "&&", porque solo muestra el mensaje :) – NL628

Respuesta

60

Te has quedado sin suerte aquí. La mejor manera es definir su propia macro assert.

Básicamente, se puede tener este aspecto:

#ifndef NDEBUG 
# define ASSERT(condition, message) \ 
    do { \ 
     if (! (condition)) { \ 
      std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \ 
         << " line " << __LINE__ << ": " << message << std::endl; \ 
      std::terminate(); \ 
     } \ 
    } while (false) 
#else 
# define ASSERT(condition, message) do { } while (false) 
#endif 

Esto va a definir la macro ASSERT sólo si el no-debug macro NDEBUG no está definido.

A continuación, tendrá que utilizar de esta manera:

ASSERT((0 < x) && (x < 10), "x was " << x); 

que es un poco más simple que el uso ya que no es necesario stringify "x was " y x explícitamente, esto se hace implícitamente por la macro.

+4

¿Por qué do {} while (false)? – tauran

+4

@tauran: para que pueda poner un punto y coma después de la macro cuando lo use. –

+0

¿Por qué no un 'do {} while (false)' para el caso '# else'? ;-) También suele ser útil para mostrar el código fuente de la aserción cifrada '# condition'. Estrictamente, EXIT_FAILURE debería ser preferido sobre 1 también. +1 mientras se perfila como la mejor respuesta. –

6
#define ASSERT_WITH_MESSAGE(condition, message) do { \ 
if (!(condition)) { printf((message)); } \ 
assert ((condition)); } while(false) 
7

Una mejor alternativa es enseñar el depurador se detenga en la aserción cuando falla, entonces se podría examinar no sólo el valor de x pero cualquier otra información, incluyendo la pila de llamadas. Tal vez, esto es lo que realmente estás buscando. aplicación de la muestra se menciona aquí Ways to show your co-programmers that some methods are not yet implemented in a class when programming in C++

+0

+1 No es lo que busqué, pero podría ser realmente útil algún día. – tauran

2

En aras de la exhaustividad, publicó una gota en 2 archivos afirman aplicación macro en C++:

#include <pempek_assert.h> 

int main() 
{ 
    float min = 0.0f; 
    float max = 1.0f; 
    float v = 2.0f; 
    PEMPEK_ASSERT(v > min && v < max, 
       "invalid value: %f, must be between %f and %f", v, min, max); 

    return 0; 
} 

le pedirá con:

Assertion 'v > min && v < max' failed (DEBUG) 
    in file e.cpp, line 8 
    function: int main() 
    with message: invalid value: 2.000000, must be between 0.000000 and 1.000000 

Press (I)gnore/Ignore (F)orever/Ignore (A)ll/(D)ebug/A(b)ort: 

Donde

  • (I) gnore: ignore la afirmación actual
  • Ignorar (F) orever: recordar el archivo y la línea en la que la afirmación despedido y ignoran para la ejecución restante del programa
  • Ignorar (A) ll: ignorar todas las afirmaciones restantes (todos los archivos y líneas)
  • (D) ebug: interrumpir el depurador si los hay, de lo contrario abort() (en Windows, el sistema pedirá al usuario asociar un depurador)
  • a (b) ORT: llamar abort() inmediatamente

Usted puede averiguar más al respecto hay:

espero que ayude.

7

Hay algunos trucos viejos para incluir mensajes sin necesidad de escribir sus propias rutinas:

La primera es la siguiente:

bool testbool = false; 
assert(("this is the time", testbool)); 

También hay:

bool testbool = false; 
assert(testbool && "This is a message"); 

El primero se trabaja, porque el resultado de la expresión de parens interna es el valor de 'testbool'. El segundo funciona, porque el valor de la cadena va a ser distinto de cero.

0

estar de acuerdo con la respuesta de Konrad Rudolf que puede hacerlo un poco más conciso con

#include <assert.h> 
#include <stdio.h> 
#define ASSERT(condition,...) assert(\ 
    condition|| \ 
    (fprintf(stderr,__VA_ARGS__)&&fprintf(stderr," at %s:%d\n",__FILE__,__LINE__)) \ 
); 

que también funciona en C,

funciona usando la idea general de algunas de las respuestas a la pregunta enlazó, pero la macro le permite ser un poco más flexible

Cuestiones relacionadas