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 :

ne pas prendre en compte \n dans scanf


Sujet :

C

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    280
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 280
    Points : 149
    Points
    149
    Par défaut ne pas prendre en compte \n dans scanf
    Bonjour,

    j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
    #include <ctype.h>
     
    int main () {
        char i='b';
        while (i!='A'&&i!='E'&&i!='O'&&i!='U'&&i!='Y'&&i!='I'){
            printf("tapez :");
            scanf("%c",&i);
            fflush(stdin);
            i=toupper(i);
        }
        return 0;
    }
    Comment éviter que l'invite "tapez" n'apparaisse deux fois après une première saisie à cause du retour à la ligne encore dans l'entrée standard.

    J'ai essayé fflush(stdin); mais ça ne marche pas...

    Pardon pour cette question de gros gros gros débutant... et merci
    "Bien qu'on ait du coeur à l'ouvrage,
    L'Art est long et le Temps est court." - CB

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    280
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 280
    Points : 149
    Points
    149
    Par défaut Précision
    En fait je viens d'esayer sous Windows ça marche trés bien.
    Mon premier essai était sous linux openSUSE sur cet environnement on dirait que fflush n'est pas pris en compte... Il répète autant de fois l'invite qu'il y a de caractères dans la saisie précécente. Comment ça se fait ?
    "Bien qu'on ait du coeur à l'ouvrage,
    L'Art est long et le Temps est court." - CB

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    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 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Citation Envoyé par PyNub Voir le message
    En fait je viens d'esayer sous Windows ça marche trés bien.
    Mon premier essai était sous linux openSUSE sur cet environnement on dirait que fflush n'est pas pris en compte... Il répète autant de fois l'invite qu'il y a de caractères dans la saisie précécente. Comment ça se fait ?
    fflush() ne fait pas ce que tu crois : http://www.developpez.net/forums/d10...r/#post6047558

    Le comportement le plus « logique » de fflush(stdin) est justement de laisser le buffer en l'état.

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    280
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 280
    Points : 149
    Points
    149
    Par défaut
    Mais alors comment vider le buffer clavier juste après ma saisie ? Je vais essayer la fonction dans la FAQ...
    Comment se fait-il que ça marche sous windows ? Je vais essayer de voir le comportement en enlevant le fflush...
    Merci
    "Bien qu'on ait du coeur à l'ouvrage,
    L'Art est long et le Temps est court." - CB

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    280
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 280
    Points : 149
    Points
    149
    Par défaut
    c'est bien fflush(stdin) qui vide l'entrée standard sous windows. En l'enlevant je retrouve le même comportement que sous linux
    "Bien qu'on ait du coeur à l'ouvrage,
    L'Art est long et le Temps est court." - CB

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    280
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 280
    Points : 149
    Points
    149
    Par défaut
    Sous linux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
     
    void clean_stdin(void)
    {
        int c;
     
        do {
            c = getchar();
        } while (c != '\n' && c != EOF);
    }
    Marche... Merci encore une fois.
    Mais pourquoi sous windows le fflush fonctionne. J'utilise le compilateur de Visual Studio peut être est ce lié ?
    "Bien qu'on ait du coeur à l'ouvrage,
    L'Art est long et le Temps est court." - CB

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    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 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Citation Envoyé par PyNub Voir le message
    Mais alors comment vider le buffer clavier juste après ma saisie ? Je vais essayer la fonction dans la FAQ...
    Comment se fait-il que ça marche sous windows ? Je vais essayer de voir le comportement en enlevant le fflush... Merci
    Parce que, comme indiqué dans la FAQ, la norme ne spécifie les actions effectuées que dans le cas d'un flux en écriture et dont la dernière opération n'est pas une lecture (cas des flux en rw) et indique clairement que tout autre cas de figure résulte en un comportement non défini par la norme :

    Citation Envoyé par n1256
    7.19.5.2 The fflush function
    Synopsis
    1 #include <stdio.h>
    int fflush(FILE *stream);

    Description
    2 If stream 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.

    3 If stream is a null pointer, the fflush function performs this flushing action on all
    streams for which the behavior is defined above.

    Returns
    4 The fflush function sets the error indicator for the stream and returns EOF if a write
    error occurs, otherwise it returns zero.
    … et

    J.2 Undefined behavior
    1 The behavior is undefined in the following circumstances:



    — The stream for the fflush function points to an input stream or to an update stream in which the most recent operation was input (7.19.5.2).



    — An output operation on an update stream is followed by an input operation without an intervening call to the fflush function or a file positioning function, or an input operation on an update stream is followed by an output operation with an intervening
    call to a file positioning function (7.19.5.3).


    Ce comportement étant « indéfini », certains systèmes y voient une forme de liberté et l'implémentent comme ils l'entendent. C'est mal parce que, d'une part, cela fait prendre d'emblée de mauvaises habitudes aux débutants et, d'autre part, parce que comme dit plus haut, « fflush » n'a pas du tout vocation à « effacer » un buffer et à détruire son contenu. Au contraire, il sert à provoquer leur envoi immédiat vers leur destinataire.

    Note bien que cela ne « marche » pas plus dans l'autre sens : si tu fais un fflush(stdout), tu envoies les données vers le fichier ou le pipe concerné et tu vides ainsi ton buffer, certes, mais tu ne peux pas t'en servir pour « abandonner » ce qui y a été écrit. Même si ton programme se termine, le contenu du buffer sera quand même envoyé, sauf en cas de mort violente (kill -9).

    D'autre part, il se peut également que fflush(stdin), même lorsqu'il fonctionne, ne suffise pas à vider le buffer clavier : cette fonction agit sur le buffer du processus, mais pas sur ce qu'il y a en amont et ce qui est géré par le système, spécialement quand il s'agit d'un terminal en mode ligne.

    Enfin, détail non négligeable : ça ressemble à de la programmation système mais, en fait, fflush() fait partie de la norme C. Ça veut dire que — même en programmant sous Windows — ton programme peut très bien cesser de fonctionner comme il le fait actuellement si tu le recompiles avec un autre compilateur. À dire vrai, celui-ci peut très bien décider, en tant que compilateur C, d'ignorer purement et simplement l'instruction fflush() s'il peut affirmer de façon certaine que le flux qu'il traite à un moment donné est en lecture seule. Il aurait le droit de le faire parce que c'est dans son périmètre.

    Donc, pour toutes ces raisons, c'est Linux qui est le plus « dans le vrai ». D'abord parce que cela force directement le programmeur à adopter le bon comportement, mais ensuite et surtout parce que même d'un point de vue sémantique, « fflush() » n'a jamais signifié « effacement du buffer » et que donc, en principe, cette idée ne devrait jamais être venue à un programmeur. Si elle y parvient, c'est qu'il s'agit d'une erreur de compréhension.

    Relis bien les discussions derrière le lien que je t'ai donné. Tu y trouveras non seulement une explication détaillée mais également des solutions de vidage propres.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    280
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 280
    Points : 149
    Points
    149
    Par défaut
    Merci d'avoir pris le temps de me donner toutes ces précisions.

    « fflush » n'a pas du tout vocation à « effacer » un buffer et à détruire son contenu. Au contraire, il sert à provoquer leur envoi immédiat vers leur destinataire.
    en effet tout le contraire de ce que je voulais faire...
    "Bien qu'on ait du coeur à l'ouvrage,
    L'Art est long et le Temps est court." - CB

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 06/03/2013, 13h00
  2. Réponses: 2
    Dernier message: 23/07/2012, 16h09
  3. Réponses: 7
    Dernier message: 16/11/2011, 14h18
  4. Réponses: 6
    Dernier message: 10/02/2011, 08h38
  5. [XL-2003] Masquer une cellule et ne pas prendre en compte sa valeur dans les calculs
    Par *.Har(d)t dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 30/10/2009, 11h07

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