【问题标题】:Random guessing game (integer) - bug when entering string随机猜谜游戏(整数) - 输入字符串时出现错误
【发布时间】:2012-06-13 16:36:15
【问题描述】:

我正在制作一个典型的猜谜游戏来学习 C 语言,这是我人生中的第一次,我发现了一个错误。如果你输入一个整数,你会得到Guess a higher valueGuess a lower value,这很好用。但是如果你输入一个字符串,它会变得疯狂并打印出很多字符串,上面写着Guess a higher value

  1. 我现在要做的是检查用户是否输入了一个字符串,它会告诉用户类似Enter a number, not text 的内容。我该怎么做?

  2. 您认为我可以在这段代码中改进什么吗?

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    int main () {
    
        int secret, answer;
    
        srand((unsigned)time(NULL));
    
        secret = rand() % 10 + 1;
    
        do {
            printf ("Guess a number between 1 and 10");
            scanf ("%d",&answer);
            if (secret<answer) puts ("Guess a higher value");
            else if (secret>answer) puts ("Guess a lower value");
        } while (secret!=answer);
    
        puts ("Congratz!");
        return 0;
    }
    

【问题讨论】:

  • 相应地更改了标签(C 不是 C++)。
  • 哦,是吗?嗯……这个例子是不是很简单? C 和 C++ 不是很像吗?这个例子在两种语言中并没有什么不同。
  • @user1431627:这可能令人惊讶,因为大多数 C 可以编译为 C++ 并且工作方式类似(尽管 C++ 不是严格的超集)。但是您在这里没有使用 C++ 的任何特性,纯 C 代码。 (我敢说,纯 C89 代码)
  • 谢谢!那我就用C编译吧。如果我使用 C++,printf() 将是cout &lt;&lt; &lt;&lt;?你会推荐我用什么?

标签: c string random numbers


【解决方案1】:

您可能想要创建一个函数来检查输入是否为数字。喜欢:

int isNumeric( char *str){
   while(*str)
   {
     if (!isdigit(*str))
         return 0;
     str++;
   }
   return 1;
}

int main(){
   char guess[3];
   int iGuess;
   do {
      printf("Guess a number between 1 and 10");
      gets(guess);
      if (!isNumeric(guess)){
        printf("Invalid input");
        continue;
      }
      iGuess = atoi(guess);
     if (iGuess<secret)
           printf("Higher");
     else if (iGuess>secret)
           printf("Lower");
   } while (secret!=iGuess);
   printf("Congrats");
   return 0;
}

你需要包含 ctype.h 和 string.h

【讨论】:

    【解决方案2】:

    检查 scanf 的返回值。它将返回成功匹配和分配的项目数。这种情况下如果你输入一个字符串,那么它就不会被匹配和赋值,但是这个字符串会留在输入缓冲区中,而scanf在每次迭代中都会尝试读取它并且失败,因此问题就出现了。

    您可以将代码更改为:

    int main () {
    
        int secret, answer;
    
        srand((unsigned)time(NULL));
    
        secret = rand() % 10 + 1;
    
        do {
            printf ("Guess a number between 1 and 10");
            if (scanf ("%d",&answer) != 1)
            {
             printf ("\nPlease enter an integer\n\n");
             scanf ("%*s");
             continue;
            }
            if (secret<answer) puts ("Guess a higher value");
            else if (secret>answer) puts ("Guess a lower value");
        } while (secret!=answer);
    
        puts ("Congratz!");
        return 0;
    }
    

    请注意,在if 内,scanf ("%*s"); 行已完成。在%*s 中,* 是输入抑制指示符,这表示将读取一个字符串(代表%s),但* 表示虽然将从输入中读取该字符串,但它将是丢弃。这样做是为了简单地丢弃 scanf ("%d",&amp;answer) 未读取的先前输入的字符串。如果您不丢弃缓冲区中的字符串,它将保留,并且每次迭代 scanf ("%d",&amp;answer) 将无法匹配任何整数,因为它将遇到输入缓冲区中的剩余字符串。

    另一方面,您可以读取一个字符串并将该字符串转换为整数。

    如下:

    int main () {
    
        int secret, answer;
        char buff[128];
    
        srand((unsigned)time(NULL));
    
        secret = rand() % 10 + 1;
        do {
            printf ("Guess a number between 1 and 10");
            scanf ("%s",buff);
            if ((answer = atoi (buff)) == 0)
            {
              printf ("\nPlease enter an integer\n\n");
              continue;
            }
            if (secret<answer) puts ("Guess a higher value");
            else if (secret>answer) puts ("Guess a lower value");
        } while (secret!=answer);
    
        puts ("Congratz!");
        return 0;
    }
    

    atoi () 会将字符串转换为整数(以 10 为基数)。如果组成整数的字符不包含有效数字,它将返回0。检查它,我们可以检测用户是否正确输入。另外因为您的应用程序需要输入 1 和 10 之间的整数,因此不包括 0,因此可以将 0 视为无效。为了更好地控制检测无效整数格式以及字符串中错误的位置,请使用strtol ()

    【讨论】:

    • 当我使用你的代码时,程序将无法正常运行。它总是说‘猜一个较低的值,但没有从 1 到 10 的值。我尝试了所有可能的数字 1,2,3,4,5,6,7,8,9,10。
    • 我无法重现您所面临的错误。上面的代码还是下面的代码?
    • 第一个代码。编辑:现在检查:下面的那个也不起作用。它只是说我需要一个较低的数字。
    【解决方案3】:

    您忽略了scanf 的返回值,它会告诉您转换是否顺利。 scanf 将返回分配的项目数,因此如果它返回 1,则您知道 answer 已分配给一个数字。如果它返回 0,你就知道出了问题。

    【讨论】:

    • 当我停止我的应用程序时它返回 0。
    • 那么你就知道用户没有输入有效号码。打印错误信息并再次提示用户。
    【解决方案4】:

    我现在要做的是检查用户是否输入 字符串,它会告诉用户输入一个数字,而不是 文本。我该怎么做?

    scanf 进行格式化输入。您可能还想查看scanf 中的高级格式说明符——例如忽略部分输入、指定读取字符串的缓冲区大小、仅指定要读取的特定字符集等。如果您想验证输入,您最好使用fgets 从控制台读取一行,然后解析该行。

    您认为我可以在这段代码中改进什么吗?

    您可能希望改进随机数生成算法。阅读 C 常见问题解答。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-04
      • 2019-11-29
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多