1

In the following snippet, after reading the int the '\n' remains in the stdin, and is read by second scanf.

Is scanf called on the enter, and then reads what is in the stdin, or is it called before typing happens?

What signals to scanf that the input is ready? For example if I type on my keyboard 12345, and scanf is reading an int, it can be read as 1, 12, 123 ... If the enter is the signal to read, why doesn't scanf clear that character from the stdin?

#include <stdio.h> int main() { int a; scanf( "%d", &a ); char b; scanf( "%c", &b ); printf( "%d %c", a, b ); return 0; } 
13
  • 1
    In the snippet, b will read the '\n' left by the entry of a. To correct use " %c" as the format string where the leading whitespace in the format string will consume the whitespace ('\n' being whitesapace as is space, tab, etc..) Always validate the return of scanf(). The return is the number of successful conversions that take place. So if (scanf ("%d", &a) == 1) you know a valid integer was provided. (validation with "%c" isn't needed except to check for EOF.) Commented Dec 18, 2021 at 2:24
  • Thanks for the answer! Is scanf called before the '\n', and waits for it? Commented Dec 18, 2021 at 2:26
  • scanf doesn't consume trailing whitespace. The comment above gives you the work around to consume it before the next conversion. Commented Dec 18, 2021 at 2:27
  • When you press [Enter] after the entering the value for a a '\n' is inserted in the input stream. If you fail to account for the newline -- your next attempted read will read the \n'. This is also the primary reason that you are encouraged to take all user input with fgets() an a sufficiently sized buffer and then parse any needed information from the buffer using sscanf() instead. fgets() will consume the trailing '\n' Commented Dec 18, 2021 at 2:27
  • So any white space can signal to scanf to read? Commented Dec 18, 2021 at 2:30

1 Answer 1

2

scanf works somewhat like a pattern-matching function. For example:

scanf("%d %f", &a, &b); 

Would first look for an int starting from left, ignoring all whitespaces. If some unexpected character appeared before successful read, the functions returns immediately. Now, the final character in the string will be read and then put back for the next call of scanf to read. That is why we need to press the return key once more to expend the next call and nothing else is read. In order to work around this, we can pattern match the forthcoming scanf call as such:

scanf(" %c", &c1); 
  • Note the space in front of the string. This indicates to scanf that one whitespace character is expected to be matched.

  • Important to note that scanf will discard ALL leading whitespace - no matter how many whitespace characters there are - thanks David C. Rankin

Sign up to request clarification or add additional context in comments.

10 Comments

Almost - "indicates to scanf that one whitespace character is expected to be matched" - NO. It tells scanf() to discard ALL leading whitespace -- no matter how many whitespace characters there are.
More importantly, I'm not sure the OP understands the concept of buffered I/O. scanf is "line oriented"- won't read ANYTHING until you hit "newline" (or unless you explicitly turn buffering off). Hence his confusion about "12345".
You can correct with "... at least one ...". Which would make it correct. From man 3 scanf "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."
All it means (for line-buffered input) is when the user enters input, it isn't processed by scanf() as each character is typed. Instead, each character is placed in an internal read-buffer (that you have no control over) and when [Enter] is pressed, the entire line of input is passed to scanf() to be matched against the format-string. scanf() then returns the number of successful conversions that took place which tells you whether all variables you expected scanf() to fill -- were filled.
It is buffered in a read-buffer and then made available as stdin. I would have to go look at the glibc source to determine what buffer is used (and I don't think that matters much), but you are correct that it is made available as stdin to the program. This area has changed a bit in the last few years.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.