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 :

Le buffer et les entrées au clavier


Sujet :

C

  1. #1
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Points : 199
    Points
    199
    Par défaut Le buffer et les entrées au clavier
    Bonjour,


    J'ai quelques difficultés à bien maîtriser les différentes approches pour faire une saisie au clavier en langage C.
    Je suis en 1ère année de DUT info et j'ai différents sons de cloches entre les FAQ, les tutoriels et les cours de mes professeurs
    La FAQ C m'a bien aidé, mais j'ai encore besoin de quelques éclaircissements :


    1) Le buffer
    Quand on effectue une saisie avec scanf / gets / getchar, le caractère '\n' reste dans le buffer.
    Mes profs m'ont dit d'utiliser fflush(stdin) pour le vider, mais lorsque je teste chez moi je me rends compte que ça marche absolument pas (j'utilise GNU/Linux et GCC).
    Est-ce que ça marche sur certaines plate-formes et pas sur d'autres ? Quel est l'utilité de fflush(stdin) alors ?

    Je codais déjà un peu en C avant de rentrer en IUT, et j'ai l'habitude d'utiliser pour vider le buffer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (getchar() != '\n');
    (En fait, je n'avais encore j'avais vu fflush() auparavant)
    Mais la FAQ préconise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int c;
    while ((c = getchar()) != '\n' && c != EOF); /* mange le tampon */
    Qu'est-ce que ce code fait de mieux ? Comment un caractère EOF peut se retrouver dans le buffer puisqu'on valide les saisies avec la touche enter, qui correspond à '\n' ?


    2) La saisie d'un caratère :
    Est-ce qu'il y a une différence entre :
    et :

    3) Passons aux chaînes de caractères :
    Mes profs m'ont dit d'utiliser uniquement gets(texte); , tout en condamnant l'usage de scanf("%s", texte); .
    Je sais bien qu'aucune de ces fonctions n'est faite pour interagir avec l'utilisateur, et qu'il faut utiliser fgets(), mais je me pose les question suivantes :
    - Quelle est la différence entre gets(texte); et scanf("%s", texte); ?
    J'ai remarqué qu'on peut faire un scanf("%d", &entier); entre deux scanf("%s", texte); , alors qu'on ne peut pas le faire entre deux gets(texte); .
    Pourquoi ? Un '\n' ne devrait-il pas rester dans le buffer et être mangé par le deuxième scanf("%s", texte); avant que la saisie n'ait lieu ?
    - Pourquoi gets me donne droit un avertissement à la compilation (the `gets' function is dangerous and should not be used.) ? Mes profs m'ont dit que c'est scanf("%s", texte) qui est à bannir.


    Merci
    <3 Debian
    [ C | C++ | PHP | Python ]

  2. #2
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Holala, Emmanuel Delahaye va encore partir en croisade contre l'enseignement du C en France... En effet, il semble que tu en connaisses plus que tes professeurs.

    Citation Envoyé par Haze. Voir le message
    Est-ce que ça marche sur certaines plate-formes et pas sur d'autres ? Quel est l'utilité de fflush(stdin) alors ?
    fflush() ne fonctionne que sur les flux sortants (stdout, stderr, fichiers ouverts en écriture). Certaines implémentations ont ajouté la possibilité de vider le tampon des flux entrants via fflush(), mais c'est une extension à la norme, donc à éviter si l'on cherche la portabilité.

    Qu'est-ce que ce code fait de mieux ? Comment un caractère EOF peut se retrouver dans le buffer puisqu'on valide les saisies avec la touche enter, qui correspond à '\n' ?
    stdin peut être en fait un fichier (redirection). Ce n'est pas toujours un utilisateur "interactif".


    Est-ce qu'il y a une différence entre :
    et :
    getchar() est plus propre, je trouve.


    Mes profs m'ont dit d'utiliser uniquement gets(texte); , tout en condamnant l'usage de scanf("%s", texte);
    Les deux sont à banir, pour la même raison : la taille du tableau de destination n'est pas connue par les fonctions. gets() est un bug, puisqu'elle ne peut pas être utilisée de facon sécure. C'est pourquoi les compilateurs modernes et les pages man avertissent de ne pas l'utiliser. fgets() toujours.

  3. #3
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par DaZumba Voir le message
    Holala, Emmanuel Delahaye va encore partir en croisade contre l'enseignement du C en France...
    Vous avez de la chance que je sois affaibli par un satané virus...
    Pas de Wi-Fi à la maison : CPL

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Haze. Voir le message
    <...> Mes profs m'ont dit d'utiliser fflush(stdin) pour le vider, <...>

    Mes profs m'ont dit d'utiliser uniquement gets(texte); , tout en condamnant l'usage de scanf("%s", texte); .
    <...>
    On peut savoir où sont enseignées ces âneries ?
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Points : 199
    Points
    199
    Par défaut
    Merci DaZumba pour tes explications.
    Pour les chaînes de caractères, il y a encore un dernier point que je n'ai pas saisi : la différence entre scanf("%s") et gets().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char texte[15]; 
    int i;
    scanf("%d", &i);
    gets(texte);
    printf("%s - %d\n", texte, i);
    On ne peut pas saisir <texte> à l'exécution, normal vu que le gets() mange le '\n' qui restait dans le buffer.
    Mais pourquoi est-ce que c'est possible avec un scanf() ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char texte[15]; 
    int i;
    scanf("%d", &i);
    scanf("%s", texte);
    printf("%s - %d\n", texte, i);
    Et quels sont concrètement les dangers avec ces deux fonctions ? Par exemple, si je saisis un texte d'une longueur de 50 caractères, est-ce que ça veut dire que la chaîne sera inscrite en mémoire depuis l'adresse de texte[0] jusqu'à celle de texte[sizeof(char) * 50] ? (et écrasant ainsi les contenus des cases mémoires qui pourraient appartenir à n'importe quoi d'autre, j'ai bon ?)

    Citation Envoyé par Emmanuel Delahaye
    On peut savoir où sont enseignées ces âneries ?
    À l'IUT Informatique de PARIS 5 (Université René Descartes). Il paraît qu'elle est en top du classement des IUT Info en France.
    On nous a fait gentiment comprendre que tout ce qu'on avait pu apprendre de nous même, c'était du grand n'importe quoi.
    <3 Debian
    [ C | C++ | PHP | Python ]

  6. #6
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Citation Envoyé par Haze. Voir le message
    Merci DaZumba pour tes explications.
    Pour les chaînes de caractères, il y a encore un dernier point que je n'ai pas saisi : la différence entre scanf("%s") et gets().
    Je pense que y'en a pas.. T'es sur que le prof a pas dit fgets() ?


    À l'IUT Informatique de PARIS 5 (Université René Descartes). Il paraît qu'elle est en top du classement des IUT Info en France.
    On nous a fait gentiment comprendre que tout ce qu'on avait pu apprendre de nous même, c'était du grand n'importe quoi.
    Viens Emmanuel on va leur peter la gueule

  7. #7
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Haze. Voir le message
    Pour les chaînes de caractères, il y a encore un dernier point que je n'ai pas saisi : la différence entre scanf("%s") et gets().
    Les 2 sont aussi dangereuses.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char line[128];
     
    scanf ("%127s", line);
    l'est moins, mais la maintenance est cauchemardesque...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char texte[15]; 
    int i;
    scanf("%d", &i);
    gets(texte);
    printf("%s - %d\n", texte, i);
    On ne peut pas saisir <texte> à l'exécution, normal vu que le gets() mange le '\n' qui restait dans le buffer.
    Mais pourquoi est-ce que c'est possible avec un scanf() ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char texte[15]; 
    int i;
    scanf("%d", &i);
    scanf("%s", texte);
    printf("%s - %d\n", texte, i);
    Si tu veux vraiment apprendre à utiliser scanf() , il faut en prendre les moyens, et crois moi, c'est pas simple :

    http://xrenault.developpez.com/tutoriels/c/scanf/
    Et quels sont concrètement les dangers avec ces deux fonctions ? Par exemple, si je saisis un texte d'une longueur de 50 caractères, est-ce que ça veut dire que la chaîne sera inscrite en mémoire depuis l'adresse de texte[0] jusqu'à celle de texte[sizeof(char) * 50] ? (et écrasant ainsi les contenus des cases mémoires qui pourraient appartenir à n'importe quoi d'autre, j'ai bon ?)
    Oui. "buffer overflow". Ca provoque un comportement indéfini.
    À l'IUT Informatique de PARIS 5 (Université René Descartes). Il paraît qu'elle est en top du classement des IUT Info en France.
    On nous a fait gentiment comprendre que tout ce qu'on avait pu apprendre de nous même, c'était du grand n'importe quoi.
    Une vrai caricature de fac à la française.... Ils nous vantent

    Intelligence Artificielle (IA) Signal Parole Image Réseaux (SPIR)

    et ils ne savent faire des I/O en C...
    Pas de Wi-Fi à la maison : CPL

  8. #8
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Points : 199
    Points
    199
    Par défaut
    Citation Envoyé par Gruik
    T'es sur que le prof a pas dit fgets() ?
    J'en suis sûr (comme je l'ai dit, j'avais déjà fait un peu de C avant d'assister aux cours).
    D'ailleurs, le prof en question avait reproché aux compilateurs de mettre un avertissement quand on utilise gets().

    Citation Envoyé par Emmanuel Delahaye
    ils ne savent faire des I/O en C...
    Même si je suis très surpris (et déçu, car les system("PAUSE") et system("CLS") sont aussi de la partie) de la manière dont on nous enseigne le C, je ne pense pas que ce soit une simple histoire d'incompétence, car les profs ont plutôt l'air expérimentés.
    Je crois que ça vient surtout du désir de l'équipe enseignante de mettre tout le monde au même niveau, tout en invoquant le fallacieux prétexte de "l'approche pédagogique" à tord et à travers.

    Et merci pour la doc, je suis encore loin de maîtriser toutes les subtilités de scanf (et de plein d'autres choses encore).

    Vivement les premiers projets '^^
    <3 Debian
    [ C | C++ | PHP | Python ]

  9. #9
    Membre régulier
    Inscrit en
    Juillet 2002
    Messages
    168
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 168
    Points : 110
    Points
    110
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Les 2 sont aussi dangereuses.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char line[128];
     
    scanf ("%127s", line);
    l'est moins, mais la maintenance est cauchemardesque...

    Si tu veux vraiment apprendre à utiliser scanf() , il faut en prendre les moyens, et crois moi, c'est pas simple :

    http://xrenault.developpez.com/tutoriels/c/scanf/

    Oui. "buffer overflow". Ca provoque un comportement indéfini.
    Une vrai caricature de fac à la française.... Ils nous vantent

    Intelligence Artificielle (IA) Signal Parole Image Réseaux (SPIR)

    et ils ne savent faire des I/O en C...
    sacré Emmanuel
    Demain n'est plus à attendre mais à inventer !!!

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

Discussions similaires

  1. Ecrire dans un fichier texte les entrées du clavier
    Par Manou1980 dans le forum Entrée/Sortie
    Réponses: 8
    Dernier message: 07/07/2011, 10h51
  2. [SWING] gérer les entrées clavier à un seul endroit
    Par Isher dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 19/07/2006, 10h55
  3. Réponses: 2
    Dernier message: 01/12/2005, 12h24
  4. [Entrée standard] Prendre les entrées clavier.
    Par Katyucha dans le forum Langage
    Réponses: 4
    Dernier message: 19/09/2005, 12h22
  5. Réponses: 3
    Dernier message: 04/02/2004, 18h35

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