而循环卡在无限循环中,我不';我不知道为什么 #包括 #包括 #包括 #包括 int main(int argc,char*argv[]) { printf(“此程序测试您的整数算术技能。\n” “您应该回答以下问题\n” 计算机对整数算术执行的规则,而不是\n “浮点算术。在后面按'Enter'键\n” “您已经输入了您的输入。当您希望完成时\n” 在测试中,输入-9876作为问题的答案。\n “\n”); int n1,n2,answer,user_answer,a,b,int_per; char-op,c; 浮点数,计数,计数,计数; 计数=0; 计数r=0; 计数w=0; printf(“你的问题是什么?”); scanf(“%d%c%d”、&n1、&op、&n2); 做 { 计数++; printf(“什么是%d%c%d?”,n1,op,n2); 如果(op=='+') { 答案=n1+n2; } else if(op='-') { 答案=n1-n2; } else if(op='%')) { 答案=n1%n2; } else if(op=='/')) { 答案=n1/n2; } else if(op=='*') { 答案=n1*n2; } c=scanf(“%d”,用户回答(&U); 如果(用户回答==回答) { printf(“正确!\n\n”); 计数r++; } 否则如果(用户回答==-9876) { 计数=计数-1; 打破 } 如果(c!=1),则为else { printf(“无效输入,它必须只是一个数字\n\n”); printf(“什么是%d%c%d?”,n1,op,n2); } else if(用户回答!=回答) { printf(“错误!\n\n”); 计数w++; } }while(用户回答!=-9876); per=(计数/计数)*100; a=(int)计数; b=(int)计数w; int_per=整数(per); printf(“\n您得到了%d对%d错,分数为%d%c\n”,a, b、 国际单位,37); 返回退出成功; }

而循环卡在无限循环中,我不';我不知道为什么 #包括 #包括 #包括 #包括 int main(int argc,char*argv[]) { printf(“此程序测试您的整数算术技能。\n” “您应该回答以下问题\n” 计算机对整数算术执行的规则,而不是\n “浮点算术。在后面按'Enter'键\n” “您已经输入了您的输入。当您希望完成时\n” 在测试中,输入-9876作为问题的答案。\n “\n”); int n1,n2,answer,user_answer,a,b,int_per; char-op,c; 浮点数,计数,计数,计数; 计数=0; 计数r=0; 计数w=0; printf(“你的问题是什么?”); scanf(“%d%c%d”、&n1、&op、&n2); 做 { 计数++; printf(“什么是%d%c%d?”,n1,op,n2); 如果(op=='+') { 答案=n1+n2; } else if(op='-') { 答案=n1-n2; } else if(op='%')) { 答案=n1%n2; } else if(op=='/')) { 答案=n1/n2; } else if(op=='*') { 答案=n1*n2; } c=scanf(“%d”,用户回答(&U); 如果(用户回答==回答) { printf(“正确!\n\n”); 计数r++; } 否则如果(用户回答==-9876) { 计数=计数-1; 打破 } 如果(c!=1),则为else { printf(“无效输入,它必须只是一个数字\n\n”); printf(“什么是%d%c%d?”,n1,op,n2); } else if(用户回答!=回答) { printf(“错误!\n\n”); 计数w++; } }while(用户回答!=-9876); per=(计数/计数)*100; a=(int)计数; b=(int)计数w; int_per=整数(per); printf(“\n您得到了%d对%d错,分数为%d%c\n”,a, b、 国际单位,37); 返回退出成功; },c,while-loop,infinite-loop,C,While Loop,Infinite Loop,上面的代码应该循环询问问题和答案,直到用户输入-9876作为答案,然后程序终止并给出他们的分数。这一切都有效,除了!!一方面当用户在输入中输入非数字时。当这种情况发生时,应该说“输入无效,请再试一次”,然后再问同样的问题。比如说 你的问题是什么9+9 什么是9+9hmmm,8 输入无效,请重试 什么是9+9 所以。。用户输入“hmmm”,而不是用同样的问题再次提示用户,然后正确地扫描,它只是跳入一个无限循环。我想知道如何解决这个问题 谢谢当读取输入时出错时,您应该清除错误状态并跳过该行的其余部分

