为什么对 scanf 的调用会这样工作?标准中有这个吗?

发布于 2024-09-30 12:17:50 字数 1076 浏览 1 评论 0原文

我正在完成 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

那片花海 2024-10-07 12:17:50

这是因为传递给 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.

一刻暧昧 2024-10-07 12:17:50

Linux 上 scanf 的手册页指出:

c     匹配长度由最大字段宽度指定的字符序列(默认为 1); next 指针必须是指向 char 的指针,并且必须有足够的空间容纳所有字符(不添加终止空字节)。通常跳过前导空白的现象被抑制。要首先跳过空格,请在格式中使用显式空格。

我相信这消除了歧义:c 本身不会跳过空格;格式字符串中必须有明确的空格字符。因此,如果将第二个示例更改为:

scanf("%c", &t1);
scanf(" %c", &t1);

由于显式空白字符,对 scanf 的第二次调用将跳过空白。

The man page for scanf on Linux states:

c     Matches a sequence of characters whose length is specified by the maximum field width (default 1); the next pointer must be a pointer to char, and there must be enough room for all the characters (no terminating null byte is added). The usual skip of leading white space is suppressed. To skip white space first, use an explicit space in the format.

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:

scanf("%c", &t1);
scanf(" %c", &t1);

The second call to scanf will skip whitespace, because of the explicit whitespace character.

寄离 2024-10-07 12:17:50

“%c %c”之间的空格表示跳过第一个和第二个字符之间的空格,第一个“%c”表示读取任何字符。

The blank between "%c %c" means skip whitespace between first and second character, "%c" in first place means read any character.

爱的十字路口 2024-10-07 12:17:50

否 - %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.

神经暖 2024-10-07 12:17:50

来自 scanf 手册页

指令是以下之一:

  • 空白字符序列(空格、制表符、换行符等;请参阅 isspace(3))。该指令匹配输入中任意数量的空格,包括无空格。

等等。在第一种情况下,您有此指令,但在第二种情况下则没有。

From the scanf man page

A directive is one of the following:

  • A sequence of white-space characters (space, tab, newline, etc; see isspace(3)). This directive matches any amount of white space, including none, in the input.

etc. In the first case you have this directive but not in the second.

我不咬妳我踢妳 2024-10-07 12:17:50

标准 (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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文