IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

tableau comme argument à vsprintf


Sujet :

C

  1. #1
    Futur Membre du Club
    Inscrit en
    Mars 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 11
    Points : 7
    Points
    7
    Par défaut tableau comme argument à vsprintf
    Je cherche à construir un buffeur pour une requete SQL et je ne connais pas le nombre d'arguments que je doit passer.
    EXEMPLE, SI j'ai un nombre d'argument fixe, je fait :
    char param1[12], param2[12];
    char *format="UPDATE t_table set col1='%s', col2='%s'";
    ......
    sprintf(buff,format,param1,param2);

    Mais dans le cas present je ne sait pas quelles colonnes seront mise a jour,
    Je construis ma chaine "UPDATE .." par concatenation avec les colonnes necessaires;
    char format[100]="UPDATE t_table set "; int i=0;
    char *param[8];
    if( bon1 ){ strcat( fromat," col1='%s',"); param[i++]=param1;}
    if( bon2 ){ strcat( fromat," col2='%s',"); param[i++]=param2;}
    ..
    vsprintf( buff,format,param);
    ET ça sa ne marche pas vsprintf veut un va_list pour troisième argument.
    Mon problème est donc de donner un tableau à "v/sprintf" plutot qu'une liste en troisieme argument.
    @+

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Pour des paramètres tous de même type, il me semble qu'une va_list est considérable comme un tableau de paramètres de ce type.
    (enfin, un pointeur vers un tableau).

    Je pense que tu peux sans risque remplir un tableau à partir de la seconde case et donner en paramètre à la macro va_start la première case du tableau (la macro prendra son adresse).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Futur Membre du Club
    Inscrit en
    Mars 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 11
    Points : 7
    Points
    7
    Par défaut marche pas
    Et non ...
    tous mes parametres sont des string mais si je mets :
    va_start(ap, param[0]); /*ou va_start(ap, param); */

    -> erreur à la compilation : "symbole non defini : ... "
    je crois que les "..." correspondent aux ... donnés en 2eme parametre à une fonction dont le nombre d'arguments est variable.

    ap est bien declaré en va_list.

    @+

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut

    Quelle plate-forme ?

    Sous Visual, j'ai une def qui marche:
    Code vadefs.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #ifdef  __cplusplus
    #define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )
    #else
    #define _ADDRESSOF(v)   ( &(v) )
    #endif
     
    #define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
     
    #define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
    Code stdarg.h : Sélectionner tout - Visualiser dans une fenêtre à part
    #define va_start _crt_va_start
    Mon code de test compile et s'exécute parfaitement après avoir inclus stdarg.h :
    Code test.c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    char const * param[8];
    param[0] = NULL;
    param[1] = "Blabla";
    param[2] = "Test";
    param[3] = NULL;
    va_list vl;
    va_start(vl, param[0]);
     
    char const *str;
    while((str = va_arg(vl, char const*)) != NULL)
    	puts(str);
    va_end(vl);
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Futur Membre du Club
    Inscrit en
    Mars 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Non toujours pas.
    Je dois faire le programme en C pour LINUX, compilateur gcc.

    J'ai essayé :
    avec va_start mais tourjours impossible de compiler cause de ...

    sans va_start en donnant le tableau de strings en argument à vsprintf, ça compile mais j'ai une Memory fault. Meme en mettant *param[dernier]=NULL
    Sauf si je mais *param[0]=NULL mais le buffeur n'a que "format"
    @+

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Tu as raison, avec gcc version 2.95.4 20020320 [FreeBSD], j'ai ces erreurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    testVaList.c: In function `main':
    testVaList.c:13: `va_start' used in function with fixed args
    Pareil avec version gcc 3.4.5 20051201 (Red Hat 3.4.5-2)

    Ce doit être le problème montré dans l'aide de microsoft: GCC n'utilise pas les va_list ANSI, mais ses propres va_list spéciales pour unixoïdes...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Dans ce cas, je suis désolé, je ne connais pas de manière portable de créer une va_list UNIX à partir de données personnelles.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Ya plus qu'a faire son propre *printf()

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Quand on pense qu'ils n'ont même pas de fonction/macro pour initialiser une va_list à partir d'autre chose que des arguments.
    Avec quoi est-on censé interfacer des appels dynamiques sur cette plate-forme?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Médinoc

    Quelle plate-forme ?

    Sous Visual, j'ai une def qui marche:
    ...
    Mon code de test compile et s'exécute parfaitement après avoir inclus stdarg.h :
    Ce code fonctionne très bien sous linux/x86 aussi, moyennant une adaptation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    #include <stdarg.h>
    #include <stdlib.h>
     
    #ifdef __cplusplus
    #define _ADDRESSOF(v) ( &reinterpret_cast<const char &>(v) )
    #else
    #define _ADDRESSOF(v) ( &(v) )
    #endif
     
    #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    #define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
     
    #ifdef va_start
    #undef va_start
    #endif
    #define va_start _crt_va_start
     
    int main() {
     char * param[8];
     param[0] = "to";
     param[1] = "Blabla";
     param[2] = "Test";
     param[3] = NULL;
     va_list vl;
     
     va_start(vl, param[0]);
    #if 1
     vprintf("%s => %s %d",vl);
    #else
     char const *str;
     
     while((str = va_arg(vl, char const*)) != NULL)
             puts(str);
     
    #endif
     va_end(vl);
    }
    ou autre possibilité moins portable:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <stdlib.h>
     
    #ifdef __cplusplus
    #define _ADDRESSOF(v) ( &reinterpret_cast<const char &>(v) )
    #else
    #define _ADDRESSOF(v) ( &(v) )
    #endif
     
    #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    #define __builtin_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
     
    #include <stdarg.h>
    Malgrès tout je ne saurais que trop vous déconseiller ce genre de pratique.
    Ces méthode ne sont absolument pas portable (ie ne fonctionneront pas sur
    d'autre plate-forme que du Intel x86), la gestion des arguments passés à
    une fonction étant différente d'une plateforme matérielle à une autre.

  11. #11
    Futur Membre du Club
    Inscrit en
    Mars 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 11
    Points : 7
    Points
    7
    Par défaut Fin
    Si si ça marche ! Meme sous Linux

    Et meme ça sa mache
    if( bon1 ){ strcat( fromat," col1='%s',"); param[i++]=param1;}
    if( bon2 ){ strcat( fromat," col2='%s',"); param[i++]=param2;}
    param[i]=NULL;
    ..
    vsprintf( buff,format,(va_list) param);

    Un simple recastage.
    Dans mon cas j'ai que des strings c'est plus simple.

    Juste une précision :
    (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1)
    c'est dans quel but ?

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est parce que la taille minimale d'un paramètre sur la pile, c'est celle d'un int (en fait, c'est arrondi au int supérieur).
    void f(char a, char b) aura ses paramètres sur 8 octets comme si c'était des int.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. passage d'un tableau comme argument d'une fonction
    Par arwen76 dans le forum Langage
    Réponses: 8
    Dernier message: 06/02/2015, 09h58
  2. Macro Word depuis Excel avec tableau comme argument
    Par emorejbleu dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 24/07/2013, 14h45
  3. Passer un tableau comme argument
    Par sinfos dans le forum Tcl/Tk
    Réponses: 1
    Dernier message: 19/02/2009, 09h29
  4. Réponses: 4
    Dernier message: 28/11/2006, 09h50
  5. fonction renvoyant un tableau en argument
    Par Jones dans le forum Langage
    Réponses: 6
    Dernier message: 30/09/2002, 18h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo