Comment effacer le tampon d’entrée dans C?

J’ai le programme suivant:

int main(int argc, char *argv[]) { char ch1, ch2; printf("Input the first character:"); // Line 1 scanf("%c", &ch1); printf("Input the second character:"); // Line 2 ch2 = getchar(); printf("ch1=%c, ASCII code = %d\n", ch1, ch1); printf("ch2=%c, ASCII code = %d\n", ch2, ch2); system("PAUSE"); return 0; } 

Comme l’auteur du code ci-dessus l’a expliqué: Le programme ne fonctionnera pas correctement car à la ligne 1, lorsque l’utilisateur appuie sur Entrée, il laisse 2 caractères dans le tampon d’entrée: Enter key (ASCII code 13) et \n (ASCII code 10) . Par conséquent, à la ligne 2, il lira le \n et n’attendra pas que l’utilisateur entre un caractère.

OK, j’ai ça. Mais ma première question est la suivante: pourquoi le deuxième getchar() ( ch2 = getchar(); ) ne lit pas la Enter key (13) , plutôt que le caractère \n ?

Ensuite, l’auteur a proposé deux manières de résoudre ces problèmes:

  1. utiliser fflush()

  2. écrire une fonction comme ceci:

     void clear (void) { while ( getchar() != '\n' ); } 

Ce code a fonctionné réellement. Mais je ne peux pas m’expliquer comment ça marche? Parce que dans l’instruction getchar() != '\n' , on utilise getchar() != '\n' , ce qui signifie que l’on lit n’importe quel caractère sauf '\n' ? Si oui, dans le tampon d’entrée rest le caractère '\n' ?

Le programme ne fonctionnera pas correctement car à la ligne 1, lorsque l’utilisateur appuie sur Entrée, il laissera le caractère tampon d’entrée 2: touche Entrée (code ASCII 13) et \ n (code ASCII 10). Par conséquent, à la ligne 2, il lira le \ n et n’attendra pas que l’utilisateur entre un caractère.

Le comportement que vous voyez à la ligne 2 est correct, mais ce n’est pas tout à fait la bonne explication. Avec les stream en mode texte, peu importe la fin de ligne utilisée par votre plate-forme (qu’il s’agisse d’un retour chariot (0x0D) + saut de ligne (0x0A), d’un CR nu ou d’un LF nu). La bibliothèque d’exécution C s’en chargera pour vous: votre programme verra juste '\n' pour les nouvelles lignes.

Si vous avez tapé un caractère et que vous avez appuyé sur Entrée, alors ce caractère d’entrée serait lu par la ligne 1, puis '\n' serait lu par la ligne 2. Voir J’utilise scanf %c pour lire une réponse Y / N, mais les entrées ultérieures sont ignorées. à partir de la FAQ comp.lang.c.

En ce qui concerne les solutions proposées, voir (à nouveau dans la FAQ comp.lang.c):

  • Comment puis-je vider une entrée en attente afin que la saisie de texte d’un utilisateur ne soit pas lue à l’invite suivante? Est-ce que fflush(stdin) fonctionne?
  • Si fflush ne fonctionne pas, que puis-je utiliser pour vider l’entrée?

qui stipule essentiellement que la seule approche portable est de faire:

 while ((c = getchar()) != '\n' && c != EOF) { } 

Votre boucle getchar() != '\n' fonctionne car une fois que vous appelez getchar() , le caractère renvoyé a déjà été supprimé du stream d’entrée.

En outre, je me sens obligé de vous décourager d’utiliser scanf entièrement: Pourquoi tout le monde dit-il de ne pas utiliser scanf ? Que dois-je utiliser à la place?

Vous pouvez le faire (aussi) de cette façon:

 fseek(stdin,0,SEEK_END); 

Les lignes:

 int ch; while ((ch = getchar()) != '\n' && ch != EOF) ; 

ne lit pas seulement les caractères avant le saut de ligne ( '\n' ). Il lit tous les caractères du stream (et les rejette) jusqu’au prochain saut de ligne (ou EOF rencontré). Pour que le test soit vrai, il faut d’abord lire le saut de ligne; ainsi, lorsque la boucle s’arrête, le saut de ligne était le dernier caractère lu, mais il a été lu.

En ce qui concerne la raison pour laquelle il lit un saut de ligne au lieu d’un retour chariot, c’est parce que le système a traduit le retour en saut de ligne. Lorsque vous appuyez sur Entrée, cela signale la fin de la ligne … mais le stream contient un saut de ligne, car il s’agit du marqueur de fin de ligne normal du système. Cela pourrait être dépendant de la plate-forme.

En outre, l’utilisation de fflush() sur un stream d’entrée ne fonctionne pas sur toutes les plates-formes. Par exemple, cela ne fonctionne généralement pas sous Linux.

Un moyen portable pour effacer jusqu’à la fin d’une ligne que vous avez déjà essayé de lire partiellement est:

 int c; while ( (c = getchar()) != '\n' && c != EOF ) { } 

Cela lit et élimine les caractères jusqu’à ce qu’il obtienne \n qui signale la fin du fichier. Il vérifie également EOF au cas où le stream d’entrée serait fermé avant la fin de la ligne. Le type de c doit être int (ou plus grand) pour pouvoir contenir la valeur EOF .

Il n’y a pas de moyen portable pour savoir s’il y a d’autres lignes après la ligne en cours (s’il n’y en a pas, alors getchar va bloquer pour les entrées).

Mais je ne peux pas m’expliquer comment ça marche? Parce que dans l’instruction getchar() != '\n' , nous utilisons getchar() != '\n' , ce qui signifie que l’on lit n’importe quel caractère sauf '\n' ?? Si oui, dans le tampon d’entrée rest toujours le caractère '\n' ??? Est-ce que je comprends mal quelque chose?

Ce que vous ne réalisez peut-être pas, c’est que la comparaison a lieu après que getchar() supprime le caractère du tampon d’entrée. Donc, lorsque vous atteignez le '\n' , il est consommé et vous sortez de la boucle.

tu peux essayer

 scanf("%c%*c", &ch1); 

où% * c accepte et ignore la nouvelle ligne

une méthode de plus au lieu de fflush (stdin) qui appelle un comportement indéfini que vous pouvez écrire

 while((getchar())!='\n'); 

N’oubliez pas le point-virgule après une boucle while

 unsigned char a=0; if(kbhit()){ a=getch(); while(kbhit()) getch(); } cout<(a) & 0xFF)< 

