web-dev-qa-db-fra.com

scanf () laisse la nouvelle ligne dans la mémoire tampon

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 que scanf() a laissé un nouveau caractère de ligne dans le tampon. Par conséquent, le programme ne s'arrête pas à la ligne 4 pour permettre à l'utilisateur de saisir les données. Il stocke plutôt le nouveau caractère de ligne dans C2 et le déplace à la ligne 5.

Est-ce correct?

Cependant, cela ne se produit-il qu'avec les types de données char? Parce que je n'ai pas vu ce problème avec les types de données int comme dans les lignes 1, 2, 3. Est-ce correct?

55
ipkiss

La fonction scanf() supprime automatiquement les espaces avant d'essayer d'analyser des conversions autres que des caractères. Les formats de caractères (principalement %c; également les ensembles d'analyse %[…] - et %n) sont l'exception; ils ne suppriment pas les espaces.

Utilisez " %c" avec un blanc au début pour ignorer les espaces blancs facultatifs. N'utilisez pas de blanc de fin dans une chaîne au format scanf().

Notez que cela ne consomme toujours pas les blancs de fin laissés dans le flux d'entrée, pas même à la fin d'une ligne, donc faites attention si vous utilisez également getchar() ou fgets() sur le même flux d'entrée. Scanf ignore simplement les conversions entre espaces {before}, comme pour %d et les conversions sans caractère.


Notez que les "directives" non-d'espaces (pour utiliser la terminologie POSIX scanf ) autres que les conversions, comme le texte littéral dans scanf("order = %d", &order);, n'ignorent pas non plus les espaces. La valeur littérale order doit correspondre au prochain caractère à lire.

Donc, vous voulez probablement que " order = %d" soit présent si vous voulez ignorer une nouvelle ligne de la ligne précédente tout en exigeant une correspondance littérale sur une chaîne fixe, comme cette question .

50

Utilisez scanf(" %c", &c2);. Cela résoudra votre problème.

25
Shweta

Une autre option (que j’ai obtenue de ici ) consiste à lire et à ignorer la nouvelle ligne en utilisant l’option Affectation-Suppression. Pour cela, nous venons de mettre un format permettant de lire un caractère avec un astérisque compris entre % et c:

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 seconderais la dernière option de la FAQ :

Selon vos besoins, vous pouvez également oublier scanf ()/getchar (), utiliser fgets () pour obtenir une ligne de texte de l’utilisateur et l’analyser vous-même. 

1
brandizzi

Utilisez getchar() avant d'appeler la deuxième scanf()

scanf("%c", &c1);
getchar();  // <== remove newline
scanf("%c", &c2);
0
Jiwon