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 :

#define STRINGIFY2( x) #x


Sujet :

C

  1. #1
    Membre confirmé
    Homme Profil pro
    Deficient visuel
    Inscrit en
    Mai 2019
    Messages
    216
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Deficient visuel

    Informations forums :
    Inscription : Mai 2019
    Messages : 216
    Par défaut #define STRINGIFY2( x) #x
    Bonjour a toutes et a tous,
    J'ai trouvé peu d'explication pour ne pas dire rien , sur cette partie de code que je ne comprends pas .
    Au prealable le code entier :

    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
    #include <stdio.h>
     
    #define NAMES_MAX_LENGTH    19  /* Maximum length of names, not including '\0' */
     
    #define STRINGIFY2( x) #x
    #define STRINGIFY(x) STRINGIFY2(x)
     
    static const char names_scan_fmt[]= "%" STRINGIFY(NAMES_MAX_LENGTH) "s";
     
    typedef struct player
    { 
            char prenom[NAMES_MAX_LENGTH + 1];  /* +1 for the '\0' */
            char nom[NAMES_MAX_LENGTH + 1];
            int age;
    } player;
     
    void changement(player *p)
    { 
            printf("quel est ton prenom ?\n");
            scanf(names_scan_fmt,p->prenom);
            printf("quel est ton nom ?\n");
            scanf(names_scan_fmt,p->nom); 
            printf("quel est ton age ?\n");
            while (!scanf("%d",&p->age))
                    scanf ("%*c");
    }
     
    int main(void)
    {
            player p1,p2;
     
            printf("\n____1er JOUEUR____\n");
            changement(&p1);
            printf("\n____2eme JOUEUR____\n");
            changement(&p2);
            printf("Le prenom du 1er joueur est %s,le nom %s et l'age est %d\n",p1.prenom,p1.nom,p1.age);
            printf("Le prenom du 2 eme joueur est %s,le nom %s et l'age est %d\n",p2.prenom,p2.nom,p2.age);
     
            return 0;
    }
    La partie que je ne comprends pas est la suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #define NAMES_MAX_LENGTH    19  /* Maximum length of names, not including '\0' */
     
    #define STRINGIFY2( x) #x
    #define STRINGIFY(x) STRINGIFY2(x)
     
    static const char names_scan_fmt[]= "%" STRINGIFY(NAMES_MAX_LENGTH) "s";
    Merci de votre aide

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Si tu ne mets pas 2 niveaux de macro, quand tu écris STRINGIFY(NAMES_MAX_LENGTH) le résultat sera "NAMES_MAX_LENGTH".
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre confirmé
    Homme Profil pro
    Deficient visuel
    Inscrit en
    Mai 2019
    Messages
    216
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Deficient visuel

    Informations forums :
    Inscription : Mai 2019
    Messages : 216
    Par défaut
    Merci .Je suis debutant en C , seulement depuis mai de cette année , et je me demandais a quoi servait :
    #define STRINGIFY2( x) #x
    #define STRINGIFY(x) STRINGIFY2(x)

    Il ne s'agit pas de quelque chose qui permet de securisé le scanf au bug overflow ?
    Mais j'ai sans doute pas le niveau pour comprendre , je devrai peut etre revenir a des choses de mon niveau !

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre confirmé
    Homme Profil pro
    Deficient visuel
    Inscrit en
    Mai 2019
    Messages
    216
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Deficient visuel

    Informations forums :
    Inscription : Mai 2019
    Messages : 216
    Par défaut
    Merci , c'est deja + clair !
    Un dernier petit point a eclaircir . Je ne comprends pas l'expression :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while (!scanf("%d",&p->age))
                    scanf ("%*c");
    }

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    C'est, en effet, une séquence subtile. Heureusement on ne rencontre que très rarement ce genre de code.
    Le premier scanf chercher à lire un nombre entier à stocker dans p->age.
    Le second scanf est totalement équivalent à appeler getc(). Il va lire un caractère tout en ne stockant aucunement la valeur lue.
    Il reste à expliquer le rôle du point d'exclamation et du while :
    - la valeur retournée par scanf() est le nombre de champs qu'elle a pu extraire. Ici il y juste un entier à extraire. La fonction va donc retourner 1 si peut lire un entier, va retourner 0 si elle ne peut rien lire, et va retourner une valeur négative en cas d'erreur.
    - le point d'exclamation est l'opérateur 'not'. S'il voit false ou une valeur nulle, il va retrourner true, s'il voit true ou une valeur non nulle il va retourner false.
    Je te propose d'écrire le code sous la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while ( scanf("%d", &p->age) == 0 )
                    getc();
    }
    C'est exactement la même chose.

    Donc cela essayer de lire un nombre entier, si c'est impossible (par exemple car la saisie commence par une lettre au lieu d'un chiffre) on va lire un caractère (donc la lettre) et recommencer jusqu'à ce finalement nombre entier soit lu.

  7. #7
    Membre confirmé
    Homme Profil pro
    Deficient visuel
    Inscrit en
    Mai 2019
    Messages
    216
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Deficient visuel

    Informations forums :
    Inscription : Mai 2019
    Messages : 216
    Par défaut
    Merci dalfab d'avoir pris le temps de toutes ces explications

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 816
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par chris7522 Voir le message
    Citation Envoyé par dalfab Voir le message
    Donc cela essayer de lire un nombre entier, si c'est impossible (par exemple car la saisie commence par une lettre au lieu d'un chiffre) on va lire un caractère (donc la lettre) et recommencer jusqu'à ce finalement nombre entier soit lu.
    C'est vrai que ce code produit ce comportement. Et donc si la saisie contient "abc123def", il en ressortira "123".

    Toutefois perso ce n'est pas un code que je te conseillerais de reproduire parce que déjà je ne suis pas fan de codes qui "veulent réparer ce qui a été mal entré" car en général ils réparent pas super bien (si la saisie est "abc123def456" ce code récupèrera "123" alors que celui qui saisit (ok il saisit comme un couillon d'où le nom "test du couillon" de ce genre de benchmark) aurait peut-être voulu "123456".
    Donc perso je préfère le style de saisie de type "tout ou rien". Soit l'utilisateur remplit correctement son truc et ça va, soit c'est un crétin et il n'a rien à faire dans mon programme.

    Et en plus ce n'est pas super efficace. Déjà quand tu entres "abc123def" il récupère bien "123" mais il laisse "def" dans le buffer clavier qui risque d'aller pourrir la saisie suivante ; et en plus que se passe-t-il pour une saisie style "abcdef" sans chiffre à récupérer ? J'ai pas testé mais quelque chose me dit que comme scanf() renverra 0 mais que le fgetc() ne récupèrera rien ça va partir en vrille.

    Perso je préfère coder ce type de saisie de cette façon
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char saisie[1024];
    while (1) {
    	fgets(saisie, 1024, stdin);
    	if (sscanf(saisie, "%d", &p->age) > 0) break;
    	fputs("Tu concentres ton demi-neurone et tu n'entres que des chiffres !!!\n", stderr);
    }
    Donc je fais saisir une string (ce qui laisse alors le clavier toujours vide) puis je regarde si je peux en extraire un nombre et sinon on recommence. Quitte à mettre ça dans une fonction dédiée. (style saisieInt()).

    Certains esprits particulièrement affutés remarqueront la limitation à 1023 ce qui est, je l'admets, une source de souci potentiel (si on saisit 3000 caractères le truc n'en consomme que 1023 et laisse le reste) mais déjà cela fait partie du ratio "probabilité du risque/coût de programmation" (ratio ici directement fonction de la taille définie par le programmeur) et d'autre part on peut aussi remplacer fgets() par getline() qui, elle, est virtuellement illimité" (ne pas oublier alors le free() de la chaine saisie ce qui augmente alors le "coût de programmation" dont j'ai parlé).

    Et en plus comme le crétin va recommencer jusqu'à ce qu'il s'instruise, je trouve déjà ce type de saisie un peu plus éducatif (ou alors il meurt de faim et de soif et ça joue un rôle de sélection naturelle... )
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

Discussions similaires

  1. #define D3D_DEBUG_INFO
    Par moldavi dans le forum DirectX
    Réponses: 7
    Dernier message: 03/02/2005, 14h14
  2. INSO Filter : "USER-defined exception" avec ctx_do
    Par Wiztiti dans le forum Oracle
    Réponses: 2
    Dernier message: 01/06/2004, 16h14
  3. USER DEFINE FONCTION : PB éxécution requête
    Par juelo dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 26/01/2004, 11h12
  4. Define sur plusieurs lignes
    Par Gogoye dans le forum C
    Réponses: 6
    Dernier message: 06/10/2003, 11h45
  5. define avec GCC.
    Par vagabon dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 12/06/2003, 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