L'exécution passe outre une entrée

Discutez d'informatique ici !
Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 20:42

L'exécution passe outre une entrée

par Rockleader » 06 Mar 2014, 13:03

Je crois avoir déjà rencontré ce problème, mais je ne me rappelle plus de la solution


j'ai quelques chose de ce style là.

Code: Tout sélectionner
char continuer='o';


while(continuer=='o')
{

/*Traitement*/
printf("Voulez vous continuer ? (o/n)
scanf("%c",&continuer);

}


Mais quand je lance je ne boucle pas plus d'une fois et je ne peux pas faire la saisie dans le scanf.




EDIT: Si mes souvenirs sont bon c'est que scanf va lire un buffer qui n’est pas vide; il faut donc vider le buffer ? J'aurais bien utilisé free mais ça va carrément me supprimer l'espace mémoire non ?


EDIT2: Résolu, c'était getchar qui permet de vider le buffer ;)
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



Black Jack

par Black Jack » 07 Mar 2014, 16:14

Essaie ainsi :

char continuer='o';


while(continuer=='o')
{

/*Traitement*/
printf("Voulez vous continuer ? (o/n)
scanf("%c",&continuer);
getchar();

}

:zen:

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 20:42

par Rockleader » 07 Mar 2014, 16:42

Oui d'où mon EDIT2 datant d'hier, je crois que j'ai demandé de l'aide un peu trop vite ;)

Mais merci quand même pour la réponse !
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

joel76
Membre Relatif
Messages: 230
Enregistré le: 11 Fév 2013, 17:31

par joel76 » 07 Mar 2014, 20:38

Black Jack a écrit:Essaie ainsi :

char continuer='o';


while(continuer=='o')
{

/*Traitement*/
printf("Voulez vous continuer ? (o/n)
scanf("%c",&continuer);
getchar();

}

:zen:
Non, la bonne méthode est donnée ici :
Code: Tout sélectionner
void clean_stdin(void)
{
    int c;
 
    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 14:00

par fatal_error » 09 Mar 2014, 00:11

hello,

pourquoi faut-il utiliser getChar apres scanf?
la vie est une fête :)

joel76
Membre Relatif
Messages: 230
Enregistré le: 11 Fév 2013, 17:31

par joel76 » 09 Mar 2014, 01:13

Contrairement a une idée répandue, scanf ne vide pas le buffer de lecture, scanf lit un flux d'entrée et convertit les données tapées suivant le format indiqué.
La lecture s'arrête dès que toutes les données ont été lues ou qu'une conversion a échoué (c'est pour cela qu'il faut toujours tester le retour de scanf qui donne le nombre de conversions réussies).
Lorsqu'on lit un seul caractère, celui ci est mémorisé mais le retour chariot est laissé dans le buffer d'entrée et est récupéré par le scanf suivant.
Il vaut toujours mieux utiliser fgets (et pas gets qui est un bug) qui assure une saisie sécurisée, mais la saisie est à traiter ensuite.

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 09:03

par ampholyte » 09 Mar 2014, 01:15

Bonjour,

Seul le solution joel76 convient, en effet un seul getchar ne suffira pas forcément pour vider le buffer stdin.

Si l'utilisateur a écrit par exemple :
Voulez vous continuer ? (o/n) oui
alors un seul getchar() var lire le prochain caractère u et ne pas poursuivre la boucle par la suite à cause de la dernière lecture.

Avec la fonction clean_stdin proposé plus haut, stdin étant complètement vide, la fonction scanf va attendre une saisie utilisateur (ce qui n'était pas le cas plus haut vu que stdin possédait encore des données non lues).

@fatal_error, supposons le cas suivant :
Voulez vous continuer ? (o/n) o

Pour valider la réponse avec le code utilisé, il faut forcément un \n ou un EOF pour poursuivre le programme.
Le scanf ne récupérant qu'un seul caractère, le prochain caractère lu sera donc \n ou EOF d'où l'absence de répétition.

On en avait déjà discuter avec Rockleader sur une façon de faire avec un fgets qui je trouve est plus sécurisé.

Black Jack

par Black Jack » 14 Mar 2014, 19:57

On peut parfaitement utiliser le scanf() pour entrer une donnée ET ne pas avoir d'ennuis de buffer.

On en parle un peu sur ce lien : http://forum.ubuntu-fr.org/viewtopic.php?id=261815
avec quelque chose comme ceci : scanf ("%*[^\n]"), getchar ();

Il existe des écritures proches avec ou sans un espace devant le % (fonctionnements différents dans les 2 cas), mais je ne me rappelle plus vraiment comment cela marche.

On peut aussi supprimer les risques de débordement du à la longueur de l'entrée via scanf(), en ajoutant un nombre entre le % et de d par exemple dans une entrée %d.

Bref, le scanf peut être parfaitement sûr et sans problème de buffer si on l'utilise correctement ... mais bon nombre des propriétes du scanf() ne sont pas décrites dans beaucoup de bouquins et donc ignorées.

Le "scanf()" reste cependant assez difficile à utiliser de manière sûre si on n'a pas l'habitude de ses propriétés trop souvent non expliquées dans beaucoup de documentations.

Et comme on peut parfaitement faire autrement ...

:zen:

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 5 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite