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

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Sans emploi
    Inscrit en
    août 2019
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Belgique

    Informations professionnelles :
    Activité : Sans emploi

    Informations forums :
    Inscription : août 2019
    Messages : 26
    Points : 28
    Points
    28
    Par défaut Alternative à fflush(stdin) via getchar, Saisie utilisateur attendue.
    Bonsoir,

    On vient d'avoir cours de C.

    Mais on a vu une fonction alternative à fflsuh(stdin) avec le professeur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void viderBuffer()
    {
        int c=0;
        //Temps que C est différent de la fin de la chaine
        while(c!='\n' && c!=EOF)
        {
            c=getchar();
        }
    }
    J'essaie de l'utiliser comme un fflush(stdin) mais il me semble que le getchar() attends une saisie de ma part quand je lance le programme. Donc je ne sais pas si il manque quelque chose à la fonction ou que ça s'utilise différemment que fflush(stdin)? (Pour vider le buffer).


    Merci.

  2. #2
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    12 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 12 212
    Points : 27 294
    Points
    27 294
    Par défaut
    getchar attend que quelque chose soit saisie sur la console avant de te rendre la main. Le test de ta boucle while ne sera fait qu'ensuite. Donc si le buffer contient des caractères, stdin sera "vidé", sinon getchar attendra une entrée avant de rendre la main.

    Par contre, si tu fais une boucle do...while, un caractère sera lu au minimum (1ère passe de la boucle), le test sera fait ensuite, si il ne reste aucun caractère (test EOF et '\n'), la boucle s'arrête .
    Regarde ceci :
    https://c.developpez.com/faq/?page=G...buffer-clavier
    regarder les entrées suivantes de la FAS notamment sur le mode cooked/raw, ça te fera une leçon en plus.

    et :
    Pourquoi ne faut-il pas utiliser fflush(stdin) pour vider le buffer clavier ?
    Dans certaines implémentations, lorsque stdin est attaché au clavier, fflush(stdin) supprime tous les caractères encore présents dans le buffer du clavier. Appliquer fflush sur un flux entrant, comme stdin, n'est cependant pas portable, car la norme ne précise l'effet de fflush que sur un flux sortant.


    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Sans emploi
    Inscrit en
    août 2019
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Belgique

    Informations professionnelles :
    Activité : Sans emploi

    Informations forums :
    Inscription : août 2019
    Messages : 26
    Points : 28
    Points
    28
    Par défaut
    J'ai reçus le code complet du cours entre temps...

    La fonction reste la même sans faire de do{}while(...); c'est fonctionnel. Donc les deux fonctions ici dont celle qui utilise la fonction viderBuffer.

    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
     
    void viderBuffer()
    {
    	int c = 0;
    	while (c != '\n' && c != EOF)
    	{
    		c = getchar();
    	}
    }
     
    int lire(char *chaine, int longueur)
    {
    	char *positionEntree = NULL;
    	if (fgets(chaine, longueur, stdin) != NULL)
    	{
    		positionEntree = strchr(chaine, '\n');
    		if (positionEntree != NULL)
    		{
    			*positionEntree = '\0';
    		}
    		else
    		{
    			viderBuffer();
    		}
    		return 1;
    	}
    	else
    	{
    		viderBuffer();
    		return 0;
    	}
    }
    Je ne saisis pas bien pourquoi ça marche ainsi. fgets à effectivement stdin en paramètre ici c'est peut être ça...Mais dès lors je ne comprends pas que stdin est impliqué dans viderBuffer car aucun paramètre lui est envoyer.
    J'avais utilisé la commande viderBuffer() après la fonction lire() lors de mon précédent post et ça faisait le bug. ici ça marche.

    Bref devrait comprendre tout ceci...Merci pour le lien et les explications.

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 825
    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 : 7 825
    Points : 21 397
    Points
    21 397
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Kitsune64 Voir le message
    Mais dès lors je ne comprends pas que stdin est impliqué dans viderBuffer car aucun paramètre lui est envoyer.
    Parce que getchar() travaille en natif sur stdin et que stdin correspond au clavier (sauf dans le cas de pipes mais je pense qu'on n'en est pas encore là).

    Citation Envoyé par Kitsune64 Voir le message
    Je ne saisis pas bien pourquoi ça marche ainsi
    fgets() lit une ligne entière. Or une ligne c'est une suite de caractères terminée par '\n'. Et '\n' correspond au <return> que tu tapes quand tu valides ta saisie.
    Donc fgets() lit tout ce qui a été entré au clavier. Le clavier étant entièrement lu, il est alors vide et n'a pas besoin d'être vidé.

    Toutefois fgets(chaine, n, buffer) peut s'arrêter avant '\n', quand elle a lu "n-1" caractères (elle en réserve un pour y mettre le '\0' de fin de chaine). Donc il peut arriver des cas où le clavier n'est pas vide. Si par exemple tu en tapes 200 mais que fgets() s'arrête à 150, il en reste 50 dans stdin.

    Donc une fois la saisie faite, le code commence par chercher si la chaine saisie contient '\n'. Si c'est le cas, ce '\n' est alors remplacé par un '\0' pour qu'il ne mette pas la zone dans le traitement de la chaine saisie. Et si la chaine saisie ne contient pas de '\n', ça veut dire que stdin n'a pas été entièrement lu et le code purge alors ce qui reste. Ce qui n'est pas forcément une bonne idée !!!

    Car ce qui est dans stdin y a été mis pour une bonne raison (l'utilisateur l'a saisi ou alors ça provient d'un autre programme dans le cas d'un pipe comme j'en ai déjà parlé). Et donc quoi qu'il en soit, supprimer de la donnée potentiellement utile n'est jamais une bonne idée (c'est d'ailleurs pour cette raison que fflush() n'est pas implémenté pour stdin).
    Donc en réalité, si tu ne lis pas toute la ligne d'un coup lors du fgets(), c'est souvent l'indice de code mal pensé à rectifier au plus tôt (soit en augmentant la zone de lecture, soit en utilisant d'autres outils de lecture comme par exemple getline() qui adapte automatiquement la zone de récupération en fonction de la taille de la ligne à lire).

    Citation Envoyé par Kitsune64 Voir le message
    Mais on a vu une fonction alternative à fflsuh(stdin) avec le professeur.
    Et c'est là que ton prof a raté un truc car au lieu de t'apprendre comment réaliser une alternative à une fonction qui avait été volontairement non implémentée (parce qu'inutile), il aurait dû t'apprendre comment bien prendre en compte tout le contenu de stdin lors d'une saisie quelconque.
    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

  5. #5
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    12 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 12 212
    Points : 27 294
    Points
    27 294
    Par défaut
    Parce que getchar() travaille en natif sur stdin
    Oui d’ailleurs la doc précise :

    getchar() est équivalent à getc(stdin).
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

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

Discussions similaires

  1. Envoyer une saisie utilisateur via INJECT_EVENTS
    Par samus35 dans le forum Android
    Réponses: 4
    Dernier message: 14/03/2013, 14h17
  2. [langage] fin de saisie utilisateur
    Par Kinethe dans le forum Langage
    Réponses: 4
    Dernier message: 24/06/2004, 15h19
  3. [langage] saisie utilisateur
    Par caro_du_94 dans le forum Langage
    Réponses: 13
    Dernier message: 03/06/2004, 19h05
  4. fflush(stdin)
    Par lestat dans le forum C
    Réponses: 9
    Dernier message: 23/03/2004, 12h46
  5. fflush(stdin)
    Par BURZUM dans le forum C
    Réponses: 2
    Dernier message: 06/01/2004, 11h59

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