scanf ne fonctionne pas sur une entrée invalide

Sur une entrée de caractère dans le premier scanf() , le second ne s’exécute pas. getchar() ne fonctionne pas non plus pour l’entrée Try Again. Il saute à prendre des entrées pour Voulez-vous jouer à nouveau? (O / N)? Il semble que your_choice soit supposé prendre le caractère et le vérifier plus tard, mais le personnage est pris par ch . Qu’est-ce qui le fait fonctionner comme ceci et comment résoudre le problème. J’ai essayé de réinitialiser les variables mais cela ne fonctionne pas.

 #include  void choice(int); int main() { char ch; int random, your_choice; do { srand(time(NULL)); system("cls"); printf("** 0 is for Rock **\n"); printf("** 1 is for Scissors **\n"); printf("** 2 is for Lizard **\n"); printf("** 3 is for Paper **\n"); printf("** 4 is for Spock **\n"); printf("\nEnter your choice here:"); scanf("%d", &your_choice); random = rand() % 5; //random number between 0 & 4 if ((your_choice >= 0) && (your_choice <= 4)) { //choice printer omitted for this post if ((random == ((your_choice + 1) % 5)) || (random == ((your_choice + 2) % 5))) printf("\n\n... and you win!!!\n"); else if ((random == ((your_choice + 3) % 5)) || (random == ((your_choice + 4) % 5))) printf("\n\n... and you lose!!!\n"); else if (random == your_choice) printf("\n\nUnfortunately, it's a tie!\n"); } else printf("\nWell, this is wrong! Try again with a number from 0 to 4!!\n"); printf("\nWould you like to play again? (Y/N)?: "); scanf(" %c", &ch); } while (ch == 'y' || ch == 'Y'); return 0; } 

Si l’utilisateur entre des caractères qui ne peuvent pas être convertis en nombre, scanf("%d", &your_choice); renvoie 0 et your_choice n’est pas modifié, il n’est donc pas initialisé. Le comportement est indéfini.

Vous devriez tester cela et ignorer l’entrée incriminée de cette façon:

  if (scanf("%d", &your_choice) != 1) { int c; /* read and ignore the rest of the line */ while ((c = getchar()) != EOF && c != '\n') continue; if (c == EOF) { /* premature end of file */ return 1; } your_choice = -1; } 

Explication:

  • scanf() renvoie le nombre de conversions réussies. Si l’utilisateur your_choice un nombre, celui-ci est converti et stocké dans your_choice et scanf() renvoie 1, s’il entre quelque chose qui n’est pas un nombre, tel que AA , scanf() laisse l’entrée incriminée dans le tampon d’entrée standard et renvoie 0, enfin si la fin du fichier est atteinte (l’utilisateur tape ^ Z enter dans windows ou ^ D sous unix), scanf() renvoie EOF .

  • si l’entrée n’a pas été convertie en nombre, nous entrons dans le corps de l’instruction if : l’entrée est consommée octet par octet avec getchar() , jusqu’à ce que la fin du fichier ou un saut de ligne soit lu.

  • si getchar() renvoyé EOF , nous avons lu l’intégralité du stream d’entrée. Inutile d’inviter l’utilisateur à entrer plus d’informations. Vous souhaiterez peut-être générer un message d’erreur avant de renvoyer un code d’erreur.

  • sinon, définissez your_choice sur -1 , une valeur non valide pour que la lecture du code se plaint et vous invite à une nouvelle saisie.

La lecture et la suppression de l’entrée incriminée sont nécessaires: si vous ne le faites pas, l’instruction d’entrée suivante scanf(" %c", &ch); lit le premier caractère de l’entrée incriminée au lieu d’attendre la saisie de l’utilisateur en réponse au Would you like to play again? (Y/N)?: Would you like to play again? (Y/N)?: invite. C’est l’explication du comportement que vous observez.