2

Are there any dangers to using %*c in scanf() to clear the buffer when necessary.

For example:

char c;
for (int i = 0; i < 5; i++) {
  scanf("%c%*c", &c);
}

Or

char* str;
char c;
int i;
scanf("%s", str);
scanf("%d%*c", &i);
scanf("%c%*c", &c);

Should there be any concern for buffer overflows or other security issues? There seems to be no formal documentation for the usage of the asterisk in scanf this way for C (EDIT This is not true), so I'm having trouble finding out exactly what happens to the extra characters that are inputted. Is there a better way of clearing the scanf buffer in C?

hesson
  • 1,812
  • 4
  • 23
  • 35
  • 4
    Yes, [no](http://linux.die.net/man/3/scanf) [formal](http://www.unix.com/man-page/FreeBSD/3/scanf/) [documentation](http://www.kernel.org/doc/man-pages/online/pages/man3/scanf.3.html) [at](http://msdn.microsoft.com/en-us/library/kwwtf9ch(v=vs.71).aspx) [all](http://developer.apple.com/library/ios/documentation/system/conceptual/manpages_iphoneos/man3/scanf.3.html). – melpomene Dec 01 '12 at 03:55
  • @melpomene, the best comment I've seen, EVER on StackOverflow – Aniket Inge Dec 01 '12 at 03:59
  • @melpomene My mistake, I guess by 'official' I meant official C documentation, however I have just realized that it doesn't actually exist in the same way that there is JavaDocs for Java. I'm still wondering what happens to the suppressed character? Is it written to something like /dev/null on a Linux machine? – hesson Dec 01 '12 at 04:04
  • You never said "official". If you want official (without paying money), http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf is your best bet (it's the C99 standard plus a few technical corrigenda). – melpomene Dec 01 '12 at 04:10
  • This html-ified version of it is much nicer: http://port70.net/~nsz/c/c99/n1256.html And for C11, this: http://port70.net/~nsz/c/c11/n1570.html – R.. GitHub STOP HELPING ICE Dec 01 '12 at 04:11
  • 1
    The suppressed character(s) are simply ignored; read and later overwritten or otherwise lost. – Jonathan Leffler Dec 01 '12 at 07:44
  • Note that there's also the POSIX specification of [`fscanf()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html), which is a superset of the Standard C library specified in C99 (because POSIX 2008 pre-dates C 2011). – Jonathan Leffler Dec 01 '12 at 07:46

3 Answers3

4

You'll have better luck conceptualizing the task you're trying to accomplish as "how do I read and discard any junk that the user might've typed after what I care about", which will lead you to constructs such as

int c;
while ((c = getchar()) != EOF && c != '\n') ;  /* discard till end of line or EOF */

But also, you can avoid the entire problem by not using scanf in the first place, which is a good idea for several other reasons. Read entire lines with getline, if you have it, or fgets if you don't, and parse them by hand.

Community
  • 1
  • 1
zwol
  • 135,547
  • 38
  • 252
  • 361
  • there is no `getline()` in standard C – Aniket Inge Dec 01 '12 at 04:03
  • @Aniket That's why I said _if you have it_. Good C libraries do. – zwol Dec 01 '12 at 04:04
  • ah, :-) Good C library != StdC library then? – Aniket Inge Dec 01 '12 at 04:05
  • Most of the interesting programs that require _only_ the facilities in C89 have already been written. I didn't used to recommend `getline` on portability grounds, but it's in POSIX.1-2008, which is getting close to old enough to rely on nowadays. And [gnulib has a drop-in implementation you can use](http://www.gnu.org/software/gnulib/manual/html_node/getline.html). – zwol Dec 01 '12 at 04:08
  • @Aniket There is no such thing as a "StdC library". – melpomene Dec 01 '12 at 04:11
  • `getline` can be written in terms of just the standard C library, using nothing but `getc`, `malloc`, and `free`. – R.. GitHub STOP HELPING ICE Dec 01 '12 at 04:12
  • @melpomene says there is no such thing as "StdC library" R.. says "standard C library", in the very next statement. – Aniket Inge Dec 01 '12 at 04:15
  • 1
    @melpomene tell it to the guy who wrote this: http://en.wikibooks.org/wiki/C_Programming/Standard_libraries#ANSI_Standard – Aniket Inge Dec 01 '12 at 04:17
  • 1
    OK, different meaning of "library". The C standard library is an abstract specification. What you actually use in your programs is a concrete implementation of this specification (such as glibc), most of which provide functionality beyond what's described in the C standard. – melpomene Dec 01 '12 at 04:19
  • 2
    Then you mean there is no Standard C Language(and a Compiler) even? Because its just an abstract specification(ANSI C?) – Aniket Inge Dec 01 '12 at 04:24
  • There definitely is no "standard C compiler", not even as a specification. But my real point was that you don't "have" the standard C library to run programs with. You seem to be using the word "library" in a different sense than Zack. – melpomene Dec 01 '12 at 04:28
-1

If you want to clear the scanf buffer, Here is

char c;
for(int i = 0; i < 5; i++) {
    scanf("%c", &c);
    while(getchar() != '\n')
        continue;
}

Or

char c;
for(int i = 0; i < 5; i++) {
    scanf("%c", &c);
    fflush(stdin);
}

However, your code is dangerous...

sleepy_dog
  • 277
  • 1
  • 2
  • 11
  • Can you please tell me why it would be dangerous my way? Also, I'm using C not C++, so would fflush(stdin) still work? – hesson Dec 01 '12 at 03:47
  • If you enter a character, when you press Enter. scanf accept you input the characters also produce a newline character '\n' carriage returns will be fed into the buffer, next time call scanf, the newline character '\n' is assigned to the character variable c – sleepy_dog Dec 01 '12 at 03:48
  • There is no "scanf buffer" and `fflush(stdin)` is just wrong. – melpomene Dec 01 '12 at 03:51
  • @melpomene I don't understand what you mean by "There is no 'scanf buffer'". Is this just semantics, or does scanf actually have no buffer? If it has no buffer, then how does it retain characters from previous inputs? – hesson Dec 01 '12 at 03:54
  • char a, b; scanf("%c", &a); scanf("%c", &b); printf("%d %d\n", a, b); /* Have a test, You may know why... */ – sleepy_dog Dec 01 '12 at 03:55
  • 1
    @hesson `scanf` does not retain characters, `stdin` does (and it may not even be `stdin` but something outside of the program). I don't understand what you mean by "is this just semantics, or does scanf actually have no buffer?". What do you think "semantics" means? – melpomene Dec 01 '12 at 03:59
  • 1
    @melpomene: If you read the MSDN on [`fflush()`](http://msdn.microsoft.com/en-us/library/9yky46tz.aspx), you'll find: _The `fflush` function flushes a stream. If the file associated with stream is open for output, `fflush` writes to that file the contents of the buffer associated with the stream. If the stream is open for input, `fflush` clears the contents of the buffer._ This is different from the C standard and the Unix systems, where the behaviour of `fflush()` on input streams is undefined. This seems to be a common cause of confusion for Windows programmers moving to Unix. – Jonathan Leffler Dec 01 '12 at 04:52
  • 1
    When the EOF condition occurs, `while(getchar() != '\n') continue;` is an infinite loop. Better to use `int c; ... while(getchar() != '\n' && c != EOF);` – chux - Reinstate Monica Sep 02 '14 at 18:18
-1

there is no scanf buffer, but there is an "input" buffer. And the best way to clear it is to use rewind(stdin). But this approach has problems if the input has been redirected.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78