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 :

Aide avec scanf


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 11
    Par défaut Aide avec scanf
    Bonjour,

    J'ai écris une fonction de saisie sécurisé que l'on utilise comme scanf, et qui utilise scanf, elle vide le buffer après la saisie et récupère le dernier \n, j'y ai inséré une boucle qui tourne tant que la saisie n'est pas bonne.

    Ce que j'aimerai faire c'est inséré entre chaque format le format %n pour vérifier quelle saisie à planté.

    Je vous poste le code commenté :

    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
     
    #include <stdio.h>
    #include <stdarg.h>
    #include <string.h>
     
    void input (char *format, ...)
    {
     
        int i;
        char seq[] = "%*[^\n]";
        char *ptn = format;
     
        /*
         * On cherche le nombre d'assignement
         * pour verifier la sortie du vscanf
         */ 
        for (i = 0; (ptn = strchr (ptn, '%')); ++i)
        {
            /* si le pointeur est null, alors il
             * n'y a plus d'assignement
             */
            if (ptn == NULL)
                break;
            else
            {
                ptn++;
                /* si le '%' est suivi d'un '*'
                 * ou d'un 'n', il n'y a pas
                 * d'assignement
                 */
                if (*ptn == '*' || *ptn == 'n')
                    i--;
            }
        }
     
        va_list v_arg;
        va_start (v_arg, format);
     
        /* tant que la saisie n'est pas bonne, on recommence */
        while (i != vscanf (format, v_arg))
        {
            printf ("Try again: ");
            scanf (seq); /* on vide le buffer */
            getchar(); /* on enleve le '\n' restant */
        }
        scanf (seq);
        getchar ();
     
        va_end (v_arg);
    }
    J'ai aussi cette erreur à la compilation :
    [misc] david $ cc input.c -Wall
    input.c: In function ‘input’:
    input.c:26: attention : implicit declaration of function ‘vscanf’
    D'après le manuel (man vscanf), elle se trouve dans stdarg.h qui est inclue pourtant.

    Cordialement, Link/DD

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Je crois que la fonction vscanf() n'est pas C90, mais C99. Essaie en rajoutant -std=c99 sur ta ligne de commande à gcc...
    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
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Je crois que la fonction vscanf() n'est pas C90, mais C99. Essaie en rajoutant -std=c99 sur ta ligne de commande à gcc...
    Avec MinGW en mode C90 strict, aucun problème... (du moins, pas celui-la...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
    -------------- Build: Debug in hello ---------------
     
    Compiling: main.c
    Linking console executable: bin\Debug\hello.exe
    C:\dev\hello\main.c: In function `input':
    C:\dev\hello\main.c:36: warning: ISO C90 forbids mixed declarations and code
    C:\dev\hello\main.c:22: warning: will never be executed
    C:\dev\hello\main.c: In function `main':
    C:\dev\hello\main.c:58: warning: passing arg 1 of `input' discards qualifiers from pointer target type
    Output size is 20.29 KB
    Process terminated with status 0 (0 minutes, 0 seconds)
    0 errors, 3 warnings
    Je recommande :
    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 <stdarg.h>
    #include <string.h>
     
    void input (char const *format, ...)
    {
     
       int i;
       char seq[] = "%*[^\n]";
       char const *ptn = format;
     
       /*
        * On cherche le nombre d'assignement
        * pour verifier la sortie du vscanf
        */
       for (i = 0; (ptn = strchr (ptn, '%')); ++i)
       {
          /* si le pointeur est null, alors il
           * n'y a plus d'assignement
           */
          if (ptn == NULL)
             break;
          else
          {
             ptn++;
             /* si le '%' est suivi d'un '*'
              * ou d'un 'n', il n'y a pas
              * d'assignement
              */
             if (*ptn == '*' || *ptn == 'n')
                i--;
          }
       }
     
       {
          va_list v_arg;
          va_start (v_arg, format);
     
          /* tant que la saisie n'est pas bonne, on recommence */
          while (i != vscanf (format, v_arg))
          {
             printf ("Try again: ");
             scanf (seq);           /* on vide le buffer */
             getchar ();            /* on enleve le '\n' restant */
          }
          scanf (seq);
          getchar ();
     
          va_end (v_arg);
       }
    }

  4. #4
    Membre Expert
    Avatar de muad'dib
    Homme Profil pro
    Développeur Java
    Inscrit en
    Janvier 2003
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Janvier 2003
    Messages : 1 013
    Par défaut
    Excusez-moi mais je ne vois pas l'intérêt de réinventer la roue. À priori tu es entrain d'essayer de réecrire ce qui existe déja (fgets + vidage correct du buffer). Alors à moins que ce soit à but pédagogique ou intellectuel, pourquoi ne pas utiliser fgets ?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 11
    Par défaut
    Emmanuel Delahaye: Il n'y a aucun problème si le développeur mets %4s, scanf récupèrera 4 caractères et le reste sera toujours dans le buffer, cependant ici le buffer est vidé.

    L'utilisation de scanf ou de toute autre fonction de lecture sur l'entrée standard est dangereuse si on ne vérifie pas la taille de ce qui est récupéré. Pour l'instant ma fonction ne fais que vider le buffer et redemander la même chose à l'utilisateur tant que ce qu'il a entré est faux, je compte bien l'améliorer ^^

    Je préfère bien utiliser scanf plutot qu'utiliser fgets et les fonctions de conversions adéquates ce qui fait souvent une masse non négligeable de code.

    En compilant avec l'option -std=c99, je obtiens une erreur de segmentation.

    Link/DD

  6. #6
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Link/DD Voir le message
    J'ai écris une fonction de saisie sécurisé que l'on utilise comme scanf, et qui utilise scanf, elle vide le buffer après la saisie et récupère le dernier \n, j'y ai inséré une boucle qui tourne tant que la saisie n'est pas bonne.
    Apparemment aussi mal sécurisée que scanf()...

    Ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int main (void)
    {
       int n;
       char s[4];
     
       input ("%d%s", &n, s);
     
       printf ("%d '%s'\n", n, s);
     
       return 0;
    }
    provoque un crash...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    123 unechaineunpeulongue...
    123 'unechaineunpeulongue...'
     
    Process returned -1073741819 (0xC0000005)   execution time : 33.872 s
    Press any key to continue.
    Je recommande de laisser tomber scanf() si on est pas un expert...

    http://emmanuel-delahaye.developpez.com/inputs.htm

Discussions similaires

  1. Besoin d'aide avec scanf
    Par teddyalbina dans le forum Débuter
    Réponses: 3
    Dernier message: 29/12/2008, 11h59
  2. [ASA] J'ai besoin d'aide avec sybase et vb6 svp !!
    Par tibo830 dans le forum SQL Anywhere
    Réponses: 7
    Dernier message: 12/05/2006, 10h09
  3. Réponses: 2
    Dernier message: 29/08/2003, 17h52
  4. PB avec scanf
    Par ché dans le forum C
    Réponses: 6
    Dernier message: 13/08/2003, 07h25
  5. Besoin d'aide avec postgresql sous windows NT
    Par Chihuahua dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 18/07/2003, 08h29

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