为什么对 scanf 的调用会这样工作?标准中有这个吗?
我正在完成 K&R 练习 7.4 和 7.5,并发现了一个我不相信标准规定的恼人的“功能”。
根据K&R,转换规范“%c”的作用方式
“下一个输入字符(默认为 1)放置在指定位置。正常跳过空白字符被抑制;要读取下一个非空白字符,请使用 %1s”< /p>
我的问题是,该声明应该读成这样:
“下一个输入字符(默认 1)将放置在指示的位置。然后,在连续调用 scanf 时再次使用 %c,正常跳过空白被抑制;要读取下一个非空白字符,请使用 %1s"
...因为此代码:
void test1()
{
char t1, t2;
scanf("%c %c", &t1, &t2);
printf("%d\n", t1);
printf("%d\n", t2);
//INPUT is: "b d" (without quotes)
}
导致 t1 = 98 (b) 和 t2 = 100 (d)。 (跳过空格)
但是,此代码:
void test2()
{
char t1, t2;
scanf("%c", &t1);
scanf("%c", &t2);
printf("%d\n", t1);
printf("%d\n", t2);
//INPUT is: "b d" (without quotes)
}
导致 t1 = 98 (b) 和 t2 = 32 (' ')。 (空白 NOT 被跳过)
阅读原始引用,我认为任何有理智的人都会认为它意味着在对 scanf(%c) 的同一次调用期间,空白跳过被抑制。然而,情况似乎并非如此。
似乎为了恢复原来的功能,必须完全清空标准输入。
这应该是这样的吗?是否有记录?因为我环顾四周并没有看到太多这方面的信息。
作为参考,我正在用 C99 编程。
I was finishing up K&R exercises 7.4 and 7.5 and came across an annoying "feature" that I don't believe the standard states.
According to the K&R, the mode of action for the conversion specification "%c"
"The next input characters (default 1) are placed at the indicated spot. The normal skip over white space is suppressed; to read the next non-white space character, use %1s"
My question is, is that statement supposed to be read like:
"The next input characters (default 1) are placed at the indicated spot. THEN, in successive calls to scanf in which %c is used again, the normal skip over white space is suppressed; to read the next non-white space character, use %1s"
...because this code:
void test1()
{
char t1, t2;
scanf("%c %c", &t1, &t2);
printf("%d\n", t1);
printf("%d\n", t2);
//INPUT is: "b d" (without quotes)
}
results in t1 = 98 (b) and t2 = 100 (d). (Whitespace skipped)
However, this code:
void test2()
{
char t1, t2;
scanf("%c", &t1);
scanf("%c", &t2);
printf("%d\n", t1);
printf("%d\n", t2);
//INPUT is: "b d" (without quotes)
}
results in t1 = 98 (b) and t2 = 32 (' '). (Whitespace NOT skipped)
Reading the original quote, I think any reasonable person would take it to mean that during that same call to scanf(%c), the whitespace skip is suppressed. However, that doesn't seem to be the case.
It seems that in order to gain back the original functionality, one would have to completely empty stdin.
Is this supposed to work this way? Has it been documented? Because i've looked around and haven't seen much information on this.
For reference, I'm programming in C99.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这是因为传递给 scanf 的字符串中的空格意味着空格跳过。
如果删除空格并使用
"%c%c"
而不是"%c %c"
,第一个程序的行为将与第二个程序完全相同。所以你的问题的答案是:正常的跳过总是被抑制,只是空间发挥了魔力。
This is because a space in the string passed to scanf means whitespace skip.
If you removed the space and used
"%c%c"
instead of"%c %c"
, the first program would behave exactly as the second.So the answer to your question is: the normal skip is always suppressed, it's just the space that does the magic.
Linux 上
scanf
的手册页指出:我相信这消除了歧义:
c
本身不会跳过空格;格式字符串中必须有明确的空格字符。因此,如果将第二个示例更改为:由于显式空白字符,对
scanf
的第二次调用将跳过空白。The man page for
scanf
on Linux states:I believe that removes the ambiguity:
c
by itself does not skip whitespace; you must have an explicit space character in the format string. Therefore if you change your second example to:The second call to
scanf
will skip whitespace, because of the explicit whitespace character.“%c %c”之间的空格表示跳过第一个和第二个字符之间的空格,第一个“%c”表示读取任何字符。
The blank between "%c %c" means skip whitespace between first and second character, "%c" in first place means read any character.
否 - %c 只是读取输入的下一个字符,无论它是什么。与 %s 形成对比,%s 会跳过任意数量的前导空白,然后读取指定数量的字符(在指定数量处或遇到空白字符时停止)。
但是,在第一段代码中,两个 %c 转换之间的格式字符串中有一个空格。格式流中的空格意味着它应该在尝试下一次转换之前跳过所有连续的空白。
No -- %c just reads the next character of input, regardless of what it is. The contrasts with %s, which skips any amount of leading white space, then reads up to the specified number of characters (stopping at the specified number or when it encounters a whitespace character).
In your first piece of code, however, you have a space in the format string between the two %c conversions. A space in a format stream means it should skip across any and all successive white space before attempting the next conversion.
来自 scanf 手册页
指令是以下之一:
等等。在第一种情况下,您有此指令,但在第二种情况下则没有。
From the scanf man page
A directive is one of the following:
etc. In the first case you have this directive but not in the second.
标准 (C9899:TC3) 表示,对于 %c 和其他一些规范,不会跳过空格 (7.19.6.2.8)。
The standard (C9899:TC3) says that for %c and some other specifications whitespace is not skipped (7.19.6.2.8).