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 :

Impossible de vider le buffer clavier saisie multiples scanf()


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Ingénieur
    Inscrit en
    Avril 2020
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2020
    Messages : 88
    Points : 48
    Points
    48
    Par défaut Impossible de vider le buffer clavier saisie multiples scanf()
    Bonjour,

    J'ai lu sur le site developpez.com, ici = https://c.developpez.com/faq/?page=G...buffer-clavier, comment vider le buffer clavier.

    Je pense ne rien avoir oublié et pourtant cela ne fonctionne toujours pas.
    J'ai des problèmes lors de ma saisie multiples lorsque je lance le programme.
    Je ne sais pas si vraiment le problème vient de là mais généralement avec la fonction scanf() c'est ça.

    Ci-dessous le code source (environs 45 lignes) :
    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
    56
    57
     
    // BIBLIOTHEQUES :
    // ======================================================================================
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
    // ======================================================================================
     
    // FONCTION VIDAGE DU BUFFER CLAVIER :
    // ======================================================================================
    void clean_stdin(void) 
    { 
        int c; 
     
        do
        { 
            c = getchar(); 
        } while (c != '\n' && c != EOF);
    }
    // ======================================================================================
     
    void main(void)
    {
    	// DECLARATION DES VARIABLES :
    	int note = 0;
    	float moyenne;
    	bool saisieNote = true;
    	int somme_note = 0;
    	int nombre_note = 0;
     
    	// ALGO :
    	while(saisieNote)
    	{
    		while(note < -1 || note > 20)
    		{
    			printf("Erreur !\n");
    			printf("Veuillez recommencer la saisie !\n");
    		}
     
    		printf("Entrez - 1 pour arretez la saisie.\n");
    		printf("Entrez une note : \n");
    		scanf("%d\n", &note);
     
    		nombre_note++;
    		somme_note = somme_note + note;
     
    		if(note == -1)
    			saisieNote = false;
     
    		clean_stdin();
    	}
     
    	moyenne =  (float) ( ((float)somme_note) / ((float)(nombre_note)) );
     
    	printf("Moyenne de la classe : %f\n", moyenne);
    }
    Es ce que quelqu'un à une idée ?
    Merci pour votre aide.

  2. #2
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 608
    Points : 43 579
    Points
    43 579
    Par défaut
    Pour commencer, tu dois analyser le retour de scanf.

    Je préfère l'utilisation de fonction fgets.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    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 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par zephyre Voir le message
    J'ai lu sur le site developpez.com, ici = https://c.developpez.com/faq/?page=G...buffer-clavier, comment vider le buffer clavier.
    C'est une mauvaise solution. Un buffer clavier ne se vide pas, il se gère. Et s'il contient des infos utiles? Si le programme est mis en sortie de pipe?
    chrtophe a donné la bonne solution. D'abord fgets() pour récupérer la ligne saisie, puis sscanf() pour extraire la note de la ligne. Et en vérifiant son retour pour savoir si elle a pu ou pas extraire ladite note.

    Quant à ton code, supprime le "\n" au scanf() et tu pourras saisir des notes.

    Citation Envoyé par zephyre Voir le message
    Je ne sais pas si vraiment le problème vient de là mais généralement avec la fonction scanf() c'est ça.
    Normal, scanf() est fait pour faire se la saisie "formatée" et pas de la saisie clavier. Si tu l'utilises pour un travail pour lequel elle n'a pas été prévue, normal que ça ne fonctionne pas correctement.

    Autres détail: il n'y a rien qui te choque dans la boucle while (note < -1 || note > 20)? Une boucle où rien ne change?? Et ton calcul? Tu additionnes la note y compris si elle vaut -1...
    Et t'as pas besoin de tout caster en float. Pour qu'une opération soit en float il suffit d'un seul float dans l'un des opérandes. Attention toutefois à l'ordre des opérations car dans un calcul style 10/3+1.0 le premier calcul 10/3 ne se fait pas en float. Donc un float suffit mais à condition qu'on le place de façon judicieuse.
    Et main() n'est pas de type void.
    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]

  4. #4
    Membre du Club
    Homme Profil pro
    Ingénieur
    Inscrit en
    Avril 2020
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2020
    Messages : 88
    Points : 48
    Points
    48
    Par défaut
    Bonjour,
    C'est noté, ou peut t'on trouver le code source de la fonction fgets() et de la fonction sscanf().
    En cherchant sur le net je n'ai trouvé que les prototypes de ces 2 fonctions ?
    Il faut déjà que je comprenne comment fonctionne ces 2 fonctions.
    Exemple ici :
    https://devdocs.io/c/io/fgets


    Citation Envoyé par Sve@r
    Autres détail: il n'y a rien qui te choque dans la boucle while (note < -1 || note > 20)? Une boucle où rien ne change?? Et ton calcul? Tu additionnes la note y compris si elle vaut -1...
    Et t'as pas besoin de tout caster en float. Pour qu'une opération soit en float il suffit d'un seul float dans l'un des opérandes. Attention toutefois à l'ordre des opérations car dans un calcul style 10/3+1.0 le premier calcul 10/3 ne se fait pas en float. Donc un float suffit mais à condition qu'on le place de façon judicieuse.
    Et main() n'est pas de type void.
    Je vais corriger tout ça.
    T'inquiète pas Sve@r, j'ai vraiment écrit mon code en quelques minutes.
    Je boucle à l'infini, y a pas de condition de sortie dans la boucle while.
    Et j'additionne le -1 dans le calcule de la moyenne.
    Laisse moi juste du temps.

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    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 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par zephyre Voir le message
    C'est noté, ou peut t'on trouver le code source de la fonction fgets() et de la fonction sscanf().
    Euh??? A priori je dirais "dans les sources de la libC". Mais je ne pense pas que ça t'apporte grand chose (en plus les trucs ils doivent être hardcodés de ouf que c'en sera incompréhensible).

    Citation Envoyé par zephyre Voir le message
    En cherchant sur le net je n'ai trouvé que les prototypes de ces 2 fonctions ?
    Il faut déjà que je comprenne comment fonctionne ces 2 fonctions.
    Tout ce qu'il y a à savoir c'est que fgets() fait saisir une chaine et que sscanf() peut extraire des éléments de cette chaine (et renvoie le nb d'éléments extraits ce qui permet de vérifier que ça a fonctionné)
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int saisieInt() {
    	char str[1024 + 1];
    	int n;
    	while (1) {
    		fputs("Entrez un nombre :", stdout); fflush(stdout);
    		fgets(str, 1024 + 1, stdin);
    		if (sscanf(str, "%d", &n) == 1) return n;
    		fputs("Vous n'avez pas saisi un nombre correct !!!\n", stdout);
    	}
    }
    Pas 100% robuste (si on a un abruti qui rentre plus de 1024 caractères ça va merder) mais ça peut résoudre 99% des cas. On peut faire 100% robuste mais on entre là dans un domaine de ratio "probabilité de risque/coût de développement pour s'en protéger".

    Citation Envoyé par zephyre Voir le message
    Laisse moi juste du temps.
    Ok, prends ton temps, on sera encore là quand tu reviendras
    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
    Membre du Club
    Homme Profil pro
    Ingénieur
    Inscrit en
    Avril 2020
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2020
    Messages : 88
    Points : 48
    Points
    48
    Par défaut
    Je connais maintenant les éléments de base en langage C.
    Je pense que c'est une bonne idée de lire le code source d'une fonction pour comprendre ce qu'elle fait.

    Cela permet de se familiariser avec la langage en question et en plus c'est excellent pour développer la logique algorithmique.
    Je vais donc essayer même si c'est hardcoder, et si j'y arrive pas je laisse tomber.

    Elle est sûrement installé sur le système en dur sinon mon programme serait incapable de tourner.
    La question c'est ou ?

    Comme ça je serai en mesure une fois que j'aurais acquis un certains niveau en langage C, de créer mes propres fonctions à partir de 0.
    Je sais qu'il faut faire absolument du code source qui puisse être réutilisable et portable d’où la recommandation d'utiliser les bibliothèques standards.
    Cependant dans un premier temps je ne pense pas que ce soit une bonne idée, car on ne réfléchis pas à l'algo qu'il y a derrière.
    On se contente "bêtement" d'appliquer la fonction.

    Et de plus on doit être capable de s'en sortir dans n'importe quelles situations, donc autant commencer par recoder (dans une certaine mesure) toutes les fonctions des bibliothèques standard.

    Je pense que c'est un excellent exercice en plus.

    Autrement dit, il est impossible d'innover si on ne maîtrise pas l'existant.

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    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 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par zephyre Voir le message
    Je pense que c'est une bonne idée de lire le code source d'une fonction pour comprendre ce qu'elle fait.
    Dans l'absolu oui. Dans la pratique...
    Là le souci c'est que tu t'attaques à des fonctions très bas niveau (elles vont lire le buffer). Mais bon fais tes propres expériences, les sources sont disponibles.

    Citation Envoyé par zephyre Voir le message
    Elle est sûrement installé sur le système en dur sinon mon programme serait incapable de tourner.
    Héhé... tu connais le C mais pas encore trop la chaine de compilation.
    La chaine de compilation, c'est ".c => .o => .so (ou .a) => exécutable". Mais l'exécutable n'a pas besoin des ".c" et ".o" pour tourner (il a quand-même besoin des ".so" mais ce sont eux-aussi des compilés).
    Mais t'es pas obligé de me croire. Donc tu crées un ".c" quelconque (qui dit "Hello"), tu le compiles, puis tu l'effaces => l'exécutable continuera de fonctionner.

    Citation Envoyé par zephyre Voir le message
    La question c'est ou ?
    De partout sur le net => https://android.googlesource.com/pla.../stdio/fgets.c

    Citation Envoyé par zephyre Voir le message
    Comme ça je serai en mesure une fois que j'aurais acquis un certains niveau en langage C, de créer mes propres fonctions à partir de 0.
    Je sais qu'il faut faire absolument du code source qui puisse être réutilisable et portable d’où la recommandation d'utiliser les bibliothèques standards.
    Cependant dans un premier temps je ne pense pas que ce soit une bonne idée, car on ne réfléchis pas à l'algo qu'il y a derrière.
    On se contente "bêtement" d'appliquer la fonction.
    C'est un peu pareil avec ceux qui construisent des avions. Ils ne s'embêtent pas à construire des roues, ils se contentent de "bêtement" acheter des roues standard car ce n'est pas ça qui fait la force d'un avion.
    Tu auras déjà pas mal de travail à créer ton algo en utilisant ce qui est disponible sur étagère, autant éviter de se mettre un handicap inutile. Je t'assure ça ne te fera pas progresser.

    Citation Envoyé par zephyre Voir le message
    Et de plus on doit être capable de s'en sortir dans n'importe quelles situations, donc autant commencer par recoder (dans une certaine mesure) toutes les fonctions des bibliothèques standard.
    Oui, et aussi être capable de faire du feu avec des silex, sait-on jamais si les briquets disparaissent...

    Citation Envoyé par zephyre Voir le message
    Je pense que c'est un excellent exercice en plus.
    Oui, excellent pour ceux qui ont un niveau plus élevé que "connaitre les bases". Pour ceux qui veulent écrire des drivers par exemple. Et pour ceux qui ont le temps

    Citation Envoyé par zephyre Voir le message
    Autrement dit, il est impossible d'innover si on ne maîtrise pas l'existant.
    Il faut aussi savoir faire la part des choses et s'autoriser un "niveau plancher" au dessous duquel il est inutile d'aller voir.
    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]

  8. #8
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 608
    Points : 43 579
    Points
    43 579
    Par défaut
    Pas 100% robuste (si on a un abruti qui rentre plus de 1024 caractères ça va merder) mais ça peut résoudre 99% des cas.
    En quoi ça va merder ? Si le buffer est dépassé avec fgets la lecture s'arrête non ?
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Salut
    Citation Envoyé par chrtophe Voir le message
    En quoi ça va merder ? Si le buffer est dépassé avec fgets la lecture s'arrête non ?
    Oui, a priori, tu n'auras pas de problème avec le contenu de str...

    Par contre, le buffer du clavier n'aura pas été vidé, car il y restera tous les caractères supplémentaires introduits par cet abruti

    C'est à dire que tu risques de te retrouver avec une sortie complètement à l'est à l'extraction suivante
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    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 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    En quoi ça va merder ? Si le buffer est dépassé avec fgets la lecture s'arrête non ?
    Citation Envoyé par koala01 Voir le message
    C'est à dire que tu risques de te retrouver avec une sortie complètement à l'est à l'extraction suivante
    Voilà. C'est à ça que je pensais
    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]

Discussions similaires

  1. vider le buffer clavier
    Par kyuubii_74 dans le forum x86 16-bits
    Réponses: 2
    Dernier message: 20/12/2010, 17h47
  2. [C] Problème pour vider un buffer clavier
    Par mickael777 dans le forum Windows
    Réponses: 7
    Dernier message: 08/11/2007, 17h05
  3. vider le buffer clavier
    Par josmiley dans le forum Général Python
    Réponses: 2
    Dernier message: 09/08/2007, 16h11
  4. vider le buffer clavier
    Par Pragmateek dans le forum C
    Réponses: 31
    Dernier message: 20/06/2006, 21h33

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