You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言使用scanf()时如何忽略特定扫描调用?附数学游戏优化咨询

问题根因分析

你遇到的需额外输入数字的问题以及隐藏bug如下:

  • scanf("%s%i", foo, &bar)的格式串要求必须连续输入一个字符串+一个整数,缺少任意一个参数scanf都会阻塞等待用户输入,所以单独输入show-stats时程序会一直等待后续整数输入,这就是需要多输入0的原因。
  • char foo[] = ""定义的字符数组长度仅1字节(只能存字符串结束符\0),输入任意长度大于0的字符串都会发生缓冲区溢出,属于严重内存越界bug,会破坏程序其他变量的数值。
  • 字符串匹配逻辑写反:strcmp判断两个字符串相等时返回0,你原代码的if(strcmp(foo,"show-stats"))逻辑是输入不是show-stats的时候才打印分数,完全不符合预期。
最小复现代码修复方案
#include <stdio.h>
#include <string.h>

int main() {
    int bar = 0;
    // 给字符串预留足够缓冲区
    char foo[100] = {0};
    int score = 1;
    char input_buf[128] = {0};
    
    // 先读整行避免输入阻塞
    fgets(input_buf, sizeof(input_buf), stdin);
    // 尝试匹配字符串+整数,返回值是成功匹配的参数个数
    int match_cnt = sscanf(input_buf, "%s %i", foo, &bar);
    
    // 字符串相等时才打印统计
    if(strcmp(foo,"show-stats") == 0) {
        printf("Score is %i\n", score);
    }
    
    // 成功匹配到两个参数、且bar等于2时才执行加倍逻辑
    if(match_cnt == 2 && bar == 2) {
        score = bar * 2;
        printf("Doubled Points.\n");
    }
    return 0;
}
完整游戏代码优化建议
  • 随机数种子初始化错误:srand(time(NULL))不要放在死循环内部,time(NULL)返回秒级时间戳,同一秒内多次调用srand会导致生成的随机数完全重复,应该移到循环外,程序启动时仅调用一次即可。
  • 变量未初始化:score变量没有赋初始值,首次运行时的分数是内存中的随机垃圾值,建议按需求初始化为0或1。
  • 减法逻辑bug:x和y是无符号整型,当x < y时做减法会得到无符号溢出的超大数值,存入int类型的sum会变成负数,用户根本无法答对,建议生成减法题时强制要求x >= y,如果生成的x比y小就交换两者数值。
  • 输入鲁棒性差:当前scanf("%i",&ans)如果用户输入非数字内容,会直接匹配失败,输入缓冲区的垃圾数据会一直残留,导致后续所有输入都错乱,建议先读整行再判断内容是数字答案还是show-stats这类命令。
  • 代码冗余:两次打印统计数据的逻辑完全重复,可以抽成单独的打印函数,传入需要的参数即可,后续修改统计项只需要改一次。
  • 拼写错误:提示语Your correct!应为You're correct!。
  • 新增命令支持:把原来直接读整数的逻辑改成先读整行,先判断行内容是不是show-stats等命令,如果是就执行对应逻辑,否则尝试转换为整数作为答案处理。
优化后完整游戏示例代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>

#define VER 10
#define DIV "-----"

// 抽离公共打印统计函数
void print_stats(int score, int max, int correct, int wrong, int show_answer, int answer) {
    printf("%sStats%s\n", DIV, DIV);
    if (show_answer) {
        printf("The correct answer was %i\n", answer);
    }
    printf("Score:%i\n"
           "Max possible number:%i\n"
           "Correct Answers:%i\n"
           "Wrong Answers:%i\n"
           "%s%s%s\n",
           score, max, correct, wrong, DIV, DIV, DIV);
}

int main()
{
    system("clear");
    // 随机数种子仅初始化一次
    srand(time(NULL));
 
    unsigned int x,y;
    int ans,sum;
    unsigned int max = 10;
    // 初始化分数
    int score = 0;
    char operation;
    int correctAnswers = 0, wrongAnswers = 0;
    char input_buf[128] = {0};
    char cmd[64] = {0};

    printf("Math game\nVersion %i.\n", VER);
    for (; ;) {
        // 生成运算数
        x = rand() % max;
        y = rand() % max;
        // 生成运算类型
        operation = rand() % 2;
        switch (operation) {
            case 0:
                operation = '+';
                sum = x + y;
                break;
            case 1:
                operation = '-';
                // 保证减法结果为正
                if (x < y) {
                    unsigned int tmp = x;
                    x = y;
                    y = tmp;
                }
                sum = x - y;
                break;
        }
        // 输出问题
        printf("What is %i %c %i? (输入show-stats可直接查看统计)\n", x, operation, y);
        
        // 读整行输入
        if (!fgets(input_buf, sizeof(input_buf), stdin)) {
            continue;
        }
        // 去掉末尾换行符
        input_buf[strcspn(input_buf, "\n")] = 0;

        // 先判断是不是命令
        if (strcmp(input_buf, "show-stats") == 0) {
            print_stats(score, max, correctAnswers, wrongAnswers, 0, 0);
            continue;
        }

        // 尝试转换为数字答案
        char *endptr;
        ans = strtol(input_buf, &endptr, 10);
        // 输入不是有效数字
        if (endptr == input_buf || !isspace(*endptr) && *endptr != 0) {
            printf("输入无效,请输入数字答案或者show-stats命令\n");
            continue;
        }

        // 判断答案正误
        if (ans == sum) {
            score++;
            correctAnswers++;
            max++;
            printf("You're correct! +1!\n");
            print_stats(score, max, correctAnswers, wrongAnswers, 0, 0);
        } else {
            score--;
            wrongAnswers++;
            if(max>10) {
                max--;
            }
            printf("Wrong! -1\n");
            print_stats(score, max, correctAnswers, wrongAnswers, 1, sum);
        }
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者cs07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 01:15:04