scanf не работает с недопустимым вводом

На символьном входе в первом scanf() второй не запускается. getchar() не работает ни для входа Try Again. Он пропускает ввод для ввода. Хотите ли вы снова сыграть? (Y / N)? Кажется, что your_choice должен взять персонажа и проверить его позже, но персонаж фактически принимается ch . Что заставляет его работать так и как решить проблему. Я попытался повторно инициализировать переменные, но не работает.

 #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; } 

Если пользователь вводит символы, которые не могут быть преобразованы в число, scanf("%d", &your_choice); возвращает 0, а your_choice остается неизмененным, поэтому он не инициализирован. Поведение не определено.

Вы должны проверить это и пропустить внеочередные входные данные таким образом:

  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; } 

Объяснение:

  • scanf() возвращает количество успешных конверсий. Если пользователь вводит число, он преобразуется и сохраняется в your_choice а scanf() возвращает 1, если пользователь вводит то, что не является числом, например, AA , scanf() оставляет оскорбительный вход в стандартный входной буфер и возвращает 0, наконец, если достигнут конец файла (пользователь вводит ^ Z в Windows или ^ D в unix), scanf() возвращает EOF .

  • если вход не был преобразован в число, мы вводим тело оператора if : ввод потребляется по одному байту за раз с помощью getchar() , пока не будет прочитан ни конец файла, ни строка перевода строки.

  • если getchar() возвратил EOF , мы прочитали весь входной stream, не нужно запрашивать у пользователя больше ввода, вы можете отправить сообщение об ошибке перед возвратом кода ошибки.

  • в противном случае установите для параметра your_choice значение -1 , недопустимое значение, чтобы прочитать код, и запрашивает дальнейший ввод.

Чтение и отбрасывание входного сигнала необходимо: если вы этого не сделаете, следующий оператор ввода scanf(" %c", &ch); будет читать первый символ нарушающего ввода, а не ждать ввода пользователем в ответ на « Would you like to play again? (Y/N)?: Would you like to play again? (Y/N)?: подскажите. Это объяснение поведения, которое вы наблюдаете.