J'ai le programme suivant:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d",&a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c",&c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
Comme je l'ai lu dans le livre C, l'auteur dit qu'il a scanf()
laissé un nouveau caractère de ligne dans la mémoire tampon, par conséquent, le programme ne s'arrête pas à la ligne 4 pour que l'utilisateur entre les données, il stocke plutôt le caractère de nouvelle ligne dans c2 et passe à ligne 5.
Est-ce correct?
Cependant, cela ne se produit-il qu'avec char
les types de données? Parce que je n'ai pas vu ce problème avec int
les types de données comme dans les lignes 1, 2, 3. Est-ce vrai?
fflush(stdin)
peut être utilisé avant l'appel àscanf()
pour un seul caractère. Veuillez lire Utilisationfflush(stdin)
pour une discussion des avantages et des inconvénients et des alternatives à cette méthode (qui fonctionne plus ou moins sous Windows et ne fonctionne pas dans la plupart des autres endroits).Réponses:
La
scanf()
fonction ignore automatiquement les espaces blancs avant d'essayer d'analyser les conversions autres que les caractères. Les formats de caractères (principalement%c
; également les jeux de balayage%[…]
- et%n
) sont l'exception; ils ne sautent pas d'espaces.À utiliser
" %c"
avec un blanc de début pour ignorer les espaces blancs facultatifs. N'utilisez pas de blanc de fin dans unescanf()
chaîne de format.Notez que cela ne consomme toujours aucun espace blanc de fin laissé dans le flux d'entrée, même pas jusqu'à la fin d'une ligne, alors méfiez-vous de cela si vous utilisez également
getchar()
oufgets()
sur le même flux d'entrée. Nous sommes juste en train de faire en sorte que scanf ignore les espaces avant les conversions, comme il le fait pour%d
et d'autres conversions sans caractère.Notez que les "directives" sans espace (pour utiliser la terminologie scanf POSIX ) autres que les conversions, comme le texte littéral dans
scanf("order = %d", &order);
ne saute pas non plus les espaces. Le littéralorder
doit correspondre au caractère suivant à lire.Donc, vous voulez probablement
" order = %d"
y aller si vous voulez sauter une nouvelle ligne de la ligne précédente mais avez toujours besoin d'une correspondance littérale sur une chaîne fixe, comme cette question .la source
%c
,%n
,%[]
Sont les 3 attentes spécifiques qui ne consomment pas de premier plan des espaces blancs.scanf()
chaîne de format etscanf()
demander deux fois l'entrée alors que je m'attends à ce qu'il ne demande qu'une seule fois pour une discussion sur les blancs de fin dans les chaînes de format. C'est une mauvaise idée - incroyablement mauvaise si vous vous attendez à une interaction humaine et mauvaise pour l'interaction avec le programme.Utilisez
scanf(" %c", &c2);
. Cela résoudra votre problème.la source
Une autre option (que j'ai obtenue à partir d' ici ) est de lire et de supprimer la nouvelle ligne en utilisant l' option de suppression d'affectation . Pour ce faire, il suffit de mettre un format pour lire un caractère avec un astérisque entre
%
etc
:scanf("%d%*c",&a); // line 1 scanf("%c%*c",&c1); // line 3
scanf
lira alors le caractère suivant (c'est-à-dire la nouvelle ligne) mais ne l'attribuera à aucun pointeur.En fin de compte, cependant, je soutiendrais la dernière option de la FAQ :
la source
a
alors espace puis nouvelle ligne, la conversion de caractères supprimée lit l'espace et laisse toujours la nouvelle ligne. Si l'utilisateur tapesupercalifragilisticexpialidocious
quand vous le souhaiteza
, vous avez beaucoup de caractères supplémentaires à gérer. Vous ne pouvez jamais dire non plus si une conversion supprimée de fin réussit - elles ne sont pas comptées dans le retour descanf()
.À utiliser
getchar()
avant d'appeler en secondscanf()
.scanf("%c", &c1); getchar(); // <== remove newline scanf("%c", &c2);
la source
int c; while ((c = getchar()) != EOF && c != '\n') ;
(écrite sur trois lignes quand elle n'est pas dans un commentaire). C'est souvent suffisant; ce n'est pas infaillible (et vous devez vous rappeler que les imbéciles sont très intelligents pour écraser les choses).