上面的代码应该循环询问问题和答案,直到用户输入-9876作为答案,然后程序终止并给出他们的分数。这一切都有效,除了!!一方面当用户在输入中输入非数字时。当这种情况发生时,应该说“输入无效,请再试一次”,然后再问同样的问题。比如说

你的问题是什么9+9

什么是9+9hmmm,8

输入无效,请重试

什么是9+9

所以。。用户输入“hmmm”,而不是用同样的问题再次提示用户,然后正确地扫描,它只是跳入一个无限循环。我想知道如何解决这个问题


谢谢

当读取输入时出错时,您应该清除错误状态并跳过该行的其余部分,然后再尝试读取更多用户输入

更换管路:

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

int main(int argc, char * argv[])
{
   printf("This program tests your integer arithmetic skills.\n"
          "You should answer the questions following the same \n"
          "rules that computers do for integers arithmetic, not \n"
          "floating-point arithmetic. Hit the 'Enter' key after \n"
          "you have typed in your input. When you wish to finish \n"
          "the test, enter -9876 as the answer to a question.\n"
          "\n");

   int n1, n2, answer, user_answer, a, b, int_per;
   char op, c;
   float per, count, count_r, count_w;

   count = 0;
   count_r = 0;
   count_w = 0;

   printf("What is your question? ");
   scanf("%d %c %d", &n1, &op, &n2);


   do
   {
      count++;

      printf("What is %d %c %d ? ", n1, op, n2);

      if (op == '+')
      {
         answer = n1 + n2;
      }
      else if (op == '-')
      {
         answer = n1 - n2;
      }
      else if (op == '%')
      {
         answer = n1 % n2;
      }
      else if (op == '/')
      {
         answer = n1 / n2;
      }
      else if (op == '*')
      {
         answer = n1 * n2;
      }

      c = scanf("%d", &user_answer);

      if (user_answer == answer)
      {
         printf("Correct!\n\n");
         count_r++;

      }
      else if (user_answer == -9876)
      {
         count = count - 1;
         break;  
      }
      else if (c != 1)
      {
         printf("Invalid input, it must be just a number\n\n");
         printf("What is %d %c %d ? ", n1, op, n2);
      }
      else if (user_answer != answer)
      {
         printf("Wrong!\n\n");
         count_w++;
      }

   } while(user_answer != -9876);

   per = (count_r / count) * 100;

   a = (int) count_r;
   b = (int) count_w;
   int_per = roundf(per);

   printf("\nYou got %d right and %d wrong, for a score of %d%c\n", a,
          b, int_per, 37);

   return EXIT_SUCCESS;

}

其中
skipRestOfLine()
可以实现为:

  else if (c != 1)
  {
     printf("Invalid input, it must be just a number\n\n");

     // Clear the error states.
     clearerr(stdin);

     // Skip the rest of the line
     skipRestOfLine(stdin);

     printf("What is %d %c %d ? ", n1, op, n2);
  }
在通话中

scanf("%d%c%d",&n1, &op, &n2) use this code 
%d
转换说明符希望看到十进制数字字符序列;它将告诉
scanf
跳过任何前导空格,然后读取十进制数字字符直到第一个非十进制数字字符,然后将结果转换并保存到
user\u answer
。如果您键入12aEnter,
scanf
将读取并使用
'1'
'2'
字符,将值
12
分配给
user\u answer
并返回1(对于一个成功的转换和分配),在输入流中保留
'a'
和换行字符

键入
“hmmm”
时,第一个非空白字符不是十进制数字,因此
scanf
保留该字符,不为
用户答案分配任何内容,并返回
0
。使用
“%d”
转换说明符对
scanf
的所有剩余调用都将执行相同的操作

因此,您需要确保您的
scanf
成功,如果没有成功,请在执行另一次读取之前清除输入流中的所有字符,如下所示:

c = scanf("%d", &user_answer);
if ( (c = scanf( "%d", &user_answer ) ) == 0 )
{
  /**
   * input matching failure, clear stray characters from input stream
   * up to the next newline character
   */
  while ( getchar() != '\n' )
    ; // empty loop 
}
else if ( c == EOF )
{
  // error occurred during input operation
}
else
{
  // do something with user_answer
}
在我的第一个示例中,您会注意到,
%d
转换说明符接受了输入
“12a”
;它将
12
转换并分配给
user\u answer
,在输入流中留下
'a'
字符,以干扰下一次读取。理想情况下,您希望完全拒绝这种格式错误的输入。您可以执行以下操作:

