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

Contribuez Discussion :

[FAQ] fflush(stdin) => Comment vider le buffer clavier ?


Sujet :

Contribuez

  1. #1
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut [FAQ] fflush(stdin) => Comment vider le buffer clavier ?
    Bonjour

    L'entrée http://www.developpez.com/faq/?page=...buffer_clavier me pose problème car elle considère qu'il y a quelque dans le buffer. Quand il est vide, on attend !
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Lien correct

    En fait, la réponse est simple: Il n'existe rien en standard pour "vider le buffer clavier".

    L'entrée de la FAQ sert à "finir de lire la ligne courante" (après un scanf() ou après un fgets() n'ayant pas retourné de \n).
    C'est généralement suffisant tant que tu restes en Command-Line Interface.

    Si par contre tu veux une interface qui n'attend pas [Entrée] (et que tu utilises donc getch()) tu peux faire une simple boucle while(kbhit()) getch(); pour vider le buffer clavier.
    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
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Ce problème a déjà été abordé ici : http://www.developpez.net/forums/d76...s/#post6685910

  4. #4
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    Je viens de regarder les différentes archives...
    Citation Envoyé par Obsidian Voir le message
    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
    #ifndef _POSIX_SOURCE
    #define _POSIX_SOURCE
    #endif
     
    #include <errno.h>
    #include <stdio.h>
    #include <fcntl.h>
     
    /* Vide le buffer d'entrée d'un flux utilisable
     * en lecture. Renvoie 1 en cas d'échec, 0 sinon. */
     
    int fclearbuf (FILE * f)
    {
        int ret = 1;
        int fd = -1;
     
        if (f!=NULL)
        if ((fd=fileno(f))>=0)
        {
            long flags  = 0;
     
            flags = (long)fcntl (fd,F_GETFL,0);
            if (!(flags & O_WRONLY))
            {
                char buffer [64];
     
                fcntl (fd,F_SETFL,flags | O_NONBLOCK);
                while (fread(buffer,sizeof buffer,1,f)==1);
                if (ferror(f) && errno == EWOULDBLOCK)
                {
                    clearerr (f);
                    ret = 0;
                }
                fcntl (fd,F_SETFL,flags);
            }
        }
     
        return ret;
    }
    Pour rendre ce programme compatible avec plus de compilateurs C, il faudrait initialiser les variables au début de la fonction.
    Et surtout, il faudrait un peu expliquer ! C'est beau de piquer un programme, mais il faut le comprendre !
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    En gros, ça fait la même chose que le while(kbhit()) getch();, à bas niveau, et par blocs de 64 bytes.

    Et c'est pour POSIX uniquement.
    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
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Bonjour,

    Citation Envoyé par troumad Voir le message
    Pour rendre ce programme compatible avec plus de compilateurs C, il faudrait initialiser les variables au début de la fonction.
    Euh, elles le sont. De quelles variables non initialisées parles-tu ?

    Et surtout, il faudrait un peu expliquer ! C'est beau de piquer un programme, mais il faut le comprendre !
    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
    #ifndef _POSIX_SOURCE
    #define _POSIX_SOURCE
    #endif
     
    #include <errno.h>
    #include <stdio.h>
    #include <fcntl.h>
     
    /* Vide le buffer d'entrée d'un flux utilisable
     * en lecture. Renvoie 1 en cas d'échec, 0 sinon. */
     
    int fclearbuf (FILE * f)
    {
        int ret = 1;
        int fd = -1;
     
        /* Si f est NULL ou si le descripteur est invalide, sors directement. */
        if (f!=NULL)
        if ((fd=fileno(f))>=0)
        {
            long flags  = 0;
     
            /* Récupère les flags associés au flux */
            flags = (long)fcntl (fd,F_GETFL,0);
     
            /* Sors également si le flux n'est pas utilisable en lecture */
            if (!(flags & O_WRONLY))
            {
                char buffer [64];
     
                /* Ajoute le flag non bloquant aux attributs actuels */
                fcntl (fd,F_SETFL,flags | O_NONBLOCK);
     
                /* Lis un bloc et continue tant que l'on arrive à en */
                /* obtenir un entier et que, donc, il a potentiellement */
                /* des données restantes derrière. */
                while (fread(buffer,sizeof buffer,1,f)==1);
     
                /* Si on s'est arrêté à cause d'une erreur et que */
                /* cette erreur est EWOULDBLOCK en particulier */
                /* alors c'est celle que l'on attendait et on la réinitialise. */
                /* Sinon, on laisse le programme appelant la gérer. */
                if (ferror(f) && errno == EWOULDBLOCK)
                {
                    clearerr (f);
                    ret = 0;
                }
     
                /* Remets les flags dans l'état où on les a trouvés en entrant, et sors. */
                fcntl (fd,F_SETFL,flags);
            }
        }
     
        return ret;
    }

    Le buffer a une longueur de 64 octets, choisie complètement arbitrairement. L'idée était d'éviter de faire un appel système par caractère, tout en économisant la pile et en choisissant une taille en rapport avec la quantité de caractères en attente et saisie au clavier, puisque c'est généralement à cela que sert cette fonction.

    Par contre, je m'aperçois que j'ai omis de gérer la valeur de retour de fcntl() qui peut échouer pour bon nombre de raisons et ça, c'est une lacune ! Désolé.

    Citation Envoyé par Médinoc Voir le message
    En gros, ça fait la même chose que le while(kbhit()) getch();, à bas niveau, et par blocs de 64 bytes.
    C'est surtout utile là où kbhit() n'est pas disponible, et c'est à bas niveau parce qu'effectivement, puisqu'il n'y a rien d'exploitable dans la norme C, ça devient de la programmation système.

    Ensuite, « bas niveau », oui et non parce que ça reste un fread(), mais il faut bien positionner le flag anti-bloquant d'une façon ou d'une autre.

    Et c'est pour POSIX uniquement.
    Oui, c'est comme cela qu'on l'a présenté (dans le post initial en tous cas).

  7. #7
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    Je parlais des variables flag et buffer qui ne sont pas initialisées en début de procédure, mais plus loin. Toutes les normes de C, surtout les plus anciennes, ne tolèrent pas ça.

    Merci pour tes explications. Il me restera à comprendre certaines notions que je n'ai pas encore comme fcntl.
    Je pourrai l'utiliser en le comprenant !
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par troumad Voir le message
    Je parlais des variables flag et buffer qui ne sont pas initialisées en début de procédure, mais plus loin. Toutes les normes de C, surtout les plus anciennes, ne tolèrent pas ça.
    Elles sont en début de bloc, même C89 autorise ça. Peut-être même le C K&R.
    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.

Discussions similaires

  1. Comment vider le buffer d'un EditText?
    Par diagonale dans le forum Android
    Réponses: 1
    Dernier message: 30/12/2012, 16h55
  2. comment vider un buffer?
    Par hamidoo07 dans le forum VB.NET
    Réponses: 5
    Dernier message: 24/06/2009, 18h31
  3. vider le buffer clavier
    Par Pragmateek dans le forum C
    Réponses: 31
    Dernier message: 20/06/2006, 21h33
  4. [vb.net] Comment vider un buffer ?
    Par mdc dans le forum Windows Forms
    Réponses: 4
    Dernier message: 16/12/2003, 15h43

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