[C con Clase] Macro para gestionar errores
Steven Davidson
srd4121 en njit.edu
Mie Mar 4 18:44:55 CET 2009
Hola Vicente,
vicente lozano wrote:
> Ok, gracias por contestar.
>
> El porque define es porque vengo de C y aun no habia llegado a las
> constantes jeje.
>
> perror y sterror no las conocia aun, pero aun asi es para gestionar
> mis propios errores en las funciones.
>
> Por otro lado, para que los mensajes de error puedan ser en
> diferentes idiomas existe algo o hay que hacerlo asi?
>
Hay varias formas de hacer esto. Puedes usar directivas del
precompilador para modificar tu código fuente. Por ejemplo,
// errores.h
#ifdef ERRORES_ENG
const char *ERRORS[] = { "Opening file", "Writing file",
"Creating Socket",...};
#else
#ifdef ERRORES_ESP
const char *ERRORS[] = { "Abriendo fichero", "Escribiendo fichero",
"Creando Socket",...};
#else
#ifdef ERRORES_FRA
const char *ERRORS[] = { "Ouvrant fichier", "Fermant fichier",
"Créant Socket",...};
#else
...
#else // Por defecto, español
#define ERRORES_ESP
const char *ERRORS[] = { "Abriendo fichero", "Escribiendo fichero",
"Creando Socket",...};
#endif
En tu código fuente, #define la constante simbólica que te interese. Por
ejemplo,
// main.cpp
// Elegimos inglés para los mensajes de errores
#define ERRORES_ENG
#include "errores.h"
...
Claro está, no puedes cambiar el idioma una vez compilado tu programa.
Si quieres mayor control, entonces usa punteros. Por ejemplo,
// main.cpp
const char *ERRORS_ENG[] = { "Opening file", "Writing file",
"Creating Socket",...};
const char *ERRORS_ESP[] = { "Abriendo fichero", "Escribiendo fichero",
"Creando Socket",...};
const char *ERRORS_FRA[] = { "Ouvrant fichier", "Fermant fichier",
"Créant Socket",...};
...
// Español, por defecto
const char **ERRORS = ERRORS_ESP;
El resto del código fuente usa el puntero 'ERRORS'. Si quieres cambiar
el idioma, simplemente, cambia el valor de 'ERRORS' para "apuntar" a
otro array de cadenas de caracteres. Por ejemplo,
if( <francés> ) ERRORS = ERRORS_FRA;
Todo lo demás sigue igual.
Otra solución es parecida a esta última, pero en lugar de escribir la
información en el propio código fuente, lo hacemos en un fichero de
texto. Luego, nuestro programa carga esta información en el array de
cadenas según la configuración que tenemos. Por ejemplo,
bool CargarMensajes( const char *szErrores[], const char szFichero[] );
...
char ERRORS[10][128]={0};
// Cargar mensajes en español
CargarMensajes( ERRORS, "errores_esp.txt" );
...
if( <francés> ) CargarMensajes( ERRORS, "errores_fra.txt" );
La función 'CargarMensajes()' se encargará de leer las cadenas del
fichero indicado - si puede - y copiarlas al array de cadenas dado.
> Gracias y perdonar por mi desconocimiento de las librerias, me pasa
> mucho lo de pensar algo, ponerme a hacerlo y luego descubrir que
> existe alguna funcion de libreria que podia haber usado. Espero que
> el capitulo de librerias me ayude a solucionar ese "problemilla"
>
Bueno, al menos así aprendes todos los detalles de cualesquier temas. A
veces viene bien hacer las cosas uno mismo, pero otras veces no.
Como ha dicho Ferrán, es mejor usar funciones en línea agregando el
vocablo 'inline' como prefijo a la declaración o definición de la
función. Si quieres usar una macro, aconsejo reescribirlo de esta manera:
#define check(cond,errn)\
( -1==cond ? fprintf(stderr, "ERROR: %s.\n", ERRORS[errn]) : -1 )
Ten mucho cuidado con macros y sus #definiciones. Las macros no son
funciones. Pensar así es la causa de errores y de muchos quebraderos de
cabeza. Por esta razón, en C++ usamos funciones 'inline' por la
oportunidad de optimizar la función como una macro.
Espero haber aclarado las dudas.
Steven
Más información sobre la lista de distribución Cconclase