c++ - programacion - Pasar argumentos variables a otra función que acepte una lista de argumentos variables
paso de parametros en c (7)
Basándome en el comentario de que estás vsprintf
, y que esto está etiquetado como C ++, te sugiero que no trates de hacer esto, sino que cambies tu interfaz para usar iostreams de C ++. Tienen ventajas sobre la línea de print
de funciones, como seguridad de tipo y poder imprimir elementos que printf
no podría manejar. Algunas modificaciones ahora podrían ahorrar una gran cantidad de dolor en el futuro.
Entonces tengo 2 funciones que tienen argumentos similares
void example(int a, int b, ...);
void exampleB(int b, ...);
Ahora el example
llama al example
exampleB
, pero ¿cómo puedo pasar las variables en la lista de argumentos variables sin modificar el exampleB
(ya que esto ya se usa en otros lugares)?
Incidentalmente, muchas implementaciones de C tienen una variación de v / printf interna que en mi humilde opinión debería haber sido parte del estándar de C. Los detalles exactos varían, pero una implementación típica aceptará una estructura que contenga un puntero de función de salida de caracteres e información que diga lo que se supone que sucederá. Esto permite que printf, sprintf y fprintf utilicen el mismo mecanismo ''core''. Por ejemplo, vsprintf podría ser algo así como:
void s_out(PRINTF_INFO *p_inf, char ch) { (*(p_inf->destptr)++) = ch; p_inf->result++; } int vsprintf(char *dest, const char *fmt, va_list args) { PRINTF_INFO p_inf; p_inf.destptr = dest; p_inf.result = 0; p_inf.func = s_out; core_printf(&p_inf,fmt,args); }
La función core_printf llama a p_inf-> func para cada carácter que se va a producir; la función de salida puede enviar los caracteres a la consola, un archivo, una cadena u otra cosa. Si la implementación de uno expone la función core_printf (y cualquier mecanismo de configuración que utilice), se puede ampliar con todo tipo de variaciones.
No puedes hacerlo directamente; tienes que crear una función que tome una va_list
:
#include <stdarg.h>
static void exampleV(int b, va_list args);
void example(int a, int b, ...)
{
va_list args;
va_start(args, b);
exampleV(b, args);
va_end(args);
}
void exampleB(int b, ...)
{
va_list args;
va_start(args, b);
exampleV(b, args);
va_end(args);
}
static void exampleV(int b, va_list args)
{
...whatever you planned to have exampleB do...
...except it calls neither va_start nor va_end...
}
Tal vez tirar una piedra en un estanque aquí, pero parece funcionar bastante bien con las plantillas variadas de C ++ 11:
#include <stdio.h>
template<typename... Args> void test(const char * f, Args... args) {
printf(f, args...);
}
int main()
{
int a = 2;
test("%s/n", "test");
test("%s %d %d %p/n", "second test", 2, a, &a);
}
Por lo menos, funciona con g++
.
También quería envolver printf y encontré una respuesta útil aquí:
Cómo pasar el número variable de argumentos a printf / sprintf
No me interesaba en absoluto el rendimiento (estoy seguro de que este fragmento de código se puede mejorar de varias maneras, no dudes en hacerlo :)), esto es solo para la depuración general, así que hice esto:
//Helper function
std::string osprintf(const char *fmt, ...)
{
va_list args;
char buf[1000];
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args );
va_end(args);
return buf;
}
que luego puedo usar así
Point2d p;
cout << osprintf("Point2d: (%3i, %3i)", p.x, p.y);
instead of for example:
cout << "Point2d: ( " << setw(3) << p.x << ", " << p.y << " )";
Los ostreams de c ++ son hermosos en algunos aspectos, pero prácticamente se vuelven horribles si quieres imprimir algo como esto con algunas cadenas pequeñas como paréntesis, dos puntos y comas insertadas entre los números.
Usando el nuevo estándar C ++ 0x, puede hacer esto usando plantillas variadic o incluso convertir ese código antiguo a la sintaxis de plantilla nueva sin romper nada.
deberías crear versiones de estas funciones que toman una va_list y las pasan. Mira vprintf
como un ejemplo:
int vprintf ( const char * format, va_list arg );