C语言中一个字符串正常工作另一个异常的原因排查求助
问题分析与解决
你的问题出在**scanf("%[^\n]", ...)的使用方式**以及字符串缓冲区的终止符处理上,具体原因和修复方案如下:
核心问题
缓冲区溢出+缺少字符串终止符
你定义的entryTime[5]和exitTime[5]刚好能容纳HH:MM格式的5个字符(比如12:34),但%[^\n]会读取输入中所有非换行符的字符,且不会自动在字符串末尾添加C字符串必需的\0终止符。输入HH:MM按回车后,第一个scanf会把5个字符填满entryTime,没有剩余空间放\0。这会导致后续printf("%s")因找不到终止符触发未定义行为(无输出或读取垃圾数据);而提取分钟时刚好取到数组第3、4位的有效数据,所以能正常解析。残留换行符的潜在干扰
第一个scanf读取完entryTime后,输入缓冲区会残留你按下的换行符\n。虽然你提到exitTime处理正常,但这只是输入操作偶然规避了问题,本质上第一个scanf的缓冲区溢出已经破坏了内存布局。
修复方案
方法1:修正输入逻辑(推荐)
限制scanf的读取长度,同时给字符串数组留足终止符空间,还要处理输入后的换行符:
// 先把数组定义改为char entryTime[6], exitTime[6]; 多1个字节存\0 scanf("%5[^\n]", entryTime); // %5限制最多读5个字符,留位置给终止符 getchar(); // 吃掉输入后的换行符,避免干扰下一个scanf scanf("%5[^\n]", exitTime); getchar();
更稳妥的方式是用fgets读取整行,再手动去除换行符:
fgets(entryTime, sizeof(entryTime), stdin); // 去掉末尾的换行符 size_t len = strlen(entryTime); if (len > 0 && entryTime[len-1] == '\n') { entryTime[len-1] = '\0'; } fgets(exitTime, sizeof(exitTime), stdin); len = strlen(exitTime); if (len > 0 && exitTime[len-1] == '\n') { exitTime[len-1] = '\0'; }
方法2:临时修复时间解析逻辑
如果暂时不修改输入部分,必须给解析用的aux数组添加终止符,否则atoi会读取垃圾数据:
// entryTime 小时解析代码修正 aux[0] = entryTime[0]; aux[1] = entryTime[1]; aux[2] = '\0'; // 必须添加终止符 hAux = atoi(aux);
注意:这只是治标,根源问题还是输入阶段的缓冲区溢出,优先修复输入逻辑。
额外注意事项
- 定义字符串数组时,必须留足
\0的空间:HH:MM是5个字符,数组至少要定义为char xxx[6]。 %[^\n]属于高风险格式符,若不严格限制读取长度极易引发缓冲区溢出,建议优先用fgets处理行输入。
内容的提问来源于stack exchange,提问作者Lucas Bonato Soares
相关产品推荐
相关产品推荐

