Scanf et boucles
voici un morceau de code qui est censé en boucle jusqu'à ce que les entrées de l'utilisateur un nombre compris entre 0 et 15
int input;
do
{
printf("Enter a number => ");
scanf("%d",&input);
printf("\n %d \n",input);
}
while (!(input>0 && input <15));
Toutefois, si l'utilisateur met dans quelque chose comme "gfggdf" qu'il résulte de la boucle répéter plus et plus et plus et de ne jamais demander à l'utilisateur pour la saisie de nouveau... la console ressemble à ceci
Enter a number =>
0
Enter a number =>
0
Enter a number =>
0
Enter a number =>
0
Enter a number =>
0
Enter a number =>
0
(looping indefinitely)
Après en regardant à travers ce livre, il semble que j'ai besoin de faire quelque chose comme cela pour empêcher que cela se produise.
int input, error, status;
char skip_ch;
do
{
error = 0;
printf("Enter a number => ");
status = scanf("%d",&input);
printf("\n %d \n",input);
if(status!=1)
{
error=1;
}
else if(input < 0 || input >15){
error = 1;
}
do
{
scanf("%c",&skip_ch);
}while(skip_ch != '\n');
}
while (error);
Je comprends d'avoir à vérifier pour le scanf état pour s'assurer qu'il est valide d'entrée, Ce que je ne comprends pas la l'intérieur do-while. Je crois que le livre n'a jamais vraiment expliqué moi pourquoi scanf doit être appelée plusieurs fois comme ça, c'est comme en quelque sorte le scanf de la mémoire tampon s'est rempli avec un tas d'ordures et c'est en quelque sorte le nettoyage par bouclage par le biais d'un million de fois pour vous.
Quelqu'un pourrait-il m'expliquer pourquoi la magie noire pour moi?
OriginalL'auteur Danny | 2010-10-04
Vous devez vous connecter pour publier un commentaire.
Le code d'origine est en boucle parce que les données non valides (le "gfggdf") est pas supprimé de la mémoire tampon d'entrée lorsque le scanf ne parvient pas à convertir un nombre entier -- il reste dans la mémoire tampon d'entrée, de sorte que le prochain appel à scanf regarde les mêmes données, et (bien sûr) encore ne peut pas convertir un nombre entier, de sorte que la boucle s'exécute encore une fois, et les résultats n'ont pas encore changé.
L':
se contente de lire les caractères un à un (et ignore jusqu'à ce qu'il arrive à la fin de la ligne. Si vous préférez pour se débarrasser des ordures dans la mémoire tampon d'entrée sans une boucle, vous pouvez utiliser quelque chose comme:
scanf("%*[^\n]");
Une autre possibilité c'est (probablement plus) largement utilisé est de commencer par la lecture de l'intégralité de la ligne, puis de tenter de les convertir ce qui est dans la ligne. Si elle convertit ou non, vous avez déjà lu toutes les données à la fin de la ligne de sorte que la prochaine tentative de lecture/conversion commencera à partir de la ligne suivante si la conversion a fonctionné ou pas. Cela ne veut avoir une faiblesse potentielle: si vous avez une vraiment long ligne de saisie, vous pourriez finir la lecture et le stockage d'un grand nombre de données pour lequel vous n'avez pas de réelle utilisation. C'est rarement une grosse affaire, mais vous devriez toujours être conscient de cela.
OriginalL'auteur Jerry Coffin
C'est pourquoi il ya tellement de nombreuses réponses à des questions similaires, qui recommande de ne pas utiliser
scanf()
.Aussi, vous devez vérifier la valeur de retour de
scanf()
parce qu'il vous dit quand quelque chose s'est mal passé - et qu'aucune valeur n'a pu être transformé.La normale de la solution recommandée est une combinaison de
fgets()
de lire des lignes d'entrée et desscanf()
à analyser la ligne une fois qu'il est lu.La deuxième boucle dans votre exemple va autour de la lecture les caractères jusqu'à et y compris un retour à la ligne, donc de la resynchronisation
scanf()
et en ignorant tout des données fausses. C'est un travail de longue haleine façon de le faire, il serait plus simple d'utilisergetchar()
à la place:Remarque l'utilisation de la "
int c;
'- le type est absolument pas "char
" ou "unsigned char
" parce qu'il doit stocker tous les possibleschar
valeurs plus EOF.OriginalL'auteur Jonathan Leffler
Tout d'abord, évitez d'utiliser
scanf()
, utilisezfgets()
à la place.Pour évaluer votre état de santé (premier code).
0 > 0
estfalse
.0 < 15
esttrue
.false && true
estfalse
.!false
esttrue
. C'est pourquoi il est en boucle indéfiniment.OriginalL'auteur Ruel