Fonction scanf pas exécutée
Résolu/Fermémamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 - 20 oct. 2022 à 11:15
- Fonction scanf pas exécutée
- Fonction si et - Guide
- Fonction moyenne excel - Guide
- Fonction somme excel - Guide
- Excel remplir automatiquement une cellule en fonction d'une autre ✓ - Forum Excel
- Fonction remplacer word - Guide
4 réponses
Modifié le 9 oct. 2022 à 22:27
Pour reproduire ce que tu as constaté, essaye le code suivant :
#include <stdio.h> int main(void) { printf("Veuillez taper un entier\n"); int n; scanf("%d", &n); printf("J'ai récupéré : [%d]\n", n); printf("Veuillez taper un caractère et taper entrée\n"); char c; scanf("%c", &c); printf("J'ai récupéré : [%c]\n", c); return 0; }
Si on exécute ce code en tapant 12 et entrée, le 2ème scanf() n'interrompt pas le programme (l'exécution semble "sauter" le scan() suivant) et cela produit ceci :
$ gcc -Wall -Wextra 37704224.c
$ ./a.out
Veuillez taper un entier
12
J'ai récupéré : [12]
Veuillez taper un caractère et taper entrée
J'ai récupéré : [
]
Il s'est passé la chose suivante :
- on a tapé 12 et Entrée
- scanf() a seulement récupéré 12 et a laissé Entrée dans le tampon de stdin
- en fait le scanf() suivant n'est pas sauté, il consomme juste le prochain char disponible dans le tampon de stdin
- le caractère entrée a donc été lu par le prochain scanf(), comme on peut le constater dans l'affichage du char récupéré que l'on tente d'afficher entre crochets
scanf() laisse toujours, au moins, le caractère de retour à la ligne '\n' dans le tampon de stdin.
Il peut laisser plus que cela (par exemple, si on avait tapé "12toto" et Entrée, le premier scanf() n'aurait récupéré que 12 et aurait laissé "toto" et Entrée dans stdin qui pourront être consommés par le(s) prochain(s) appel(s) à scanf().
Pour être sûr que le tampon de stdin est vide, après chaque scanf() on peut faire ceci :
int c; while((c = getchar()) != '\n' && c != EOF) /* on consomme tout ce qui reste dans stdin */ ;
On peut mettre ces lignes telles quelles dans une fonction empty_stdin() et l'appeler après chaque appel à scanf().
Modifié le 10 oct. 2022 à 00:17
II peut arriver que le terminal buffer les touches et donc que tu ne penses pas avoir appuyé sur une touche, mais que si en fait.
Je te propose de changer ton
printf("ça marche\n");
en
printf("ça marche code %d caractere %c c'est bon\n", propose, propose);
Comme ça ça va t'afficher la touche vue avec son code.
Si tu vois que code à 0 c'est un nul qui est récupéré, sinon, regarde le résultat.
Concernant le CoreDump, je suspecte plutôt une autre cause.
Mais je ne fais pas de C/C++ habituellement, donc je ne saurais aller plus loin sans plus de détail (et même là, je ne garanti pas).
Modifié le 20 oct. 2022 à 11:18
Bonjour,
Si on parlait d'un flux dans lequel on écrit, on aurait envie d'utiliser la fonction fflush. Malheureusement, comme l'explique cet article, on ne peut pas l'utiliser pour stdin.
On peut toutefois, comme le suggère [Dal] (#5), consommer les caractères résiduels en écrivant une fonction qui va s'en charger. C'est ce qui est proposé ici. Si je reprends le code proposé par [Dal] (#3) on aboutit à ceci :
#include <stdio.h> void clear_stdin() { for (int c = 0; c != '\n' && c != EOF; c = getchar()); } int main() { int n; printf("Veuillez taper un entier puis entrée\n"); scanf("%d", &n); clear_stdin(); printf("J'ai récupéré : [%d]\n", n); char c; printf("Veuillez taper un caractère puis entrée\n"); scanf("%c", &c); clear_stdin(); printf("J'ai récupéré : [%c]\n", c); return 0; }
Ce qui donne à l'exécution :
Veuillez taper un entier puis entrée
123
J'ai récupéré : [123]
Veuillez taper un caractère puis entrée
a
J'ai récupéré : [a]
9 oct. 2022 à 18:43
Résolution du souci de lecture de la variable :
la variable s'appelant 'propose' je l'ai renommée en un nom plus court : 'try'.
Ça a résolu mon affaire de scanf.
Je ne comprends pas.
9 oct. 2022 à 23:01
-_-
Donc dans un monde parfait en C il faudrait s'assurer que les tampons sont systématiquement vides histoire de ne pas se retrouver avec une cabriole du genre de ce que je rencontre régulièrement?
Modifié le 9 oct. 2022 à 23:46
stdin est un flux bufferisé.
Si ton code n'utilise qu'une partie de son contenu, mais s'attend à ce qu'il soit vide, c'est évident que tu vas au devant de comportements inattendus.
Ton utilisation de scanf() ne vide pas le tampon.
fgets() sur stdin ne le vide que si la ligne lue, y compris le '\n', tient dans la taille spécifiée dans le 2ème argument. Si la taille est insuffisante, le tampon conservera les char non consommés.
Pour que le tampon de stdin soit vide, il faut que ton code consomme ce qui s'y trouve. C'est tout.
Lorsque tu utilises ces fonctions, tu dois savoir comment elles fonctionnent, pour savoir déterminer si le tampon doit être vidé ou pas selon ce que tu as fait et ce que tu veux faire par la suite.
Modifié le 10 oct. 2022 à 00:12
Voilà un exemple de programme où on utilise le comportement de scanf() sur le buffer stdin pour lire en boucle ce qui s'y trouve tant qu'il y a des entiers à traiter.
cela donne, à l'exécution :
Notre programme consomme les entiers présents dans le tampon de stdin et ne vide pas le tampon entre chaque appel à scanf() parce qu'il est conçu pour traiter ce qui s'y trouve par appels successifs.
Quand scanf() retourne autre chose que 1, c'est qu'autre chose qu'un entier séparé par des caractères "blancs" a été rencontré, et on termine la boucle.
https://cplusplus.com/reference/cstdio/scanf/#return