-ou-

utiliser peut-être utiliser _getch_nolock() .. ???

Je rencontre un problème en essayant d’implémenter la solution

 while ((c = getchar()) != '\n' && c != EOF) { } 

Je poste un petit ajustement ‘Code B’ pour quiconque a peut-être le même problème.

Le problème était que le programme m’empêchait d’attraper le caractère ‘\ n’, indépendamment du caractère de saisie, voici le code qui m’a donné le problème.

Code A

 int y; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ continue; } printf("\n%c\n", toupper(y)); 

et l’ajustement consistait à “attraper” le caractère (n-1) juste avant l’évaluation de la condition dans la boucle while, voici le code:

Code b

 int y, x; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ x = y; } printf("\n%c\n", toupper(x)); 

L’explication possible est que pour que la boucle while se brise, elle doit affecter la valeur ‘\ n’ à la variable y, ce sera donc la dernière valeur affectée.

Si j’ai manqué quelque chose avec l’explication, le code A ou le code B, dites-le moi, je suis à peine nouveau dans le c.

j’espère que ça aide quelqu’un

Courte, portable et déclarée dans stdio.h

 stdin = freopen(NULL,"r",stdin); 

Ne se bloque pas dans une boucle infinie lorsqu’il n’y a rien sur stdin qui vienne s’append à la ligne suivante:

 while ((c = getchar()) != '\n' && c != EOF) { } 

Un peu cher alors ne l’utilisez pas dans un programme qui doit effacer le tampon à plusieurs resockets.

Volé d’un collègue 🙂

 char choice; do{ printf("\n *"); printf("\n Do you want to continue? (y/n) "); choice = getchar(); if(getchar() != '\n'){ fflush(stdin); } }while( choice != 'n' ); 

Une autre solution non encore mentionnée est d’utiliser: rembobiner (stdin);