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; }
关键修复点说明
彻底避免数组越界:
- 把
tempo长度改为6,用来存储hh:mm(5个字符)+ 字符串终止符'\0'。 - 使用
scanf("%5s", tempo)限制输入最多5个字符,防止用户输入过长内容。 - 先检查输入格式:判断
tempo[2]是否为':',且tempo[4]不为空,格式不对直接跳过后续处理。
- 把
修复字符串解析问题:
- 把
ora和min改为char[3],手动添加'\0',保证atoi能正确转换字符串为整数。
- 把
修正循环逻辑:
- 把
while(ok=true)改为while(!ok),确保猜对后循环终止。
- 把
替换不安全的缓冲区操作:
- 用手动读取剩余字符的方式替换
fflush(stdin),避免未定义行为。
- 用手动读取剩余字符的方式替换
这样修改后,不管用户输入多少次错误内容,都不会破坏内存,输入正确的hh:mm格式时间后就能正常触发胜利逻辑啦!
内容的提问来源于stack exchange,提问作者Pi7on
相关产品推荐
相关产品推荐

