为什么scanf(“%d”,[...])不消耗'\ n'?而scanf(“%c”)呢?

时间:2012-11-07 17:57:28

标签: c scanf format-specifiers

Here,我在接受的答案中看到了这句话:

  

大多数转换说明符都会跳过包含换行符的前导空格,但%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'将被第二个{{1}消耗与scanf。我在linux和windows上测试了gcc,行为是一样的:

  

gcc(GCC)4.7.2 20120921(Red Hat 4.7.2-2)
  版权所有(C)2012 Free Software Foundation,Inc。
  这是免费软件;查看复制条件的来源。没有   保证;甚至不适用于适销性或特定用途的适用性。

所以我的问题是:%c%d为什么表现不同w.r.t. %c中的'\n'

4 个答案:

答案 0 :(得分:12)

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

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'

答案 1 :(得分:10)

来自horse's mouth

7.21.6.2 fscanf函数

...
5由白色空格字符组成的指令通过读取输入来执行 第一个非空白字符(仍未读取),或直到没有其他字符可以 被阅读。指令永远不会失败 ...
7作为转换规范的指令定义了一组匹配的输入序列,如 下面针对每个具体说明。转换规范按以下步骤执行:

8跳过输入的空格字符(由isspace函数指定),除非 规范包括[cn指定者 284)

9除非规范包含n指定符,否则将从流中读取输入项。 <强>一种 输入项被定义为不超过的最长输入字符序列 任何指定的字段宽度,它是匹配输入序列的前缀,或者是匹配输入序列的前缀。 285) 输入项目之后的第一个字符(如果有)仍未读取。如果输入的长度 item为零,指令的执行失败;这种情况是匹配失败,除非 文件结束,编码错误或读取错误阻止了流的输入,其中 这是一个输入失败的情况。
284)这些空白字符不计入指定的字段宽度 285)fscanf将最多一个输入字符推回到输入流上。因此,有些序列 strtod,strtol等可接受的,对fscanf来说是不可接受的。

我强调的重点。

空格不是有效整数字符串的一部分,因此%d转换说明符跳过任何前导空格是有意义的。但是,空格本身可能是有效的,因此%c转换说明符跳过它是有意义的。

上面的第5条,如果在%c指令之前的格式字符串中放置一个空格,将跳过所有前导空格:

scanf(" %c", &ch);

答案 2 :(得分:2)

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

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

如果您只想使用字母和数字,请使用!isalnum(),或仅使用!isalpha()字母。

答案 3 :(得分:-2)

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

fflush(stdin);

每次扫描后都有帮助..

如:

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