2010-03-10 6 views
6

Disons que je veux faire quelque chose comme çaC, avec des fonctions Traiter arguments variables

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

Quelle est la bonne façon de passer le nombre variable d'arguments directement à une fonction avec accepte des arguments variables?

+0

Comment allez-vous savoir que le tampon est assez grand? Et vous devriez vraiment retourner le nombre de conversions effectuées par sprintf(), sinon les utilisateurs n'ont aucun moyen de connaître la fonction travaillée. –

+0

J'ai rayé tout ce qui n'était pas essentiel pour illustrer mon propos. Évidemment dans mon code de version je suis beaucoup plus approfondie :) – Mike

Répondre

9

sprintf a une forme va_list appelée vsprintf. Passez le va_list que vous construisez localement comme dernier argument.

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

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

va_end(ap); 
} 
+3

L'en-tête opérationnel est ''. –

+0

Si c'est disponible, vous devriez utiliser 'vsnprintf'. –

1

Je ne sais pas comment ce code utile sera, comme il est C++, mais il montre comment vérifier, à l'aide d'une vsnprintf fonction spécifique Win32(), que le tampon alloué est assez grand et sinon alloue un plus grand. Et il renvoie une chaîne std ::, donc vous devrez utiliser malloc/realloc pour gérer cela. Mais que diable:

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

Vous pouvez nous les fonctions de style vsprintf pour obtenir l'impression de style printf pour votre paramètre de longueur variable. Cependant, il n'y a pas besoin de le faire. Vous pouvez si vous choisissez écrire votre fonction pour continuer à accepter les paramètres jusqu'à ce qu'il rencontre un pointeur nul.

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

ou vous pouvez avoir le nombre de paramètres comme la première à votre fonction param

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

} 

Son vraiment à vous, les possibilités sont illimitées. Je pense que la seule exigence réelle pour les ellipses est qu'il y ait au moins un paramètre avant les ellipses.

+0

nécessitant l'utilisateur de spécifier le nombre de paramètres serait une catastrophe de conception – Mike

+1

mon point est le ... n'est pas pigeon troué dans un certain usage. L'utilisateur de la fonction peut décider ce qui convient le mieux à sa situation. Transmettre le nombre de paramètres n'est pas différent que d'avoir le nombre incorporé dans une chaîne ... ie sprintf ("% d% d", a, b) est juste le même que tonprintf (2, a, b), sprintf est tout aussi sujet à une erreur de l'utilisateur. – Medran

Questions connexes