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 :

Utilisation des va_list en argument d'un printf


Sujet :

C

  1. #1
    Membre habitué
    Avatar de barthelv
    Inscrit en
    Mars 2003
    Messages
    267
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 267
    Points : 126
    Points
    126
    Par défaut Utilisation des va_list en argument d'un printf
    Bonjour,

    Voici mon problème, j'ai un fichier texte qui comporte deux lignes du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    %s a %d ans
    <nom><age>
    Dans mon programme C, je veux faire un printf ainsi :

    printf("%s a %d ans", prenom, age);

    Pour faire cela, je récupère la première ligne, ce qui me permet de mettre cela comme premier argument du printf. Mais pour la récupération de la seconde ligne, je ne sais pas sous quel type de variable je dois mettre le prénom et l'age ? Est-ce que je peux les mettre dans une variable de type va_list ?

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    Il n'y a rien en standard pour créer dynamiquement une va_list. Ou alors, c'est que j'ai mal cherché.

    J'ai bien peur que tu te retrouves acculé à faire autrement : Je ne pense pas qu'on puisse réellement appeler dynamiquement une fonction variadic (les va_list servent plus à transmettre une liste d'argument d'une fonction variadic à sa version va_list ou celle d'une autre)...

  3. #3
    Membre habitué
    Avatar de barthelv
    Inscrit en
    Mars 2003
    Messages
    267
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 267
    Points : 126
    Points
    126
    Par défaut
    bon ben tant pis, je vais essayer de faire autrement...

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    349
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 349
    Points : 376
    Points
    376
    Par défaut
    Dans ton fichier, ta deuxième ligne est déjà formatée.
    Tu peux donc très bien faire la manip suivante:

    Récupérer la première ligne.
    Transformer tous les %quelque chose en %s et s'en servir comme premier argument du printf.

    Mettre en arguments suivants du printf les chaînes de caractères que tu récupères depuis la deuxième ligne.

  5. #5
    Membre éclairé Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Points : 844
    Points
    844
    Par défaut
    La soluce :

    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
    FILE *f;
    char line1[80];
    char line2[80];
    char *nom, *age, *tmp;
    int pos;
     
    f = fopen("mon_fichier.txt", "rt");
    fgets(line1, 80, f);
    fgets(line2, 80, f);
    fclose(f);
     
    nom = line2 + 1;
    pos = strchr(line2, '>');
    line2[pos] = 0;
     
    line2 += pos + 1;
    age = line2 + 1;
    pos = strlen(line2) - 1;
    line2[pos] = 0;
     
    printf(line1, nom, strtol(age, &tmp, 10));
    printf("\n");
    Pas besoin de va_list !

  6. #6
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Bonjour,

    Citation Envoyé par mchk0123
    La soluce :
    Qui ne compile pas :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    main.c: In function ‘main’:
    main.c:23: warning: assignment makes integer from pointer without a cast
    main.c:26: error: invalid operands to binary +

    Une version qui compile (la gestion des erreurs est loin d'être parfaite) :
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    static int str_istr (const char *cs, const char *ct)
    {
      int index = -1;
     
      if (cs && ct)
      {
        char *ptr_pos = NULL;
     
        ptr_pos = strstr (cs, ct);
        if (ptr_pos)
        {
          index = ptr_pos - cs;
        }
      }
      return index;
    }
     
    int main (void)
    {
      FILE *f;
     
      f = fopen("mon_fichier.txt", "rt");
      if (f != NULL)
      {
        char line1[80] = "";
        char line2[80] = "";
        char *nom = NULL;
        char *age = NULL;
        char *tmp = NULL;
        int pos;
     
        fgets(line1, 80, f);
        fgets(line2, 80, f);
        fclose(f), f = NULL;
     
        nom = &line2[1];
        pos = str_istr (line2, ">");
        line2[pos] = 0;
     
        age = &line2[pos + 2];
        pos = strlen(&line2[pos + 2]) - 1;
        line2[pos] = 0;
     
        printf(line1, nom, strtol(age, &tmp, 10));
        printf("\n");
      }
      return 0;
    }
    Mais loin d'être satisfaisante :

    Fichier de test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    AAAA|%s|%d|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|
    <gege><2061>
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    gege2061@moisi-box:~/test/string$./a.out
    AAAA|gege|2061|61ffe78b|0|99999999|0|61ffe787|0|61ffe78b|6765673c|3e313630|61ffe890|48bc29e8|30322043|0|0|0|0|3436|41414141|
    Un peu de lecture :
    Les pièges du C
    Exploiting Format String Vulnerabilities

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    Y'a quand même des problèmes dans l'article:
    Citation Envoyé par Exploiting Format String Vulnerabilities
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf ("The magic number is: %s\n", 1911);
    The text to be printed is "The magic number is:", followed by a format parameter `%s', that is replaced with the parameter (1911) in the output. Therefore the output looks like: The magiv number is: 1911.
    Ou plutôt, la sortie a plus de chances de ressembler à : Segmentation fault (core dumped).

    En clair, un joli comportement indéfini (undefined behaviour).


    Sans compter le manifique printf() à trois variables, dont une disparait dans la représentation de la pile, etc.

  8. #8
    Membre éclairé Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Points : 844
    Points
    844
    Par défaut
    Citation Envoyé par gege2061
    Qui ne compile pas :
    Arg ... j'oubliais que : "BB is watching me" ;-)

    Code qui compile et fonctionne :

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main() {
      FILE *f;
      char line1[80];
      char line2[80];
      char *ptr;
      char *nom, *age, *tmp;
      int pos;
     
      f = fopen("mon_fichier.txt", "rt");
      fgets(line1, 80, f);
      fgets(line2, 80, f);
      fclose(f);
     
      ptr = line2; 
      nom = ptr + 1;
      pos = strchr(ptr, '>') - ptr;
      ptr[pos] = 0;
     
      ptr += pos + 1;
      age = ptr + 1;
      pos = strlen(ptr) - 1;
      ptr[pos] = 0;
     
      printf(line1, nom, strtol(age, &tmp, 10));
    }

  9. #9
    Membre actif
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Points : 284
    Points
    284
    Par défaut
    Citation Envoyé par Médinoc
    Y'a quand même des problèmes dans l'article:
    [...]
    C'est bien dommage, le sujet avaitl'air assez amusant. Comme ce programme qui utilisait un printf mal formatté pour lancer une fonction sans l'appeler (j'ai oublié où j'ai vu cet exemple).

Discussions similaires

  1. boost::spirit utilisation des arguments
    Par SKone dans le forum Boost
    Réponses: 11
    Dernier message: 28/01/2011, 11h16
  2. [Fabrique] Besoin d'arguments pour utiliser des factories
    Par jm1974 dans le forum Design Patterns
    Réponses: 0
    Dernier message: 07/08/2009, 12h43
  3. utilisation des references en argument
    Par zaboug dans le forum Langage
    Réponses: 5
    Dernier message: 16/01/2009, 10h56
  4. [Débutant] Utiliser des listes en argument d'une fonction
    Par erkenbrand dans le forum Windows Forms
    Réponses: 10
    Dernier message: 29/05/2008, 12h56
  5. [ksh et/ou bash] Utilisation des arguments type -d
    Par novices dans le forum Shell et commandes GNU
    Réponses: 7
    Dernier message: 24/11/2007, 14h04

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