Buffer scanf
Fermé
Ed Edson
-
8 oct. 2013 à 11:03
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 - 8 oct. 2013 à 15:00
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 - 8 oct. 2013 à 15:00
A voir également:
- Vider buffer c
- Vider les cookies - Guide
- Vider le cache d'une application - Guide
- Vider la corbeille - Guide
- Vider corbeille whatsapp - Guide
- Vider memoire iphone - Guide
3 réponses
Utilisateur anonyme
Modifié par orinym le 8/10/2013 à 11:50
Modifié par orinym le 8/10/2013 à 11:50
Bonjour, as-tu essayé avec %s à a place de %c?
Le scanf attend un caractère avec %c et non pas une chaine de caractère.
C'est pour cela qu'il lit le premier caractère (t) puis passe au scanf suivant qui lit le deuxième caractère (r).
Si tu mets d'autres scanf, tu devrais lire caractère par caractère le reste de ton entrée standard.
Si tu remplaces le %c par un %s, si je me souviens bien, le scanf attend non pas un caractère mais une chaine de caractère, il lira donc l'entrée standard jusqu'à la fin de la chaine.
Cordialement.
Le scanf attend un caractère avec %c et non pas une chaine de caractère.
C'est pour cela qu'il lit le premier caractère (t) puis passe au scanf suivant qui lit le deuxième caractère (r).
Si tu mets d'autres scanf, tu devrais lire caractère par caractère le reste de ton entrée standard.
Si tu remplaces le %c par un %s, si je me souviens bien, le scanf attend non pas un caractère mais une chaine de caractère, il lira donc l'entrée standard jusqu'à la fin de la chaine.
Cordialement.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
8 oct. 2013 à 14:57
8 oct. 2013 à 14:57
La solution est de vider le buffer clavier :
Cdlt,
int c;
while ( (c=getchar()) != '\n') && c != EOF );
Cdlt,
[Dal]
Messages postés
6198
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
13 décembre 2024
1 096
Modifié par [Dal] le 8/10/2013 à 15:04
Modifié par [Dal] le 8/10/2013 à 15:04
Salut Ed Edson,
Ce n'est pas trivial de saisir une chaine en C.
1.
Je complète la réponse de orinym, qui dit très exactement qu'il conviendrait d'utiliser %s au lieu de %c si tu veux récupérer plus qu'un caractère.
Cependant, il faut savoir qu'avec simplement "%s", scanf s'arrêtera en fin de ligne, mais aussi au premier "blanc" trouvé (espace ou tabulation), en laissant le reste dans le flux.
Vois la documentation de scanf.
Donc, si la chaîne que tu veux récupérer comporte des espaces, par exemple "Bonjour toi", tu ne récupères que "Bonjour\0" et " toi\n" restent dans le flux.
2.
De plus, comme tu n'as pas montré le type de tes variables "monChar1" et "monChar2" (et que, si on se fie au nom, il y a des chances que tu aies affecté un type "char"), il faudra aussi que la variable soit, non pas un "char", mais un pointeur sur char pointant sur une zone mémoire allouée disposant de suffisamment d'espace pour accueillir l'entrée.
Tu peux faire cela comme cela pour disposer d'un espace te permettant de stocker 255 caractères plus le caractère terminal \0 (cf. https://www.commentcamarche.net/contents/118-langage-c-les-chaines-de-caracteres) :
que tu utilises l'une ou l'autre méthode, "st" sera déjà un pointeur (sur char), et tu n'auras donc pas à préfixer la variable "st" de & dans ton scanf.
3.
Cependant scanf est complexe à utiliser, et délicate à utiliser de manière sûre afin d'obtenir une saisie de texte au clavier en C (même si paradoxalement, c'est une des fonction qu'on enseigne en premier aux personnes qui apprennent le C pour effectuer une saisie intéractive sur le terminal...). Si tu ne fais pas ce qu'il faut :
- tu ne contrôles pas le nombre de caractères pris en compte par scanf (qui ne va pas vérifier toute seule si la capacité du tampon n'est pas dépassée), ce qui peut conduire à un débordement de mémoire, donc un plantage, corruption de données, voire un problème de sécurité
- tu te retrouves avec des caractères qui trainent dans le flux stdin ('\n' n'est pas capturée) et qu'il faut purger
fgets est plus facile à utiliser pour opérer ce contrôle (il faudra retirer le '\n', en revanche, qui est capturé par fgets).
Autrement, on peut faire avec scanf comme cela, avec un spécificateur de taille et un spécificateur de classe excluant '\n' :
De cette façon, tu n'utilises pas %s qui s'arrête aux blancs, tu limites la taille de la saisie prise en compte à une taille maximale ou au premier '\n' rencontré (exclu). La boucle while qui suit est la façon classique de purger le flux stdin, pour que le '\n' qui reste dans le flux (et/ou les caractères excédant éventuellement la taille spécifiée), soient purgés et ne se retrouvent pas capturés au prochain scanf.
ouf !
Dal
Ce n'est pas trivial de saisir une chaine en C.
1.
Je complète la réponse de orinym, qui dit très exactement qu'il conviendrait d'utiliser %s au lieu de %c si tu veux récupérer plus qu'un caractère.
Cependant, il faut savoir qu'avec simplement "%s", scanf s'arrêtera en fin de ligne, mais aussi au premier "blanc" trouvé (espace ou tabulation), en laissant le reste dans le flux.
Vois la documentation de scanf.
Donc, si la chaîne que tu veux récupérer comporte des espaces, par exemple "Bonjour toi", tu ne récupères que "Bonjour\0" et " toi\n" restent dans le flux.
2.
De plus, comme tu n'as pas montré le type de tes variables "monChar1" et "monChar2" (et que, si on se fie au nom, il y a des chances que tu aies affecté un type "char"), il faudra aussi que la variable soit, non pas un "char", mais un pointeur sur char pointant sur une zone mémoire allouée disposant de suffisamment d'espace pour accueillir l'entrée.
Tu peux faire cela comme cela pour disposer d'un espace te permettant de stocker 255 caractères plus le caractère terminal \0 (cf. https://www.commentcamarche.net/contents/118-langage-c-les-chaines-de-caracteres) :
char st[256];ou
char * st;
st = malloc(256);
/* faire qq chose avec st */
free(st);
que tu utilises l'une ou l'autre méthode, "st" sera déjà un pointeur (sur char), et tu n'auras donc pas à préfixer la variable "st" de & dans ton scanf.
3.
Cependant scanf est complexe à utiliser, et délicate à utiliser de manière sûre afin d'obtenir une saisie de texte au clavier en C (même si paradoxalement, c'est une des fonction qu'on enseigne en premier aux personnes qui apprennent le C pour effectuer une saisie intéractive sur le terminal...). Si tu ne fais pas ce qu'il faut :
- tu ne contrôles pas le nombre de caractères pris en compte par scanf (qui ne va pas vérifier toute seule si la capacité du tampon n'est pas dépassée), ce qui peut conduire à un débordement de mémoire, donc un plantage, corruption de données, voire un problème de sécurité
- tu te retrouves avec des caractères qui trainent dans le flux stdin ('\n' n'est pas capturée) et qu'il faut purger
fgets est plus facile à utiliser pour opérer ce contrôle (il faudra retirer le '\n', en revanche, qui est capturé par fgets).
Autrement, on peut faire avec scanf comme cela, avec un spécificateur de taille et un spécificateur de classe excluant '\n' :
char st[256]={0};
char c;
if (scanf("%255[^\n]",st) == 1) {
while ((c = getchar()) != '\n' && c != EOF)
/* purge de stdin */ ;
}
De cette façon, tu n'utilises pas %s qui s'arrête aux blancs, tu limites la taille de la saisie prise en compte à une taille maximale ou au premier '\n' rencontré (exclu). La boucle while qui suit est la façon classique de purger le flux stdin, pour que le '\n' qui reste dans le flux (et/ou les caractères excédant éventuellement la taille spécifiée), soient purgés et ne se retrouvent pas capturés au prochain scanf.
ouf !
Dal
8 oct. 2013 à 14:56
Dans ce cas plutôt utiliser fgets et prévoir nu buffer assez grand.