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

C语言猜时间游戏异常求助:多次错误输入后正确答案也报错

问题分析与解决方案

嘿,作为编程新手能尝试做猜谜游戏已经很棒啦!你的问题主要来自数组越界访问和几个C语言里容易踩的小坑,我来一步步帮你拆解修复:

核心问题:数组越界导致内存混乱

当用户输入长度不足5的内容(比如随机字母、短字符串)时,你的代码依然会强行读取tempo[3]和tempo[4],这会超出tempo数组的边界(你定义的char tempo[5]索引范围是0-4,输入短字符串时后面的位置是未初始化的垃圾值),甚至会覆盖栈上的其他变量(比如timeinfo指针、ok标志),导致后续即使输入正确内容,程序状态已经被破坏,出现报错。

除此之外,还有几个小问题会加剧这个错误:

  • ora和min是char[2],但没有添加字符串终止符'\0',atoi函数需要读到终止符才会停止,会读取到内存里的无关数据,转换出错误的整数。
  • do-while循环条件写错了:ok=true是赋值操作,不是判断,这会导致循环永远不会终止,即使猜对了也会继续运行。
  • fflush(stdin)是未定义行为,C标准里不允许用fflush刷新输入缓冲区。
  • scanf("%s",&tempo)里的&是多余的,tempo本身就是数组首地址。

修复后的完整代码

#include <stdio.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h> // 用于rand和srand,标准C必须显式包含

int main(){
    bool ok = false; 
    int tent = 0; 

    // 给tempo多留1位存字符串终止符,hh:mm是5个字符,数组长度至少6
    char tempo[6]; 
    // ora和min需要3位:两位数字+终止符,保证atoi能正确解析
    char ora[3]; 
    char min[3]; 

    // 获取当前时间
    time_t my_time;
    struct tm *timeinfo;
    time(&my_time);
    timeinfo = localtime(&my_time);

    // 初始化随机数生成器
    srand((unsigned int)time(NULL));

    // 谜语提示
    printf("In principio era uno, e il nulla.\n\n");
    printf("Poi l'uomo lo duplico', e tra essi traccio' la via...\n");
    printf("Lo fece ancora... e gli sembro' perfetto.\n");
    printf("Ma non era abbastanza... ");
    printf("Cosi' si spinse piu' in profondita', e sbirciando poco oltre trovo'... ");

    do{
        printf("\nInserisci la risposta (formato hh:mm): ");
        // 限制输入最多5个字符,避免数组越界
        scanf("%5s", tempo);

        // 正确清空输入缓冲区:读取所有剩余字符直到换行
        int c;
        while ((c = getchar()) != '\n' && c != EOF);

        // 先检查输入格式是否符合hh:mm
        if (tempo[2] != ':' || tempo[4] == '\0') {
            tent++;
            int val = rand()%6;
            switch(val){
                case 0: printf("Non ci siamo...\n\n"); break;
                case 1: printf("Pare di no...\n\n"); break;
                case 2: printf("Riprova.\n\n"); break;
                case 3: printf("Pensaci meglio...\n\n"); break;
                case 4: printf("Nah, prova ancora.\n\n"); break;
                case 5: 
                    printf("Ti ho mai detto quante risposte hai gia' provato?\n");
                    printf("Beh... sono ben %d\n\n", tent); 
                    break;
            }
            continue; // 格式不对,直接进入下一轮循环
        }

        // 拆分小时和分钟,添加字符串终止符
        ora[0] = tempo[0];
        ora[1] = tempo[1];
        ora[2] = '\0';

        min[0] = tempo[3];
        min[1] = tempo[4];
        min[2] = '\0';

        // 转换为整数
        int oraint = atoi(ora);
        int minint = atoi(min);

        // 验证时间是否正确
        if(oraint == timeinfo->tm_hour && minint == timeinfo->tm_min){
            printf("\nCOMPLIMENTI! Hai trovato la risposta!\n");
            printf("\n\nEcco le tue prossime istruzioni!\n\n");
            printf("TURFeE1UQXdNREF3TVRFd01EQXdNVEF4TVRFd01ERXhNREV4TVRBd01URXdNVEV4TURFeE1UQXhNVEF4TVRFeE1ERXhNREV3TVRFd01ERXdNVEF4TVRBeE1URXdNREV4TVRBd01URXdNVEV3TVRBd01UQXhNVEF4TVRFeE1ERXhNREV4TVRBPQ==\n\n");
            printf("Che c'e'? devo anche dirti come decifrarle?\n");
            printf("...e va bene...ti do un'indizio\n");
            printf("Ricorda che, a volte, un colpo non basta.");
            ok = true;
        } else {
            tent++;
            int val = rand()%6;
            switch(val){
                case 0: printf("Non ci siamo...\n\n"); break;
                case 1: printf("Pare di no...\n\n"); break;
                case 2: printf("Riprova.\n\n"); break;
                case 3: printf("Pensaci meglio...\n\n"); break;
                case 4: printf("Nah, prova ancora.\n\n"); break;
                case 5: 
                    printf("Ti ho mai detto quante risposte hai gia' provato?\n");
                    printf("Beh... sono ben %d\n\n", tent); 
                    break;
            }
        }
    } while(!ok); // 这里是判断逻辑,不是赋值,猜对后终止循环

    // 等待用户按回车退出
    printf("\nPremi invio per uscire...");
    while(getchar() != '\n');
    getchar();
    return 0;
}

关键修复点说明

  1. 彻底避免数组越界:

    • 把tempo长度改为6,用来存储hh:mm(5个字符)+ 字符串终止符'\0'。
    • 使用scanf("%5s", tempo)限制输入最多5个字符,防止用户输入过长内容。
    • 先检查输入格式:判断tempo[2]是否为':',且tempo[4]不为空,格式不对直接跳过后续处理。
  2. 修复字符串解析问题:

    • 把ora和min改为char[3],手动添加'\0',保证atoi能正确转换字符串为整数。
  3. 修正循环逻辑:

    • 把while(ok=true)改为while(!ok),确保猜对后循环终止。
  4. 替换不安全的缓冲区操作:

    • 用手动读取剩余字符的方式替换fflush(stdin),避免未定义行为。

这样修改后,不管用户输入多少次错误内容,都不会破坏内存,输入正确的hh:mm格式时间后就能正常触发胜利逻辑啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:12:59