簡體   English   中英

While 循環陷入無限循環,我不知道為什么

[英]While loop is stuck in infinite loop and I don't know why

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

}

上面的代碼應該循環詢問問題然后回答,直到用戶輸入 -9876 作為答案,然后程序終止並給出他們的分數。這一切都有效,除了!! 一方面。 當用戶在輸入中輸入一個非數字時。 發生這種情況時,它應該說“無效輸入,請重試”,然后再次提出相同的問題。 例如

你的問題是什么? 9+9

什么是 9 + 9? 嗯,8

輸入無效,請重試

什么是 9 + 9?

所以.. 用戶輸入“嗯”,而不是再次提示用戶同樣的問題,然后正確掃描它只是跳入一個無限循環。我想知道如何解決這個問題。

謝謝

在通話中

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

%d轉換說明符期望看到一個十進制數字字符序列; 它會告訴scanf跳過任何前導空格,然后讀取十進制數字字符直到第一個非十進制數字字符,然后轉換並將結果保存到user_answer 如果您輸入1 2 a Enterscanf將讀取並使用'1''2'字符,將值12分配給user_answer並返回 1(對於一次成功的轉換和分配),將'a'和換行符留在輸入流。

當您鍵入"hmmm" ,第一個非空白字符不是十進制數字,因此scanf將其user_answer在原位,不向user_answer分配任何user_answer ,並返回0 使用"%d"轉換說明符對scanf所有剩余調用都將執行相同的操作。

因此,您需要確保您的scanf成功,如果沒有成功,請在再次讀取之前清除輸入流中的所有字符,如下所示:

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" 它轉換並分配了12user_answer ,在輸入流中留下'a'字符以user_answer下一次讀取。 理想情況下,您希望完全拒絕這種格式錯誤的輸入。 您可以執行以下操作:

/**
 * 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 );
  }
}

另一種選擇是將您的輸入讀取為文本,然后使用strtol庫函數將其轉換為結果類型:

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", &user_answer);

閱讀完您可能會想的所有內容后,“C 中的交互式輸入肯定是個麻煩事”。 你是對的。

當讀取輸入出現錯誤時,您應該清除錯誤狀態並在嘗試讀取更多用戶輸入之前跳過該行的其余部分。

替換行:

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

其中skipRestOfLine()可以實現為:

void skipRestOfLine(FILE* stream)
{
   int c;
   while ( (c = fgetc(stream)) != '\n' && c != EOF );
}
scanf("%d%c%d",&n1, &op, &n2) use this code 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM