【问题标题】:C: rand() and scanf() malfunction?C: rand() 和 scanf() 故障?
【发布时间】:2014-11-04 19:10:11
【问题描述】:

我对 C/C++ 有点陌生,但我不明白以下代码中的问题所在。 在这个作业中,我只能使用 C 函数和语法,不允许使用 C++。

程序应该从字母表中随机选择一个字符,并让用户 3 次尝试猜测它。

#include <stdio.h>
#include <stdlib.h>
#define guesses 3

int main(){

    setbuf(stdout, NULL);
    /* A 2.P.b */

    /* version with loop*/

    int i = 0;
    char randomChar = (65 + (rand()%26) + 1);

    /* comment the line below, when the programm works as intended */
     printf("\n%c\n", randomChar);

    char guessedChar;

    while((i<=guesses) && (guessedChar != randomChar)){

        printf("Guess a letter.\n");
        scanf("%c", &guessedChar);

        if(guessedChar != randomChar){
            int guessesLeft = guesses - i;
            if (guessesLeft > 1){
                printf("Wrong letter. You have %d more tries.\n", guessesLeft);
            }
            else{
                printf("Wrong letter. Last try.");
            }

        }

        else{
            printf("Congratulations.\n");
        }

        i++;
    }
    return 1;
}

输出如下:

Q
Guess a letter.
A
Wrong letter. You have 3 more tries.
Guess a letter.
Wrong letter. You have 2 more tries.
Guess a letter.
B
Wrong letter. Last try.Guess a letter.
Wrong letter. Last try. 

问题:

选择的字母不是随机的,而是 Q。

第一个猜测需要花费两条“生命”?!

【问题讨论】:

  • 您是否阅读过rand(3)scanf(3) 的文档?如果你这样做了,你就不会问这个问题了。另外,请尝试了解 RTFM 和 STFW 的含义。并使用所有警告和调试信息进行编译gcc -Wall -Wextra -g) 顺便说一句,C 和 C++ 是不同的语言
  • 也许还有 GIYF 和 LMGTFY 以提供稍微不那么冒犯性的替代方案。
  • 一个关于风格的小技巧,建议你使用预处理器定义的宏(如guesses)你应该只使用大写字母,如GUESSES。它不是由语言或预处理器强制要求的,它只是几乎在任何地方和每个人都常用的。

标签: c


【解决方案1】:

scanf 的问题是你输入的字母后面的换行符仍然留在输入缓冲区中,下次会被读取。

要解决这个问题,只需告诉scanf 通过在格式字符串中添加一个空格来读取并跳过所有前导空格,例如

scanf(" %c", &guessedChar);
//     ^
//     |
//     Note space here

随机数生成的问题在于您没有为生成器设置种子,这意味着它总是以相同的种子开始并始终生成相同的数字。

要设置种子,你需要在调用rand之前调用srand函数,这是一个不可预测的种子(当前时间通常就足够了):

srand(time(NULL));

然而还有一个更严重的问题,那就是你在初始化之前使用了guessedChar。这将导致undefined behavior,因为未初始化的非静态局部变量具有不确定的值。您必须在使用本地(非静态)变量之前对其进行初始化,未初始化变量的唯一有效用途是对其进行初始化。

【讨论】:

    【解决方案2】:

    您可能总是得到 Q,因为您没有为生成器设置种子。尝试添加

    srand ( time(NULL) );
    

    在生成之前。

    【讨论】:

      【解决方案3】:

      当然。 rand() 生成一个伪随机数。对于这样的许多目的来说,它是足够随机的。但是,您必须更改起点,否则您将始终得到相同的数字。 你应该打电话给srand(something);,你可以替换任何数字,这将使你有很多记住的“游戏”,或者你可以按当前时间(包括毫秒)初始化它,这将是非常不可能重复的。

      #include <time.h>       /* time */
      
      int main(){
      srand (time(NULL));
      ...
      

      【讨论】:

        【解决方案4】:

        您需要在main 的开头使用srand 用于随机字母(不要忘记包含time.h!)

        srand(time(NULL));
        

        至于scanf的问题,在scanf%c前加一个空格:

        scanf(" %c", &guessedChar);
        

        这样做是为了删除\n,当您在输入字符后按下回车键时,stdin 中将出现该\n

        【讨论】:

          【解决方案5】:

          实际上 rand() 不是真正随机的,因为它从固定数组中获取数字,所以每次调用 rand() 时都会得到相同的数字,因此使用相同的等式会得到相同的字符,那么对于首先猜测,你在得到答案之前正在测试,这就是你应该使用的原因

          do
          {
          }
          while ();
          

          而不是

          while()
          {
          }
          

          【讨论】:

          • rand 函数不使用固定数组。
          • 请使用“删除”选项删除答案。
          【解决方案6】:

          如果您只是在输入中输入一个字符,请尝试使用

          getch();
          

          而不是

          scanf(...);
          

          do
          
          {
          }
          while ();
          

          而不是

          while()
          {
          }
          

          既然你回答了,那么你就做测试......

          【讨论】:

          • 获取角色!搞定!
          猜你喜欢
          • 1970-01-01
          • 2011-07-14
          • 1970-01-01
          • 2019-01-30
          • 1970-01-01
          • 2014-06-03
          • 2014-07-16
          • 2013-09-09
          相关资源
          最近更新 更多