为什么对scanf的调用是这样的?这是标准吗?

时间:2010-11-03 21:47:43

标签: c input stdin

我正在完成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('')。 (空格跳过)

阅读原始引用,我认为任何合理的人都会认为这意味着在同一次调用scanf(%c)期间,空格跳过被抑制。但是,情况似乎并非如此。

似乎为了获得原始功能,人们必须完全清空标准输入。

这应该是这样的吗?它有记录吗?因为我环顾四周,并没有看到太多关于此的信息。

作为参考,我在C99编程。

6 个答案:

答案 0 :(得分:13)

这是因为传递给scanf的字符串中的空格意味着空格跳过。 如果您删除了空格并使用"%c%c"而不是"%c %c",则第一个程序的行为与第二个程序完全相同。

所以你的问题的答案是:正常跳过始终被抑制,它只是做魔术的空间。

答案 1 :(得分:3)

Linux上scanf的手册页说明:

  

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

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

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

scanf的第二次调用将跳过空格,因为有明确的空白字符。

答案 2 :(得分:2)

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

答案 3 :(得分:2)

否 - %c只读取输入的下一个字符,无论它是什么。与%s形成鲜明对比,跳过任意数量的前导空格,然后读取指定数量的字符(以指定的数字停止或遇到空白字符时)。

但是,在第一段代码中,两个%c转换之间的格式字符串中有一个空格。格式流中的空格意味着它应该在尝试下一次转换之前跳过任何和所有连续的空格。

答案 4 :(得分:0)

来自scanf手册页

指令是以下之一:

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

等。在第一种情况下,你有这个指令但不在第二种情况下。

答案 5 :(得分:0)

标准(C9899:TC3)表示对于%c和其他一些规范空格不会被跳过(7.19.6.2.8)。