scanf测试在C中的函数内失败

时间:2017-03-20 17:30:55

标签: c scanf

我试图用一个简单的游戏做一个程序,让用户猜出这个数字。我的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX 30
#define TRYING 5

void guessnumber(int, int, int *);

int main(void) {
    int mytry = 1;

    guessnumber(MAX, TRYING, &mytry);

    if (mytry <= TRYING)
        printf("Congratulations! You got it right in %d tries\n", mytry);
    else
        printf("Unfortunately you could not guess the number in the number of tries predefined\n");

    printf("End\n");

    return EXIT_SUCCESS;
}

void guessnumber(int _n, int _m, int *_mytry) {
    srandom(time(NULL));
    int generated = 0, mynum = 0, test = 0;

    generated = rand() % (_n + 1);

    printf("Welcome to \"Guess the number\" \n");
    printf("A number between 0 and %d was generated\n", _n);
    printf("Guess the number:\n");

    while (*_mytry <= TRYING) {
        test = scanf(" %d", &mynum);

        if (test != 1 || mynum < 0 || mynum > MAX)
            printf("ERROR: please enter a valid number \n");
        else
        if (mynum > generated)
            printf("Wrong! The number your trying to guess is smaller\n");
        else
        if (mynum < generated)
            printf("Wrong ! The number your trying to guess is bigger\n");
        else
            break;
        *_mytry = *_mytry + 1;
    }
}

好的,现在该程序工作正常,除了一件事:scanf测试。 如果我尝试输入一个超出我的范围的数字(负数或高于我的上限),它会起作用,但如果我试图输入一个字母,它就会失败。它的作用是打印错误_m次的消息,然后打印出来#34;不幸的是你无法猜测预定义次数的数量&#34;和&#34;结束&#34;。

我做错了什么,如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

如果输入了某个字符,您就会尝试正确检测它

  if(test!=1 ......

但你没有采取任何措施来纠正它。

详细说明,一旦输入了一个字符,就会导致匹配失败。因此输入不被消耗,循环回落到起源位置,只有循环计数器增加。现在,先前的输入未被消耗,再次被送到scanf()导致失败。

这样,循环继续,直到循环条件为假。此外,对于scanf()的每次点击,由于未使用的数据已经存在于输入缓冲区中,因此不会给出新的提示

解决方案:当您遇到故障时,需要清除现有内容的输入缓冲区。你可以做点什么

while ((c = getchar()) != '\n' && c != EOF);

清除现有内容的缓冲区。

答案 1 :(得分:1)

输入字母时,scanf()会将字母留在输入流中,因为它与%d转换说明符不匹配。最简单的方法是使用getchar()删除不需要的字符:

if (test != 1) {
    getchar();
}

更好的解决方案是使用fgets()获取输入行,使用sscanf()来解析输入:

char buffer[100];
while (*_mytry<=TRYING)
{
    if (fgets(buffer, sizeof buffer, stdin) == NULL) {
        fprintf(stderr, "Error in fgets()");
        exit(EXIT_FAILURE);
    }

    test=sscanf(buffer, "%d", &mynum);

    if(test!=1 || mynum<0 || mynum>MAX)
        printf ("ERROR: please enter a valid number \n");

    else if(mynum>generated)
        printf("Wrong! The number your trying to guess is smaller\n");

    else if(mynum<generated)
        printf("Wrong ! The number your trying to guess is bigger\n");

    else
        break;
    *_mytry=*_mytry+1;
}

在上面的代码中,请注意已从格式字符串中删除了前导空格。格式字符串中的前导空格会导致scanf()跳过前导空格,包括换行符。例如,当第一个转换说明符为%c时,这很有用,因为任何先前的输入都可能留下了换行符。但是,%d转换说明符(以及大多数其他转换说明符)已经跳过前导空格,因此这里不需要它。

此外,您的代码有srandom()而不是srand();并且对srand()的调用应该只进行一次,并且可能应该在main()的开头。并且,带有前导下划线的标识符在C中保留,因此您应更改名称_m_n_mytry