Как исправить бесконечные циклы, когда пользователь вводит неверный тип данных в scanf ()? - PullRequest
1 голос
/ 17 октября 2019

C новичок здесь. Для приведенной ниже программы, когда пользователь вводит символ или строку, он входит в бесконечный цикл. Как бы вы это исправить, все еще используя scanf? И какие методы написания этой программы лучше, чем использование scanf? Спасибо тем, кто ответит.

#include <stdio.h>
#include <ctype.h>

int main() {

int rounds = 5;

do {
printf("Preferred number of rounds per game. ENTER NUMBERS ONLY: ");
scanf("%d", &rounds);   
} while(isdigit(rounds) == 0);

return 0;   
}

Ответы [ 4 ]

1 голос
/ 17 октября 2019

Использование 'scanf' требует форматирования ввода. Scanf имеет очень ограниченные возможности для обработки некорректного ввода. Распространенным решением будет использование fgets / sscanf, следуя приведенной ниже структуре:

   char buff[256] ;
   int rounds = 0 ;
   while ( fgets(buff, sizeof(buff), stdin) ) {
      if ( sscanf(buff, "%d", &rounds) == 1 ) {
          // additional verification here
          break ;
      } ;
   } ;
   // Use rounds here ...

fgets / sscanf разрешит восстановление после ошибки синтаксического анализа - неверная строка ввода будет проигнорирована. В зависимости от требования, это может быть принято решение.

0 голосов
/ 17 октября 2019

Я бы сказал, что есть только два "исправления".

  1. Сохраните вызовы scanf, бородавки и все. Тщательно воздержитесь от ввода нецифровых цифр, когда scanf ожидает цифры.

  2. Откажитесь от scanf и используйте что-нибудь еще. Мы только что обсуждали эту тактику на этом новом вопросе .

Как только вы используете scanf, всегда соблазнительно пытаться "исправить"это, так что здесь, вероятно, скрывается третий ответ, объясняющий, как сделать более качественный, более удобный для пользователя, более устойчивый к ошибкам ввод, при этом все еще используя scanf. Однако, по моему мнению, это глупое поручение, пустая трата времени. Простые, очевидные исправления многих недостатков scanf сами по себе несовершенны и имеют дополнительные недостатки. Вероятно, вы потратите больше времени на исправление программы, использующей scanf, чем потратили бы на ее переписывание, чтобы не использовать scanf - и вы получите в целом лучшие результаты (не говоря уже о более чистой программе) с не- scanf - используя переписывание в любом случае.

0 голосов
/ 17 октября 2019

Если вам действительно нравится scanf, вы можете использовать getch для отмены нецифрового ввода:

int rounds =  MIN_INT;
while (scanf("%d", &rounds)) != 1)
   if (getc() == EOF) /* discard a rubbish character */
      break; // or other error-handling return

// rounds is only valid if we did not break, when its value should be MIN_INT.
// but you might need another indicator
0 голосов
/ 17 октября 2019

Изменить

scanf("%d", &rounds);

На

int ret;

if ((ret = scanf(" %d", &rounds)) != 1) { // Skip over white space as well
   if (ret == EOF) break;
   scanf("%*[^\n\r]"); // Consume the rest of the line
}
...