【发布时间】:2016-01-21 18:08:31
【问题描述】:
我尝试了解 scanf 和输入缓冲区之间的关系。我使用带有以下格式字符串的 scanf:
int z1,z2;
scanf("%d %d", &z1,&z2);
并尝试理解为什么我在输入 54 之类的数字并按 Enter 后可以输入尽可能多的空格(Enter、Blanks、Tabs)。
据我了解,我按下的每个键都会放入输入缓冲区,直到我按下 Enter。
因此,如果我输入 54 并按 Enter,则输入缓冲区包含 3 个元素、两位数字和换行符。所以我的缓冲区看起来像 [5][4][\n]
现在 scanf/formatstring 从左到右进行评估。所以第一个 %d 匹配到 54,54 存储在 z1 中。
由于格式字符串中的空格,按第一次回车引起的换行符(\n)被“消耗”了。
因此,在对第一个 %d 和空格 (\n) 求值后,缓冲区再次为空。
现在 scanf 尝试评估格式字符串中的第二个(也是最后一个)%d。 因为缓冲区现在是空的,所以 scanf 等待进一步的用户输入(在我的案例键盘中,用户输入 = 从标准输入读取)。
所以缓冲区状态/动作序列是
buffer empty -> call of scanf -> scanf blocks for user input --> user input is: 54 Enter --> buffer contains: [5][4][\n] -> 评估第一个 %d -> 缓冲区包含 [\n] -> 评估空白 -> 缓冲区为空 --> 用户输入的 scanf 块(因为第二个和最后一个 %d 的评估) --> ...
我理解正确吗? (对不起,英语不是我的母语)
问候
【问题讨论】:
-
如果您使用终端,那么终端对输入的处理也会发挥作用;通常程序只会发送完整的输入行,但这不是必须的。使用来自文件的输入重定向来讨论 程序的 行为会更容易,例如
prog < prepared-inp.txt在 Windows 命令 shell 和各种 linux shell 中的工作方式类似。 -
另请注意,“%d%d”格式字符串的行为完全相同;当遇到第一个非数字时(其中是像换行符这样的空格)解析第一个整数停止,并且(第二个)
%d格式正确地跳过它遇到的所有空格,因为它只对数字感兴趣。格式字符串中的空格仅对%c和%[...]有意义(否则会将其分配给它们相应的参数)。 -
我也不喜欢以“缓冲区”范例开头,因为可能没有任何缓冲区,或者可能有任意数量的缓冲区(在键盘中,在远程终端/计算机中,在您的接入点,在您的网卡中,在您的程序中。后者可能就是您的意思(您可以使用
setbuf()更改),但您可以禁用它!)有趣的是字符序列getchar()看到。 它们究竟来自哪里以及它们是否被缓冲在某个地方是次要的。 -
@PeterSchneider 空白对于
%n也很重要。 -
@CoolGuy 您的意思是输入中的空格[未]被跳过-因此在分配值之前[未]计数-取决于
%n之前的空格格式?真的。当然;-)。