8

I am currently reading this book "C11 Programming for beginners" and in the scanf() chapter it says:

"Always add a leading space before the first control string character to ensure accurate character input." As in:

scanf(" %s", whatever);

The control string " %s", has a space before it. I know it sounds pretty self-explanatory, but I don't really get what could go wrong, and how this space ensures accurate character input.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Stanley
  • 69
  • 1
  • 3
  • 4
    That better come with a big caveat Single char `%c` fetching is likely the dominant reasoning behind that sledge-hammer statement, and failure to provide the specifics like that make me question the voodoo teaching ideology of that text. "Always do " without some sort of explanation *why* you should follow that mantra, and how things can go wrong if you *don't*, are often more confusing than helpful (case in point, your posting this question...). Anyway, you may find [**this answer**](http://stackoverflow.com/questions/14419954/reading-a-single-character-in-c/14419972#14419972) helpful. – WhozCraig Oct 15 '14 at 21:10
  • Is that book really called *C11 Programming for beginners*? Wasn't `scanf` superseded by `scanf_s` in C11? – Anders Marzi Tornblad Jun 17 '16 at 09:35
  • @AndersMarziTornblad: No. `scanf_s()` is an optional function defined in [Annex K §3.5.3.4 The `scanf_s` function](http://port70.net/~nsz/c/c11/n1570.html#K.3.5.3.4). Microsoft would rather you used their version of [`scanf_s()`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/scanf-s-scanf-s-l-wscanf-s-wscanf-s-l?view=msvc-170) but few other compilers/libraries have implemented it. The signatures of these functions agree, something which is not guaranteed with the `_s` (safer) functions. – Jonathan Leffler Nov 26 '21 at 14:30
  • `"%s"` means: ignore optional leading whitespace and read a whitespace delimited string... `" %s"` means ignore optional whitespace and then ignore optional leading whitespace and read a whitespace delimited string. – pmg Nov 26 '21 at 18:43

2 Answers2

6

@WhozCraig well stated shortcomings to this advice. Its comes without rational nor detail. Further it does not apply to "%s" as "%s" consumes leading white-space with or without a leading space.

A leading white-space, be it ' ', '\t', '\n', etc. all do the same thing: direct scanf() to consume and not store optional leading white-space char. This is useful as typical usage of previous scanf() does not consume the user's '\n' from the Enter

scanf("%d", &some_int);
scanf("%c", &some_char);  // some_char is bound to get the value '\n'

All scanf() input specifiers ignore leading spaces, except 3: "%c", "%n", "%[]".

Simple directives do benefit with the leading space as in the following. Previous left-over white-space is consumed before '$'.

int Money;
scanf(" $%d", &Money);

Often, though not always, a leading space before "%c" is beneficial as when reading a single char of user input.

char ch;
scanf(" %c", &ch);

What is most wrong with the advice is that 1) when using "%s", supplying a width parameter is essential to robust code and 2) the return value should be checked.

char buf[30];
int cnt = scanf("%29s", buf);
if (cnt != 1) Handle_NoInput_or_EOF_IOError();

Note that all the conversion specifiers except %c, %[…] (scan sets) and %n skip leading white space automatically, so the advice is not really relevant with %s, or %d or %lf, etc.

Lastly, I recommend using fgets() rather than scanf() whenever one can — which is usually the case.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Thank you chux :) As far as I understood, when using scanf() with "%c", "%n", or "%[]", scanf will store a leading space in a char. How does it store in the same char if a char can hold a single character only? – Stanley Oct 16 '14 at 18:42
  • 3
    @Stanley `scanf(" %c", &ch);` will consume and discard optional leading white-space. Then will store a non-white-space `char` in `ch`. `scanf("%c", &ch);` will store the first `char` that comes along into `ch`. `"%n"`, or `"%[]"` work quite differently. – chux - Reinstate Monica Oct 16 '14 at 21:46
  • Really nice answer, appreciate your effort to this site! – NeoZoom.lua Feb 26 '21 at 14:29
1

"Always add a leading space before the first control string character to ensure accurate character input."

This is to consume any trailing white space characters or leading white space characters in the stdin that might have been left by previous user input (like the carriage return), before the scanf reads the user input. Of course, all the conversions except %c, %[…] (scan sets) and %n do this automatically, so the advice is not really relevant with %s.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Haris
  • 12,120
  • 6
  • 43
  • 70