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

有些话、适合烂在心里 提交于 2019-11-27 01:59:35
John Bode

From the horse's mouth:

7.21.6.2 The fscanf function

...
5 A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails.
...
7 A directive that is a conversion specification defines a set of matching input sequences, as described below for each specifier. A conversion specification is executed in the following steps:

8 Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier. 284)

9 An input item is read from the stream, unless the specification includes an n specifier. An input item is defined as the longest sequence of input characters which does not exceed any specified field width and which is, or is a prefix of, a matching input sequence. 285) The first character, if any, after the input item remains unread. If the length of the input item is zero, the execution of the directive fails; this condition is a matching failure unless end-of-file, an encoding error, or a read error prevented input from the stream, in which case it is an input failure.
284) These white-space characters are not counted against a specified field width.
285) fscanf pushes back at most one input character onto the input stream. Therefore, some sequences that are acceptable to strtod, strtol, etc., are unacceptable to fscanf.

Emphasis added by me.

Whitespace is not part of a valid integer string, so it makes sense for the %d conversion specifier to skip any leading whitespace. However, whitespace may be valid on its own, so it makes sense for the %c conversion specifier to not skip it.

Per clause 5 above, if you put a blank space in the format string prior to the %c directive, all leading whitespace will be skipped:

scanf(" %c", &ch);

It is consistent behavior, you're just thinking about it wrong. ;)

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

So if I do this:

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

It's not that it's consuming the newline on its own in this case. Try this instead:

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

It will "skip" the second scanf() because it reads in the '\n' at that time. scanf() is consistent and you MUST consume that '\n' if you're going to use it correctly.

It is because whitespace can never be an integer, but whitespace is made up of characters. If you specifically want a character try something like

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

Or use !isalnum() if you want to allow only letters and numbers or !isalpha() for only letters.

I'm no expert, but i've found that doing:

fflush(stdin);

after every scanf helps..

Such as:

scanf("%c", &ch);
fflush(stdin);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!