scanf如何知晓终止for循环?C代码异常输入运行机制疑问
为啥你的scanf在输入不匹配时还能“正常”跑起来?
嘿,这个问题其实戳中了很多初学者对scanf的误解——它根本不是“知晓”要终止循环,而是你的输入流和格式字符串不匹配时,scanf直接停在那儿了,然后循环按自己的逻辑走完,最后那个scanf刚好捡漏匹配上了而已。咱们一步步拆解清楚:
首先得搞懂scanf的核心逻辑:它是严格按照你给的格式字符串,从输入流里逐字符匹配提取数据,过程中会自动跳过空格、换行、制表符这类空白字符。如果遇到格式字符串和输入流对不上的情况,它会立刻停止当前的scanf调用,把不匹配的字符原封不动留在输入流里,同时返回成功匹配的参数个数(失败时返回0,遇到文件结束返回EOF)。
先看正常输入的情况:「num 1 num 2 end 3」
- 第一次循环的
scanf(" num %d", &arr[i]):跳过空白后,精准匹配到num,然后把整数1读到arr[0]里,返回1(表示成功匹配1个参数)。这时候输入流剩下num 2 end 3。 - 第二次循环的
scanf:同样匹配num,把2读到arr[1],返回1。输入流剩下end 3。 - 最后一个
scanf(" end %d", &end):匹配end后把3读到end,完美收尾,程序输出和预期一致。
再看你疑惑的输入:「num 1 end 2」
- 第一次循环的
scanf还是成功的:匹配num和1,arr[0]被赋值为1,输入流剩下end 2。 - 第二次循环执行
scanf(" num %d", &arr[i]):scanf先跳过空白(这里没有),然后尝试匹配格式里的num,但输入流的第一个非空白字符是e,和格式里的n对不上。这时候这个scanf直接失败,返回0,完全不会修改arr[1]的值(它还是你初始化的0),同时把end 2原封不动留在输入流里。 - 循环按自己的逻辑走:i从0开始,执行两次后i变成2,满足
i<2不成立,退出循环。然后轮到最后一个scanf(" end %d", &end),这时候输入流里正好是end 2,scanf一眼就匹配上了end,然后把2读到end里,返回1。所以程序看起来“正常运行”,但本质上arr[1]根本没被输入赋值,只是初始值刚好是0而已。
最关键的坑:你没检查scanf的返回值
你的代码完全忽略了scanf的返回值,这是C语言里非常常见的错误。如果加上返回值检查,你就能立刻发现第二次scanf调用失败了:
for (i=0; i<2 ; i++){ if (scanf(" num %d", &arr[i]) != 1) { printf("读取arr[%d]失败!\n", i); // 这里可以做错误处理,比如直接退出循环 break; } }
这样就能避免误以为程序“正常”,实际上却没正确读取数据的情况——毕竟如果输入的不是end而是其他乱码,最后那个scanf也会失败,到时候end还是初始的0,你可能就更懵了。
内容的提问来源于stack exchange,提问作者Alex Lavriv
相关产品推荐
相关产品推荐

