web-dev-qa-db-fra.com

Comment effacer stdin avant d'obtenir de nouvelles entrées?

J'ai lu environ 5 à 10 conseils différents sur la manière de supprimer stdin, mais aucun ne répond à mes besoins. Le problème est que fflush(stdin) fonctionnait parfaitement sur mon ordinateur, mais malheureusement, il semble que cela ne fonctionne pas partout. J'ai donc besoin de quelque chose avec les mêmes fonctionnalités. Tous les autres moyens que j'ai essayés efface stdin quand il n'est pas vide mais nécessite une entrée de l'utilisateur quand stdin IS est vide, ce qui signifie qu'il nécessite une entrée dans un moment où je ne veux pas en obtenir (+ il le jette quand même).

La question est la suivante: puis-je m'assurer, d'une manière ou d'une autre, que stdin IS est vide avant que je requière la saisie de l'utilisateur? (et si non, ALORS et seulement alors effacez-le en quelque sorte?). quelque chose comme: 

if (stdin is NOT empty) 
    while (getchar() != '\n')
        continue;

EDIT: le fait est que je charge les caractères de stdin un par un et qu'à un moment donné, une partie de l'entrée de l'itération précédente peut ou non être ignorée. Quoi qu'il en soit, je dois clairement définir stdin avant de demander à l'utilisateur qu'une autre entrée soit traitée. Effacer le tampon lui-même n'est pas si grave, le problème est de savoir ce qui se passe lorsque l'entrée est vide lorsque le programme est sur le point de clarifier stdin, car à ce moment-là, le programme a besoin d'une autre entrée qui sera consommée par la compensation. une fonction. Cest ce que je veux me débarrasser. (Quand j'ai pu utiliser fflush(stdin);, je savais juste que, pour la ligne suivante de mon programme, la stdin serait vide quoi qu'il en soit, aucune question ne serait posée ...)

11
Tom

Comment effacer stdin avant d'obtenir de nouvelles entrées?
.. alors j'ai besoin de quelque chose avec les mêmes fonctionnalités.

Avec C portable, ce n'est pas possible.


Au lieu de cela, suggérez un paradigme différent (et plus habituel):
Assurez-vous que les fonctions d’entrée précédentes consomment tout l’entrée précédente.

fgets() (ou * nix getline() ) est l’approche typique et résout la plupart des situations. 

Ou roulez les vôtres. Ce qui suit lit une ligne entière, mais ne sauvegarde pas d’entrée supplémentaire.

int mygetline(char *buf, size_t size) {
  assert(size > 0 && size <= INT_MAX);
  size_t i = 0;
  int ch;
  while ((ch = fgetc(stdin)) != EOF) {  // Read until EOF ...
    if (i + 1 < size) {
      buf[i++] = ch;
    }
    if (ch == '\n') {  // ... or end of line
      break;  
    }
  } 
  buf[i] = '\0';
  if (i == 0) { 
    return EOF;
  }
  return i;
}
4
chux

TL; DRfflush(stdin) appelle un comportement non défini conformément à la norme, vous ne devez jamais l'utiliser.


Dans votre code (logique), au lieu de rechercher une nouvelle ligne, vous pouvez rechercher EOF. Avant de lancer cette boucle, il n’est pas nécessaire que stdin ait l’entrée un peu avant de lancer cette boucle.

Quelque chose comme

 while (getchar() != EOF);   //; is not a mistake

devrait répondre à vos besoins.

1
Sourav Ghosh

Utilisez only fgets() pour lire stdin.

Utilisez un tampon suffisamment grand et/ou testez pour des lignes complètes.

Avec fgets(), vous n'avez jamais à vous soucier des caractères supplémentaires dans stdin.

// read characters until 'X'
while (((ch = getchar()) != EOF) && (ch != 'X')) putchar(ch);
// discard X and the rest of the line
fflush(stdin); // UB except for Windows

// read full line
char tmp[1000], *p;
if (!fgets(tmp, sizeof tmp, stdin)) /* deal with error */;
if (!*tmp) /* embedded NUL detected: input is not a text file */;
if (tmp[strlen(tmp) - 1] != '\n') /* partial line */;
p = tmp;
while (*p && *p != 'X') putchar(*p++);
// ignore the X and all the subsequent characters
0
pmg