2015-08-10 3 views
1

J'essaye d'écrire une enveloppe autour de la fonction vfprintf mais avec l'exigence que je veux ajouter un préfixe au spécificateur de format et puis passer le nouveau spécificateur de format à vfprintf.Comment écrire un wrapper vfprintf qui ajoute un préfixe à un spécificateur de format et passe le nouveau spécificateur de format à vfprintf dans C89?

Maintenant, je ne sais pas comment faire cela, mais j'ai capturé mon intention dans le code suivant.

#include <stdio.h> 
#include <stdarg.h> 

void err(const char *format, ...) 
{ 
    va_list args; 
    va_start(args, format); 
    vfprintf(stderr, "foo: error:" format, args); 
    va_end(args); 
} 

int main() 
{ 
    err("%s: %d\n", "Transaction failed with error code", 42); 
    return 0; 
} 

Vous pouvez voir dans le code ci-dessus, que je veux préfixe "foo: error" au spécificateur de format et de passer ensuite à vprintf. Ce code, bien sûr, conduirait à une erreur de compilation car ce code n'est pas valide. Cela capture seulement mon intention de ce que j'essaye d'accomplir.

[email protected]:~/lab/c$ gcc -std=c89 -Wall -Wextra -pedantic vfprintf-wrapper.c 
vfprintf-wrapper.c: In function ‘err’: 
vfprintf-wrapper.c:8:36: error: expected ‘)’ before ‘format’ 
    vfprintf(stderr, "foo: error:" format, args); 
            ^
vfprintf-wrapper.c:8:5: error: too few arguments to function ‘vfprintf’ 
    vfprintf(stderr, "foo: error:" format, args); 
    ^

Pouvez-vous m'aider à écrire ce code correctement?

+2

Cela ressemble à une chose inutilement compliquée à faire. Pourquoi ne pas simplement imprimer le préfixe d'erreur dans une instruction séparée à l'intérieur du wrapper, puis appeler vprintf tel quel? –

+0

@ n.m. C'est une manière parfaitement valide de faire les choses, cependant, je veux apprendre si ce que je demande est possible et comment le faire. –

+1

Bien sûr, c'est possible. Il suffit de créer une nouvelle chaîne de format (malloc et un couple de strcpys le feraient). Mais ce n'est probablement pas la solution la plus efficace. – rici

Répondre

4

Votre pseudo vfprintf(stderr, "foo: error:" format, args); doit être:

fprintf(stderr, "foo: error:"); 
vfprintf(stderr, format, args); 

Vous semblez être indiquer que vous voulez éviter l'appel « extra » fprintf. Si c'est le cas, vous pouvez le faire:

char *fail = malloc(sizeof "foo: error:" + strlen(format)); 
if (!fail) 
    exit(EXIT_FAILURE); 
strcpy(fail, "foo: error:"); 
strcat(fail, format); 

vfprintf(stderr, fail, args); 

free(fail); 

mais ce serait une perte de temps et de ressources.

+0

Il semble dommage d'écrire 'if (! Fail) exit (EXIT_FAILURE);' - si vous n'avez pas échoué, quittez avec l'échec. Peut-être un meilleur choix de nom de variable serait msg_format, ou msgfmt ou quelque chose comme ça. –

+0

Oh, vous avez hérité du nom 'prog' de l'ancienne version de la question. Je pense que c'est juste un intrus, ou devrait être interpolé dans le format en tant que partie de la chaîne: 'char * msgfmt = malloc (sizeof (": erreur: ") + strlen (prog) + strlen (format); sprintf (msgfmt , "% s: erreur:% s", prog, format); vfprintf (stderr, msgfmt, args); '(ignorant la vérification d'erreur nécessaire après' malloc() '). –

+0

@JonathanLeffler oups, j'ai lu ça de son messages d'erreur et ne correspond pas au code réel (qui ne correspond pas comme vous le dites). Ouais, 'fail 'est un nom stupide pour une variable pointeur, qui était intentionnelle .. :) –