c = scanf("%d", &user_answer);
if ( (c = scanf( "%d", &user_answer ) ) == 0 )
{
  /**
   * input matching failure, clear stray characters from input stream
   * up to the next newline character
   */
  while ( getchar() != '\n' )
    ; // empty loop 
}
else if ( c == EOF )
{
  // error occurred during input operation
}
else
{
  // do something with user_answer
}
另一个选项是将输入读取为文本,然后使用
strtol
库函数将其转换为结果类型:

/**
 * Repeatedly prompt and read input until we get a valid decimal string
 */
for( ;; ) 
{
  int c, dummy;
  printf("What is %d %c %d ? ", n1, op, n2);

  if ( ( c = scanf("%d%c", &user_answer, &dummy ) == 2 )
  {
    /**
     * If the character immediately following our numeric input is
     * whitespace, then we have a good input, break out of the read loop
     */
    if ( isspace( dummy ) )
      break;
    else
    {
      fprintf( stderr, "Non-numeric character follows input, try again...\n" );
      while ( getchar() != '\n' )
        ; // empty loop body
    }
  }
  else if ( c == 1 )
  {
    /**
     * No character following successful decimal input, meaning we
     * hit an EOF condition before any trailing characters were seen.  
     * We'll consider this a good input for our purposes and break
     * out of the read loop.
     */
    break;
  }
  else if ( c == 0 )
  {
    /**
     * User typed in one or more non-digit characters; reject the input
     * and clear out the input stream
     */
    fprintf( stderr, "Non-numeric input\n" );

    /**
     * Consume characters from the input stream until we see a newline.
     */
    while ( ( getchar() != '\n' )
      ; // empty loop body
  }
  else
  {
    /**
     * Input error or EOF on read; we'll treat this as a fatal
     * error and bail out completely.
     */
    fprintf( stderr, "Error occurred during read, panicking...\n" );
    exit( 0 );
  }
}
那是我喜欢的方法

这些混乱中的任何一个都将取代生产线

for ( ;; )
{
  char input[SIZE]; // for some reasonable SIZE value, at least 12 to handle
                    // a 32-bit int (up to 10 digits plus sign plus
                    // string terminator

  printf("What is %d %c %d ? ", n1, op, n2);
  if ( fgets( input, sizeof input, stdin ) )
  {
    char *check; // will point to first non-digit character in input buffer
    int tmp = (int) strtol( input, &check, 10 );
    if ( isspace( *check ) || *check == 0 )
    {
      user_answer = tmp;
      break;
    }
    else
    {
      fprintf( stderr, "%s is not a valid input, try again\n", input );
    }
  }
  else
  {
    /** 
     * error or EOF on input, treat this as a fatal error and bail
     */
    fprintf( stderr, "EOF or error while reading input, exiting...\n" );
    exit( 0 );
  }
}

在阅读了所有你可能会想的内容之后,“C语言中的交互式输入确实是一件让人头疼的事”。你是对的。

当输入无效时清除输入缓冲区。当你用
scanf(“%d”,&value)
扫描一个整数,而输入不是一个有效的整数时,
scanf
返回0,输入返回到它开始的位置,即非数字输入之前。随后的调用将反复尝试重新解析相同的无效输入。您应该
scanf(“%*s”)
跳过它。更好的方法是,将整行的
fgets
sscanf
读入其中。我不明白为什么要使用输入
-9876
?您在scanf函数中使用了%d%c%d之间的空格..将垃圾值分配到&n1、&op和n2之间variables@NeErAjKuMaR:不,没有;格式字符串中的空格告诉scanf跳过空白字符。为什么
fgetc()
而不是
getc()
?@JonathanLeffler,我不明白为什么一个比另一个好。
getc()
可以是宏
fgetc()
保证是一个函数。如果
getc()
是一个宏,那是因为它可以执行得更好。有点夸张
c = scanf("%d", &user_answer);