为何需按回车键终止scanf函数?
核心原因不是scanf的规则,而是你的终端(命令行窗口)默认使用「行缓冲」模式——你敲的所有按键都会先存在终端的临时缓冲区里,只有按下回车键,终端才会把这一整行的内容一次性传给程序的输入流(stdin)。scanf只能从stdin里读取数据,在终端没把数据传过来之前,scanf根本没东西可读,只能一直等待。
拆解你遇到的具体场景:
输入
40后不按回车:
你敲的4和0都存在终端缓冲区里,没传到程序的stdin,scanf自然不会开始处理。只有按回车,终端把"40\n"传给stdin,scanf("%d", &age)才会从stdin里读取连续的数字40,然后停止,把值存入age变量。输入
40a后不按回车:
同样,4、0、a都留在终端缓冲区,scanf没收到任何数据,只能等。按回车后,终端把"40a\n"传给stdin,scanf读取到40后遇到非数字的a,就停止读取,把40存入变量,剩下的"a\n"会留在stdin里(如果后续还有输入操作,会从这里开始读)。输入
4 0后不按回车:
还是终端缓冲的问题,4、空格、0都没传给stdin。按回车后,终端把"4 0\n"传给stdin,scanf("%d")会先跳过前导空白字符吗?不——准确说,%d格式符会自动跳过前导的空白字符(空格、换行、制表符),但这里你输入的是4加空格加0,scanf会先读取4,遇到空格时(空格不属于数字序列)就停止读取,把4存入age,剩下的" 0\n"会留在stdin中,程序继续执行。
额外说明:
终端的行缓冲是默认行为,不是C语言或scanf的强制规定。有些场景(比如嵌入式系统的串口终端)可以配置成「无缓冲」或「字符缓冲」模式——输入一个字符就立刻传给程序,这时候scanf("%d")会在你输入非数字字符时立刻处理,不需要按回车。但普通PC的命令行窗口,默认都是行缓冲,需要回车来触发终端把数据传给程序。
你觉得“像是定义如此”其实没错,但这个定义是终端默认交互规则的定义,和scanf的格式解析规则是两个独立的环节——前者负责把用户输入传给程序,后者负责解析程序收到的数据。
内容的提问来源于stack exchange,提问作者Alexander Jonsson

