2010-03-10 20 views
6

Digamos que quiero hacer algo como estoC, que trata de las funciones de argumentos variables

void my_printf(char *fmt,...) { 
char buf[big enough]; 
sprintf(buf,fmt,...); 
} 

¿Cuál es la forma correcta de pasar el número variable de argumentos directamente a una función con argumentos acepta variables?

+0

¿Cómo vas a saber que el buffer es lo suficientemente grande? Y realmente debe devolver el número de conversiones realizadas por sprintf(), de lo contrario, los usuarios no tienen forma de saber que la función funcionó. –

+0

Rayé todo lo que no era esencial para ilustrar mi punto. Obviamente, en mi código de publicación soy mucho más completo :) – Mike

Respuesta

9

sprintf tiene un formulario va_list llamado vsprintf. Pase el va_list que construye localmente como último argumento.

void my_printf(char *fmt,...) { 
va_list ap; 
va_start(ap, fmt); 

char buf[big enough]; 
vsprintf(buf,fmt,ap); 

va_end(ap); 
} 
+3

El encabezado operativo es ''. –

+0

Si está disponible, debe usar 'vsnprintf'. –

1

no estoy seguro de lo útil será este código, ya que es C++, pero muestra cómo comprobar, utilizando un vsnprintf función específica Win32(), que el búfer asignado es lo suficientemente grande y si no se asigna uno más grande. Y devuelve una cadena std ::, por lo que tendría que usar malloc/realloc para manejar eso. Pero qué demonios:

string Format(const char * fmt, ...) { 
    const int BUFSIZE = 1024; 
    int size = BUFSIZE, rv = -1; 
    vector <char> buf(size); 
    do { 
     va_list valist; 
     va_start(valist, fmt); 
     // if vsnprintf() returns < 0, the buffer wasn't big enough 
     // so increase buffer size and try again 
     rv = _vsnprintf(&buf[0], size, fmt, valist); 
     va_end(valist); 
     size *= 2; 
     buf.resize(size); 
    } 
    while(rv < 0); 
    return string(&buf[0]); 
} 
-1

Puede usar las funciones de estilo vsprintf para obtener la impresión de estilo de impresión para su parámetro de longitud variable. Sin embargo, no hay requisito para hacerlo. Puede, si elige, escribir su función para seguir aceptando parámetros hasta que encuentre un puntero nulo.

va_list ap; 
char *param; 
va_start(ap,fmt); 
param = va_arg(ap,char*); 
while(param) 
{ 
do something... 
param = va_arg(ap,char*); 
} 

o puede hacer que el número de parámetros que el primer parámetro a la función

void my_printf(int param_num,...) 
{ 
va_list ap; 
char *param; 
va_start(ap,fmt); 
while(param_num) 
{ 
do something... 
param = va_arg(ap,char*); 
param_num--; 
} 

} 

Es realmente depende de ti, las posibilidades son ilimitadas. Creo que el único requisito real para las elipses es que tiene al menos un parámetro antes de las elipsis.

+0

requiriendo que el usuario especifique el número de parámetros sería una catástrofe de diseño – Mike

+1

mi punto es el ... no está encasillado en un cierto uso. El usuario de la función puede decidir qué es lo mejor para su situación. Pasar el número de parámetros no es diferente de tener el número incrustado en una cadena ... es decir, sprintf ("% d% d", a, b) es lo mismo que yourprintf (2, a, b), sprintf es tan propenso a error del usuario. – Medran

Cuestiones relacionadas