Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do calls to scanf work like this? Is this in the standard?

Tags:

c

input

stdin

I was finishing up K&R exercises 7.4 and 7.5 and came across an annoying "feature" that I don't believe the standard states.

According to the K&R, the mode of action for the conversion specification "%c"

"The next input characters (default 1) are placed at the indicated spot. The normal skip over white space is suppressed; to read the next non-white space character, use %1s"

My question is, is that statement supposed to be read like:

"The next input characters (default 1) are placed at the indicated spot. THEN, in successive calls to scanf in which %c is used again, the normal skip over white space is suppressed; to read the next non-white space character, use %1s"

...because this code:

void test1()
{
   char t1, t2;

   scanf("%c %c", &t1, &t2);
   printf("%d\n", t1);
   printf("%d\n", t2);

   //INPUT is: "b d" (without quotes)
}

results in t1 = 98 (b) and t2 = 100 (d). (Whitespace skipped)

However, this code:

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)
}

results in t1 = 98 (b) and t2 = 32 (' '). (Whitespace NOT skipped)

Reading the original quote, I think any reasonable person would take it to mean that during that same call to scanf(%c), the whitespace skip is suppressed. However, that doesn't seem to be the case.

It seems that in order to gain back the original functionality, one would have to completely empty stdin.

Is this supposed to work this way? Has it been documented? Because i've looked around and haven't seen much information on this.

For reference, I'm programming in C99.

like image 281
Kevin Avatar asked Dec 02 '25 08:12

Kevin


2 Answers

This is because a space in the string passed to scanf means whitespace skip. If you removed the space and used "%c%c" instead of "%c %c", the first program would behave exactly as the second.

So the answer to your question is: the normal skip is always suppressed, it's just the space that does the magic.

like image 125
Michał Trybus Avatar answered Dec 05 '25 21:12

Michał Trybus


The man page for scanf on Linux states:

c     Matches a sequence of characters whose length is specified by the maximum field width (default 1); the next pointer must be a pointer to char, and there must be enough room for all the characters (no terminating null byte is added). The usual skip of leading white space is suppressed. To skip white space first, use an explicit space in the format.

I believe that removes the ambiguity: c by itself does not skip whitespace; you must have an explicit space character in the format string. Therefore if you change your second example to:

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

The second call to scanf will skip whitespace, because of the explicit whitespace character.

like image 21
Eric Melski Avatar answered Dec 05 '25 21:12

Eric Melski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!