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 :

Problème avec va_arg


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut Problème avec va_arg
    Bonjour,

    J'utilse une fonction à taille variable d'arguments et je désire afficher sous forme de string l'ensemble de mes variables présentes. Je précise aussi que les variables récupérées sont censées être de type byte, word ou longword.

    J'ai un gros soucis avec la fonction va_arg(argList,char*) qui retourne soit rien soit (null).

    Dans le code que je vous joins, j'ai tenté deux méthodes:
    1) Utiliser la fonction vsprintf
    2) Lire chaque variable sous forme d'entier, convertir en format string, puis concaténer dansune unique chaine l'ensemble de ses variables.

    L'affichage de la variable avec la fonction va_arg(argList,int) est complètement différent de va_arg(argList,char*) , pourquoi?

    Code d'appel de la fonction contenant va_list:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      va_list   argList;
      CString parameters = NULL;
     
      if ((gRDSFlag == 1) && (theEvent <= RDS_FormerMaxEvNum))
      {  
      /*Routine to save info about RDS event in the circular buffer for Post Mortem file*/
        va_start(argList,theFormat);
        parameters = ParametersChain(theFormat,argList);
        va_end(argList);
     
        SaveRdsEvPostMortem(theEvent, theClass, theSubcode, theFormat, parameters);
      }
    Code de la fonction ParametersChain(theFormat,argList);
    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
     
    char* ParametersChain(CString theFormat, va_list argList)
    {
      char* parameters = NULL;
      char* nextParameter = NULL;
     
      /*To get parameters from the format variable*/
      if(theFormat == NULL ){
        parameters = "None";
      }
      else{    	
        /*méthode1: utiliser vsprintf et se passer de la boucle while*/
        vsprintf(parameters,theFormat,argList);
        printf("vsprintf chaine: %s\n", parameters);
     
        /* Get and add each param except the last one to the event */
        /*méthode2: récupérer sous forme de chaine chaque variable et concaténer*/
        while (*theFormat != '\0') {
          printf("chaine: %s\n", va_arg(argList, char*)); /*Ne marche pas*/
     
          sprintf(nextParameter, "%x", va_arg(argList, int)); 
     
          sprintf(parameters,"%s%s%s%s",parameters,"0x",nextParameter,"  ");
     
          printf("parameters = %s,  %d \n",parameters,va_arg (argList, int));
     
          /* advance to the next format character */
          theFormat++;
        }
     
      va_end(argList);
      printf("parameters chain = %s\n\n", parameters);
      } /* has param */
     
      return "nico"/*parameters*/;
    }
    Et voici le résultas des printf des 3 derniers appels à cette fonction:
    vsprintf chaine: (null)
    parameters chain = (null)

    vsprintf chaine: (null)
    chaine:
    parameters = (null), 13
    parameters chain = (null)

    vsprintf chaine: (null)
    chaine: (null)
    parameters = (null), 100
    chaine: tC¦|h¦Hò©8a
    parameters = (null), 2
    chaine:
    parameters = (null), 197306752
    parameters chain = (null)
    Si vous avez des explications à ces résultats obtenus et des moyens de les résoudre?

    Merci d'avance.

  2. #2
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Juste comme cela, une autre tentative avec le code et résultat obtenu toujours suspect

    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
     
        if(theFormat == NULL ){
        	parameters = "None";
        }
        else{    	
         	/* Get and add each param except the last one to the event */
          	while (*theFormat != '\0') {
    		value = va_arg (argList, int);
    		sprintf(nextParameter, "%d", value);
    		printf("value = %d  nextParameter = %s\n", value,nextParameter);
    		sprintf(parameters,"%s%s%s%s",parameters,"0x",nextParameter,"  ");
            	/* advance to the next format character */
            	theFormat++;
          }
          va_end(argList);
          printf("parameters chain = %s\n\n", parameters);
    A remarquer que la variable nextParameter correspond à la variable value de type int convertie en string...
    value = 74 nextParameter = (null)
    parameters chain = (null)

    value = 0 nextParameter = (null)
    value = 76 nextParameter = (null)
    value = 100 nextParameter = (null)
    parameters chain = (null)

    value = 0 nextParameter = (null)
    value = 76 nextParameter = (null)
    value = 100 nextParameter = (null)
    parameters chain = (null)

  3. #3
    Membre chevronné
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Par défaut
    Hello,

    Citation Envoyé par homeostasie
    Bonjour,

    J'utilse une fonction à taille variable d'arguments et je désire afficher sous forme de string l'ensemble de mes variables présentes. Je précise aussi que les variables récupérées sont censées être de type byte, word ou longword.

    J'ai un gros soucis avec la fonction va_arg(argList,char*) qui retourne soit rien soit (null).

    Dans le code que je vous joins, j'ai tenté deux méthodes:
    1) Utiliser la fonction vsprintf
    2) Lire chaque variable sous forme d'entier, convertir en format string, puis concaténer dansune unique chaine l'ensemble de ses variables.

    L'affichage de la variable avec la fonction va_arg(argList,int) est complètement différent de va_arg(argList,char*) , pourquoi?

    Code d'appel de la fonction contenant va_list:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      va_list   argList;
      CString parameters = NULL;
     
      if ((gRDSFlag == 1) && (theEvent <= RDS_FormerMaxEvNum))
      {  
      /*Routine to save info about RDS event in the circular buffer for Post Mortem file*/
        va_start(argList,theFormat);
        parameters = ParametersChain(theFormat,argList);
        va_end(argList);
     
        SaveRdsEvPostMortem(theEvent, theClass, theSubcode, theFormat, parameters);
      }
    OK, mis à part que CString me fait penser à la classe C++ ATL/MFC de micromou. D'ailleurs la conversion de char * (que retourne ParametersChain) en CString fonctionne de part la surcharge de l'opérateur d'affectation. Mais baste, c'est du C++ pas du C.

    Citation Envoyé par homeostasie


    Code de la fonction ParametersChain(theFormat,argList);
    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
     
    char* ParametersChain(CString theFormat, va_list argList)
    {
      char* parameters = NULL;
      char* nextParameter = NULL;
     
      /*To get parameters from the format variable*/
      if(theFormat == NULL ){
        parameters = "None";
      }
      else{    	
        /*méthode1: utiliser vsprintf et se passer de la boucle while*/
        vsprintf(parameters,theFormat,argList);
        printf("vsprintf chaine: %s\n", parameters);
     
        /* Get and add each param except the last one to the event */
        /*méthode2: récupérer sous forme de chaine chaque variable et concaténer*/
        while (*theFormat != '\0') {
          printf("chaine: %s\n", va_arg(argList, char*)); /*Ne marche pas*/
     
          sprintf(nextParameter, "%x", va_arg(argList, int)); 
     
          sprintf(parameters,"%s%s%s%s",parameters,"0x",nextParameter,"  ");
     
          printf("parameters = %s,  %d \n",parameters,va_arg (argList, int));
     
          /* advance to the next format character */
          theFormat++;
        }
     
      va_end(argList);
      printf("parameters chain = %s\n\n", parameters);
      } /* has param */
     
      return "nico"/*parameters*/;
    }
    Si vous avez des explications à ces résultats obtenus et des moyens de les résoudre?

    Merci d'avance.
    parameters est une variable locale, initialisée à NULL, et puis et puis, rien ... Pas d'allocation de mémoire... Comment veux-donc tu mettre quelquechose dedans, au même titre que nextParameter.
    Autre chose, theFormat est un objet de type CString pas un char * et donc pas un pointeur, donc comparer un objet à NULL, ou encore le déréférencer (*theFormat) et appliquer un opérateur d'incrément dessus (theFormat++), cela a des chances de compiler, mais c'est du n'importe quoi qui produit à coup sûr des comportements indéfinis. Le mieux ici (façon C) est de passer theFormat en char* et de passer en paramètre le tampon de char correspondant à l'objet CString (utiliser l'opérateur LPCTSTR, voir MSDN). Remarque : Sois tu fais du C et tu n'utilises que des char *, sois tu fais du C++ MS et tu utilises au plus des CString ainsi que les mécanismes C++ qui pourraient te simplifier la vie (références), mais par pitié, pas de mélange comme ceci.

    Enfin, tu as deux appels à va_end(argList), celà produit un comportement indéfini, il n'y a pas d'appel correspondant à va_start ou va_copy.

    Le(s) problème(s) est(sont) loin de concerner l'utilisation des macros pour fonctions variadiques.

    A+

  4. #4
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Oui tu as raison, je suis en effet d'accord que le(s) problème(s) proviennent aussi du code, je m'en doutais bien! En fait, je suis reparti d'une structure de code utilisée pour une application, notamment theFormat déclarée en CString et la structure pour utiliser les fonctions variadiques. D'ailleurs, pour info:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    typedef Char         *String;        /* Ptr to a string of characters */
    typedef const Char   *CString;       /* Ptr to a string of constant characters */
    Je vais donc être plus rigoureux!

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Tu devrais utiliser des types plus persos que ça, ou du moins ne pas les déclarer comme des classes (tu as d'un coté un conflit avec les System::String de .Net, de l'autre un conflit avec les CString de MFC).

    Déjà, mettre les types en majuscules (STRING et CSTRING) devrait être plus "sur" : Je ne crois pas que ces identifiants soient utilisés quelque part.

    Ou bien, au contraire, utiliser exprès des types existants sur certaines plate-formes en ne les définissant que s'il n'existent pas déjà.
    Notamment, les types LPCSTR et LPSTR (ou LPCTSTR et LPTSTR pour les amateurs d'unicode).

    Code en-tête C/C++ non-teste : 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
    #ifdef DOIS_DEFINIR_MOIMEME_CHAINES
     
    typedef char CHAR;
    typedef wchar_t WCHAR;
    #ifdef _UNICODE
    typedef WCHAR TCHAR;
    typedef WCHAR _TUCHAR; /* pour fonctions de wctype.h */
    #else
    typedef CHAR TCHAR;
    typedef unsigned char _TUCHAR; /* pour fonctions de ctype.h */
    #endif
    typedef CHAR       * LPSTR;
    typedef const CHAR * LPCSTR;
    typedef WCHAR       * LPWSTR;
    typedef const WCHAR * LPCWSTR;
    typedef TCHAR       * LPTSTR;
    typedef const TCHAR * LPCTSTR;
     
    #endif
    Edit : J'avais fait une inversion pour les TCHAR, c'est corrigé.
    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.

  6. #6
    Membre chevronné
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Par défaut
    Citation Envoyé par homeostasie
    Oui tu as raison, je suis en effet d'accord que le(s) problème(s) proviennent aussi du code, je m'en doutais bien! En fait, je suis reparti d'une structure de code utilisée pour une application, notamment theFormat déclarée en CString et la structure pour utiliser les fonctions variadiques. D'ailleurs, pour info:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    typedef Char         *String;        /* Ptr to a string of characters */
    typedef const Char   *CString;       /* Ptr to a string of constant characters */
    Je vais donc être plus rigoureux!
    AAAArrrrrrrrghhhhhhhhhhh !!!!!!!!!!!!

    C'est quoi ces alias !!!

    1) Le C est sensible à la casse, le type Char est inconnu.
    2) Ces alias de types sont pervers au possibles, ils cachent un type pointeur et ont des noms susceptibles d'être rencotntrés facilement ailleurs. Preuve est que j'étais sûr (et je n'ai pas dû être le seul) que CString était la classe C++ MS ATL/MFC. Pareil pour String, à une majuscule près, on pourrait croire qu'il s'agit du type std::string de la bibliotèque standard C++.

    ! ON NE FAIT PAS DES TYPEDEFS DE CE GENRE !

    Pour revenir à ton code initial, quelques modifs : c'est loin d'être correct et j'ai ajouté des commentaires en gras pour donner matière à réflexion.

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    va_list   argList;
    char * parameters = NULL;
      
    if ((gRDSFlag == 1) && (theEvent <= RDS_FormerMaxEvNum))
     {  
     /*Routine to save info about RDS event in the circular buffer for Post Mortem file*/
        va_start(argList,theFormat);
        parameters = ParametersChain(theFormat,argList);
        va_end(argList);
        
        if (parameters) {
            SaveRdsEvPostMortem(theEvent, theClass, theSubcode, theFormat, parameters);
            free(parameters), parameters = NULL;
           }  
      }
      
    [...]
    
    char* ParametersChain(char const * theFormat, va_list argList)
    {
      char* parameters = NULL;
      char* nextParameter = NULL;
        
      parameters = malloc(512+1);
      if(!parameter) { return NULL; }
    
      nextParameter= malloc(512+1);
      if(!nextParameter) {
          free(parameters), parameters = NULL; 
          return NULL; 
      }
    
      /*To get parameters from the format variable*/
      if(!theFormat){
        strcpy(parameters,"None");
      }
      else{     
    
    
    #ifdef METHODE1
    
        /*méthode1: utiliser vsprintf et se passer de la boucle while*/
        vsprintf(parameters,theFormat,argList);
        printf("vsprintf chaine: %s\n", parameters);
    
    #else    
    
        /* Get and add each param except the last one to the event */
        /*méthode2: récupérer sous forme de chaine chaque variable et concaténer*/
        while (*theFormat != '\0') {
    
          /* Et avec QUOI de theFormat comptes-tu récupérer un argument de type char* ? */
          printf("chaine: %s\n", va_arg(argList, char*)); /*Ne marche pas*/ 
            
          /* Et avec QUOI de theFormat comptes-tu récupérer un argument de type int ? */
          sprintf(nextParameter, "%x", va_arg(argList, int)); 
        
          /* Prendre une chaine d'un tampon pour réécrire ensuite dans le même tampon, curieux..., et superbe comportement indéfini */ 
          sprintf(parameters,"%s%s%s%s",parameters,"0x",nextParameter,"  ");
        
          printf("parameters = %s,  %d \n",parameters,va_arg (argList, int));
    
    #endif
    
          /* advance to the next format character */
          theFormat++;
    
           /* As-tu compris que ce code essaie de récupérer pour CHAQUE (et quelquesoit celui-ci) caractère du format
              une chaine, un entier, puis encore un entier, d'autant plus que tu ne fais qu'afficher
              la chaine sur la sortie standard, sans la stocker, pareil pour le deuxième entier.
              Ca n'a rien à voir avec le vsprintf() au niveau comportemental et cela implique que si tu as 3 caractères 
              ('\0' non compris), tu as en tout à passer 9 arguments après le format à la fonction !!.
            */   
            
        }
      
      printf("parameters chain = %s\n\n", parameters);
      } /* has param */
    
      free(nextParameter), nextParameter = NULL; 
    
      return parameters;
    }
    Bon, il y a du boulot. Voici un exemple simple pour commencer, avec une fonction varidique displayf qui utilise soir un vrai printf, soit un printf maison (3 formats $I pour entier int, $D pour double et $S pour chaine de caractères).

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    #include <stdio.h>
    #include <stdarg.h>
     
    int process(int truePrintf, char const * fmt, va_list args);
     
    int displayf(int truePrintf, char const * fmt, ...)
    {
        int rc = 0;
        va_list args;
     
        va_start(args, fmt);
        rc = process(truePrintf, fmt, args);
        va_end(args);
     
        return rc;
    }
     
    int process(int truePrintf, char const * fmt, va_list args)
    {
       int rc = 0;
       if (truePrintf) {
         rc = vprintf(fmt, args);
       }
       else {
         int prev = -1;
     
         while(*fmt != '\0') {
            if (prev == '$')
            { 
              switch(*fmt) {
                case 'S':
                  rc += printf("%s", va_arg(args, char*) );  
                  break;
                case 'I':
                  rc += printf("%d", va_arg(args, int) );  
                  break;
                case 'D':
                  rc += printf("%lf", va_arg(args, double) );
                  break;
                default:
                  ++rc;         
                  break;
               }
               fflush(stdout);  
           }
           else if (*fmt != '$') {
               putc(*fmt, stdout);  ++rc;
           }
           prev = *fmt;
           ++fmt;  
         }
       }
     
       return rc; 
    }
     
    int main(void)
    {
        char * chaine = "Coucou";
        int a = 2, b = 3;
        double c = 4.567; 
     
        int nbct = 0;
     
        nbct = displayf(0,"Args: $I $I $D $S\n", a,b,c,chaine);
        printf("Nb caracteres transmis avec 'printf' maison : %d\n", nbct );
     
        nbct = displayf(1,"Args: %d %d %lf %s\n", a,b,c,chaine);
        printf("Nb caracteres transmis avec 'printf' vrai : %d\n", nbct );
     
        return 0;
    }
    Et je répète, pas de String ou de CString via des typedefs. En C, on utilise un peu plus les mimines et on tape char * ou char const * à la place.

    A+

  7. #7
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Merci footbar pour la décortication du code, voici quelques explications et ce que je désirais faire:

    Code :
    typedef Char *String; /* Ptr to a string of characters */
    typedef const Char *CString; /* Ptr to a string of constant characters */
    Ceci ce n'est pas moi qui l'ai généré. En fait, j'ajoute mes optimisations personnelles dans le code existant et employé dans un long projet. Pour te dire, ces alias ont été fait en 2000 et je suis tout à fait d'accord avec tes remarques, j'ai moi même cru que c'était les CString de la classe MFC que j'utilisais en C++. D'ailleurs j'ai voulu les manipuler comme tel et je me suis fait jeter par le compilo.

    /* Et avec QUOI de theFormat comptes-tu récupérer un argument de type char* ? */
    printf("chaine: %s\n", va_arg(argList, char*)); /*Ne marche pas*/

    /* Et avec QUOI de theFormat comptes-tu récupérer un argument de type int ? */
    sprintf(nextParameter, "%x", va_arg(argList, int));
    En fait, mon but n'était pas de tenir compte du type dans theFormat pour savoir si j'ai un char*, un int etc... mais de récupérer la variable quelque soit le type en entier. Le code au dessus avait pour rôle de tester essentiellement.

    Voici ce que j'ai fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	while (*theFormat != '\0') {
    		RDSEventBuf.parameters[numParams] = va_arg (argList, int);
    		numParams++;
           	theFormat++;
          }
    /* Prendre une chaine d'un tampon pour réécrire ensuite dans le même tampon, curieux..., et superbe comportement indéfini */
    sprintf(parameters,"%s%s%s%s",parameters,"0x",nextParameter," ");
    Alors pour ce point, je me demande si c'est vraiment possible et je crois que je devrais changer cela. Je désirais concaténer au fur et à mesure "0x"+nextParameter+" " dans ma chaine existante parameters. Ainsi, la variable paramters contiendrait l'ensemble des variables récupérées sous forme de string.
    Un autre moyen de faire cela?
    J'aurais pensé que la fonction vsprintf jouait ce rôle... mais appremment ca affiche la chaine des types présent dans theFormat.

    A propos du code que tu m'as joint:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if (prev == '$')
            {
    Que signifie cette comparaison?

    Pourquoi vider stdout?

    Voilà, merci.
    A plus

  8. #8
    Membre chevronné
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Par défaut
    Hello,

    Citation Envoyé par homeostasie
    Merci footbar pour la décortication du code, voici quelques explications et ce que je désirais faire:


    Ceci ce n'est pas moi qui l'ai généré. En fait, j'ajoute mes optimisations personnelles dans le code existant et employé dans un long projet. Pour te dire, ces alias ont été fait en 2000 et je suis tout à fait d'accord avec tes remarques, j'ai moi même cru que c'était les CString de la classe MFC que j'utilisais en C++. D'ailleurs j'ai voulu les manipuler comme tel et je me suis fait jeter par le compilo.
    Si la personne qui a fait ça est encore là =>


    Citation Envoyé par homeostasie
    En fait, mon but n'était pas de tenir compte du type dans theFormat pour savoir si j'ai un char*, un int etc... mais de récupérer la variable quelque soit le type en entier. Le code au dessus avait pour rôle de tester essentiellement.

    Voici ce que j'ai fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	while (*theFormat != '\0') {
    		RDSEventBuf.parameters[numParams] = va_arg (argList, int);
    		numParams++;
           	theFormat++;
          }
    D'accord, donc quelquesoit le caractère du format, pour un caractère donné, on récupère un entier => Pourquoi pas, mais... C'est un peu couillon, pourquoi ne pas simplement passer en paramètre un entier indiquant le nombre de paramètres à suivre ? Surtout qu'il n'y a pas de condition sur le type de variable à afficher.
    Ca c'est la première incohérence.
    Ensuite, il apparait que tu souhaites afficher des entiers préfixés par "0x", donc si c'est bien de l'affichage hexadécimal, le type des données doit être unsigned int et non int à la base.

    Citation Envoyé par homeostasie

    Alors pour ce point, je me demande si c'est vraiment possible et je crois que je devrais changer cela. Je désirais concaténer au fur et à mesure "0x"+nextParameter+" " dans ma chaine existante parameters. Ainsi, la variable paramters contiendrait l'ensemble des variables récupérées sous forme de string.
    Un autre moyen de faire cela?
    J'aurais pensé que la fonction vsprintf jouait ce rôle... mais appremment ca affiche la chaine des types présent dans theFormat.
    Ce que tu souhaites, c'est concaténer tes entiers (sous forme de chaine hexa) dans parameters, strcat est là pour ça. Attention d'avoir des tampons avec assez de place. vsprintf() n'est que sprintf() fonctionnant avec un va_list, soit de l'écriture formatée dans un tampon.

    Exple de portion de code pour ta boucle dans ParametersChaine. Je suggère de remplace theFormat par un argument entier (nbParam ci-dessous), précisant le nombre d'arguments à venir.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    /*...*/
     
    char buf[20] = { '\0' };
    while (nbParam) {
       RDSEventBuf.parameters[nbParam-1] = va_arg (argList, int);
       sprintf(buf, "%#0x ", (unsigned int) RDSEventBuf.parameters[nbParam-1]);
       strcat(parameters, buf);
       --nbParams;
    }
     
    /*...*/

    Citation Envoyé par homeostasie

    A propos du code que tu m'as joint:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if (prev == '$')
            {
    Que signifie cette comparaison?
    He bien, c'était pour vérifier si le caractère précédent était bien '$' dans mon spécificateur de format maison, car j'aurais très bien pu rencontrer un 'S' ou un 'I' ou un 'D' dans un mot quelconque sans que ce soit un spécificateur de format.

    Citation Envoyé par homeostasie
    Pourquoi vider stdout?

    Voilà, merci.
    A plus
    Le flux de sortie de printf() est souvent tamponné (i. les données sont accumulées dans un tampon avant d'être réellement envoyées pour affichage). Pour forcer l'affichage (i.e l'envoie des données tamponnées) avec printf(), on met soit un caractère nouvelle ligne '\n' ou alors on 'flushe' explictitement les données avec ici fflush(sdtout). Comme je n'avais de pas de '\n' dans mes printf(), j'utilisais fflush(sdtout).

    A+

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

Discussions similaires

  1. VC++ Direct3D8, problème avec LPD3DXFONT et LPD3DTEXTURE8
    Par Magus (Dave) dans le forum DirectX
    Réponses: 3
    Dernier message: 03/08/2002, 11h10
  2. Problème avec [b]struct[/b]
    Par Bouziane Abderraouf dans le forum CORBA
    Réponses: 2
    Dernier message: 17/07/2002, 10h25
  3. Problème avec le type 'Corba::Any_out'
    Par Steven dans le forum CORBA
    Réponses: 2
    Dernier message: 14/07/2002, 18h48
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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