14

Is it allowed to use scanf(" ") without additional arguments to ignore initial whitespaces?
I'm using getchar() to read the chars of a word, and I want to ignore the whitespaces before the word (whitespaces after are used to check the end of the word).
The code is the following, is it correct?

char *read_word() {
    int size = 2;
    int char_count = 0;
    char *s;
    char ch;

    s = mem_alloc(size);

    scanf(" ");

    while ((ch = getchar()) != EOF) {
        if (char_count >= size) {
            s = mem_realloc(s, size++);
        }

        if (ch == ' ' || ch == '\n') {
            s[char_count] = '\0';
            break;
        }

        s[char_count++] = ch;
    }

    return s;
}
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
raxell
  • 677
  • 6
  • 19

4 Answers4

13

From the definition of the scanf() function (*), emphasis mine:

The format is composed of zero or more directives: one or more white-space characters, an ordinary multibyte character (neither % nor a white-space character), or a conversion specification.

[...]

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.

So scanf( " " ); is perfectly valid.


(*): ISO/IEC 9899:1999, 7.19.6.2 The fscanf function, section 3 and 5.

The other *scanf functions are defined in terms of this section.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
9

To add to the other answers, all of the following are valid:

scanf(" ");      // skip over whitespace
scanf("xyz");    // skip over the longest leading substring of "xyz" if present
                 // i.e. "xyz" or "xy" or "x"
scanf(" %*s ");  // skip over the first string and whitespace around it
dxiv
  • 16,984
  • 2
  • 27
  • 49
5

The manpage says:

The format string consists of a sequence of directives

...

A directive is one of the following:

• 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.

...

so yes, it is a legal use of scanf.


If you're after efficiency:

int c;
while(isspace(c=getchar()) {;}

leads down a more efficient path, as getchar et. al. tend to have _unlocked counterparts, unlike scanf.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • While not an issue in this case, I would be careful about relying on manpages. They usually do not distinguish clearly between what's ISO C, and what's POSIX -- and that *can* make a difference. So if the question is about whether something is legal or not "in C", standard trumps manpage. (And I'm not saying that just because I quoted it, but because I'm working on and with non-POSIX platforms from time to time.) – DevSolar Feb 11 '16 at 21:02
  • @DevSolar I agree. We posted pretty much simultaneously. I mightn't have posted mine if I'd seen yours first, but I think mine still has some value (=I'm getting points from it :D) so I'll keep it. – Petr Skocik Feb 11 '16 at 23:30
  • Note that to make your `getchar` example equivalent to `scanf(" ")` you will have to `ungetc(c, stdin)` at the end. – Nate Eldredge Feb 11 '16 at 23:56
4

I would instead try:

int skip = -1;
if (scanf(" %n", &skip)>=0 && skip>0)   {
  // you have skipped skip spaces
}

The >=0 test checks that scanf did not fail (e.g. because of EOF on stdin, or input error). The skip>0 test checks that we have skipped at least one spacelike byte. The %n conversion specifier gives the number of parsed bytes.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547