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

Bibliothèque standard C Discussion :

Question sur fflush()


Sujet :

Bibliothèque standard C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Inscrit en
    Mai 2007
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 8
    Par défaut Question sur fflush()
    Bonjour à tous ,

    Je suis étudiant en informatique et j'ai a réaliser divers programmes.

    Ma question d'aujourd'hui se porte sur la fonction fflush(stdin)

    Je m'explique ,
    dans à peu près tout mes programmes je blinde mes saisies

    exemple :
    Quelle case du vecteur voulez-vous modifier ?

    Blinder la saisie de manière à ne pas dépasser le nombre d'éléments maximum.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    do
    {
         scanf .....
         .
         .
    } while ... ;


    mon problême est que si on entre par exemple un caractère ( 'a' par exemple )
    ça plante ^^

    Je dois donc utiliser fflush(stdin).

    Le problême c'est que quand le programme commence a faire quelques lignes
    on trouve des fflush(stdin) presque tout le temps .. pas très agréable à la lecture !!

    Ma question est donc :
    Y a t il un autre moyen d'éviter ce plantage ?

  2. #2
    Membre éclairé Avatar de emprex
    Homme Profil pro
    auto-entrepreneur
    Inscrit en
    Octobre 2007
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : auto-entrepreneur
    Secteur : Services à domicile

    Informations forums :
    Inscription : Octobre 2007
    Messages : 219
    Par défaut
    je crois qu'il faut ponctuer le flot par \n.

  3. #3
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    fflush ( stdin ) a un comportement indetermine !!!!!!!!!!!!!!!!!!

    fflush est fait pour les flux de sortie, ce qui n'est pas le cas de stdin....


    http://man.developpez.com/man3/fflush.3.php

    je ne suis pas sur mon PC la, je n'ai plus la reference de la norme, mais c'est TRES CLAIR....

    http://c.developpez.com/faq/tmp/?pag...N_fflush_stdin

  4. #4
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    je ne suis pas sur mon PC la, je n'ai plus la reference de la norme
    Citation Envoyé par ISO/IEC 9899:1999, §7.19.5.2
    Ifstream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
    Une bonne manière de purger le tampon d'un flux entrant tel que stdin est d'utiliser:

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void fpurge(FILE *fp)
    {
        if (fp != NULL)
        {
            int c;
     
            while (( c = fgetc(fp)) != '\n' && c != EOF)
            {
            }
        }
    }

    Dans ce cas, tu peux saisir un entier de la manière suivante:

    Code C : 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
    # include <stdio.h>
     
    static void fpurge(FILE *fp)
    {
        if (fp != NULL)
        {
            int c;
     
            while (( c = fgetc(fp)) != '\n' && c != EOF)
            {
            }
        }
    }
     
    int main(void)
    {
        int rv;
        int entier;
     
        do
        {
            printf("Entrez un entier entre 0 et 20: ");
            fflush(stdout);
            rv = scanf("%d", &entier);
            fpurge(stdin);
        }
        while (rv != 1 || entier < 0 || entier > 20);
     
        printf("Vous avez entre l'entier %d\n", entier);
     
        return 0;
    }

    Je préfère toutefois utiliser une solution à base de fgets() pour toutes mes saisies utilisateur.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 865
    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 865
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Julz0r Voir le message
    Je dois donc utiliser fflush(stdin).
    Non, rien n'est obligatoire. T'as donc bien compris que ton scanf() a refusé le 'a' et ce 'a' est resté dans le clavier. La purge de stdin() est donc une solution mais ce n'est pas la meilleure. Pour moi, c'est ce qu'a dis Thierry Chapuis, la bonne solution est de faire un fgets() dans un tableau de char => ton clavier est donc complètement clean puis tu parses ce tableau de char via sscanf (ce qui te permet en plus de contrôler la saisie)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char saisie[256];
    int nb;
     
    printf("Entrez un nombre :"), fflush(stdout);   // Si ça t'embête d'avoir 2 lignes...
    fgets(saisie, 256, stdin);
    if (sscanf(saisie, "%d", &nb) < 1)
       // Erreur de saisie
    else
       // Saisie ok
    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]

  6. #6
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Non, rien n'est obligatoire. T'as donc bien compris que ton scanf() a refusé le 'a' et ce 'a' est resté dans le clavier. La purge de stdin() est donc une solution mais ce n'est pas la meilleure. Pour moi, c'est ce qu'a dis Thierry Chapuis, la bonne solution est de faire un fgets() dans un tableau de char => ton clavier est donc complètement clean puis tu parses ce tableau de char via sscanf (ce qui te permet en plus de contrôler la saisie)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char saisie[256];
    int nb;
     
    printf("Entrez un nombre :"), fflush(stdout);   // Si ça t'embête d'avoir 2 lignes...
    fgets(saisie, 256, stdin);
    if (sscanf(saisie, "%d", &nb) < 1)
       // Erreur de saisie
    else
       // Saisie ok
    Avec un tableau de 256 chars, il y a peu de risques que l'utilisateur (même si on est pas à l'abris d'une action volontaire de ce dernier) entre plus de caractères qu'il ny a de place dans le tampon. Par ailleurs, fgets() saisit également le caractère de fin de ligne, ce qui peut être gênant parfois. Il est souvent recommandé sur ce forum d'utiliser la fonction suivante afin de régler ces deux problèmes dans la foulée:

    Code C : 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
    #include <stdio.h>
    #include <string.h>
     
    /* -tc- elimine le caratere de fin de ligne saisi par fgets() et faire le menage
       sur le flux entrant en cas de saisie tronquee */
    void fclean(char *buffer, FILE *fp)
    {
        if (buffer != NULL && fp != NULL)
        {
            char *pc =strchr(buffer, '\n');
     
            if (pc != NULL)
            {
                *pc = 0;
            }
            else
            {
                int c;
     
                while ((c = fgetc(fp)) != '\n' && c != EOF)
                {
                }
            }
        }
    }

    Par ailleurs, et c'est une préférence personnelle, j'utilise plus volontier les fonctions de la famille strto*() pour la conversion, car elles permettent une gestion d'erreur plus fin que scanf() (on sait où la conversion s'est arrêtée). Ainsi, ton exemple devient:

    Code C : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    /* -tc- elimine le caratere de fin de ligne saisi par fgets() et faire le menage
       sur le flux entrant en cas de saisie tronquee */
    void fclean(char *buffer, FILE *fp)
    {
        if (buffer != NULL && fp != NULL)
        {
            char *pc =strchr(buffer, '\n');
     
            if (pc != NULL)
            {
                *pc = 0;
            }
            else
            {
                int c;
     
                while ((c = fgetc(fp)) != '\n' && c != EOF)
                {
                }
            }
        }
    }
     
     
    int main(void)
    {
        /* -tc- j'aime bien initialiser toutes les cases de mon tampon a 0 */
        char saisie[16] = "";
        int nb = 0;
        /* -tc- pour la gestion des erreurs avec strtol() */
        char *pend = NULL;
     
        do
        {
            printf("Entrez un nombre: ");
            fflush(stdout);
            /* -tc- il n'est pas recommande de coder la taille de saisie en dur */
            fgets(saisie, sizeof saisie, stdin);
            fclean(saisie, stdin);
            nb = strtol(saisie, &pend, 0);
        }
        while (*pend != 0);
     
        printf("Le nombre entre est %d!\n", nb);
     
        return 0;
    }

    Bien entendu, on encapsule le tout dans une fonction de saisie spécifique bien au chaud dans sa bibliothèque personnelle...

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

Discussions similaires

  1. [debutant] Questions sur 1 futur projet
    Par cyrull22 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 28/04/2003, 21h49
  2. Quelques questions sur le TWebBrowser...
    Par CorO dans le forum Web & réseau
    Réponses: 3
    Dernier message: 17/01/2003, 21h23
  3. Question sur les handles et les couleurs...
    Par MrDuChnok dans le forum C++Builder
    Réponses: 7
    Dernier message: 29/10/2002, 08h45
  4. Réponses: 2
    Dernier message: 11/08/2002, 21h27
  5. question sur les message box !
    Par krown dans le forum Langage
    Réponses: 7
    Dernier message: 02/08/2002, 16h11

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