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

C语言中一个字符串正常工作另一个异常的原因排查求助

问题分析与解决

你的问题出在**scanf("%[^\n]", ...)的使用方式**以及字符串缓冲区的终止符处理上,具体原因和修复方案如下:

核心问题

  1. 缓冲区溢出+缺少字符串终止符
    你定义的entryTime[5]和exitTime[5]刚好能容纳HH:MM格式的5个字符(比如12:34),但%[^\n]会读取输入中所有非换行符的字符,且不会自动在字符串末尾添加C字符串必需的\0终止符。输入HH:MM按回车后,第一个scanf会把5个字符填满entryTime,没有剩余空间放\0。这会导致后续printf("%s")因找不到终止符触发未定义行为(无输出或读取垃圾数据);而提取分钟时刚好取到数组第3、4位的有效数据,所以能正常解析。

  2. 残留换行符的潜在干扰
    第一个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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:27:28