为什么scanf函数(“%d”,[...])不会消耗 '\\ N'? 而scan

2019-06-19 00:59发布

在这里 ,我看到了在接受的答案这样的说法:

大部分的转换说明跳过前导空白包括换行,但%c没有。

对我来说,没有在本不同的行为清楚的理由,我本来期望统一的一个(例如总是跳过或从不)。

我到了这样的问题,采用了一块C代码是这样的:

#include "stdio.h"

int main(void){

    char ch;
    int actualNum;

    printf("Insert a number: ");
    scanf("%d", &actualNum);
    // getchar();

    printf("Insert a character: ");
    scanf("%c", &ch);

    return 0;
}

交换两个scanf小号解决了问题,以及在(注释) getchar ,否则'\n'第一插入的将由第二被消耗scanf%c 。 我在GCC都在Linux和Windows测试,该行为是相同的:

海湾合作委员会(GCC)4.7.2 20120921(红帽4.7.2-2)
版权所有(C)2012自由软件基金会。
这是自由软件; 看到复印条件源。 有没有保修; 甚至不是针对特定目的的适销。

所以我的问题是:为什么%d%c行为不同WRT '\n'scanf

Answer 1:

从马的嘴 :

7.21.6.2 fscanf函数

...
5的空白字符(一个或多个)构成的指令是通过读取输入到第一个非空白字符(这仍然是未读)执行,或直到没有更多的字符可被读取。 该指令永远不会失败。
...
7.一种指令,该指令是转换SPECI音响阳离子德连接定义了一个组匹配的输入序列,如下面对于每个SPECI音响ER描述的。 A转换SPECI音响阳离子在下面的步骤执行:

8输入的空白字符(如由编SPECI音响isspace函数)被跳过, 除非SPECI音响阳离子包括[c ,或n SPECI音响ER。 284)

9.一种输入项目是从该流读取,除非SPECI音响阳离子包括n SPECI音响ER。 的输入项被解音响定义为不超过任何SPECI音响编音响场宽度并且是或的预连接的x,一个匹配的输入序列的输入字符的最长序列。 285)的第一个字符,如果有的话,在输入项保持未读。 如果输入项的长度是零,则该指令的执行失败; 该条件匹配的失败,除非最终OF-音响文件,编码错误,或读出错误从流,在这种情况下它是一个输入故障防止输入。
284)这些空白字符不被计数针对一个特定的编音响场宽度。
285)的fscanf推回至多一个输入字符到的输入流。 因此,一些这样的序列是可以接受的的strtod,strtol将等等,都是不能接受的fscanf。

由我添加的重点。

空白是不是一个有效的整数字符串的一部分,因此是很有意义的%d转换符跳过任何前导空格。 不过,空白可能是对自己有效,因此是很有意义的%c转换符跳过它。

按照上述第5,如果你把一个空格在之前的格式字符串%c指令,所有领先的空白将被忽略:

scanf(" %c", &ch);


Answer 2:

这是一致的行为,你只是想错了。 ;)

scanf("%c", some_char); // reads a character from the key board.
scanf("%d", some_int);  // reads an integer from the key board.

所以,如果我这样做:

printf("Insert a character: ");
scanf("%c", &ch);                // if I enter 'f'. Really I entered 'f' + '\n'
                                 // scanf read the first char and left the '\n'
printf("Insert a number: ");
scanf("%d", &actualNum);      // Now scan if is looking for an int, it sees the '\n'
                              // still, but that's not an int so it waits for the 
                              // the next input from stdin

这不是它的消耗在这种情况下对自己的换行符。 试试这个:

char ch;
char ch2;
printf("Insert a character: ");
scanf("%c", &ch);
printf("Insert another character: ");
scanf("%c", &ch2); 

它会“跳过”第二个scanf() ,因为它在读取'\n'在那个时候。 scanf()是一致的,你必须消耗的是'\n'如果你要正确地使用它。



Answer 3:

这是因为空格不可能是整数,但空格是由字符组成。 如果你特别想要一个字符尝试类似

scanf("%c", &ch );
while(isspace(c))
    scanf("%c" , &ch);

或者使用!isalnum()如果你希望只允许字母和数字或!isalpha()只字母。



Answer 4:

我不是专家,但我发现,这样做:

fflush(stdin);

以后每scanf的帮助..

如:

scanf("%c", &ch);
fflush(stdin);


文章来源: Why scanf(“%d”, […]) does not consume '\\n'? while scanf(“%c”) does?