2

I'm a student in software engineering and I'm on Christmas break in order to get better for the next semester I've been writing various console applications to practice. I have however ran into a problem, I need to get integer input from the user. I've been using fgets to get the string from stdin and then using sscanf to get the integer (Which has worked fine) but if the user enters more than my buffer size trailing characters are left in the stream (Including a newline with skips my next call to fgets). I've looked around and found that most people seem to suggest while(getchar() != '\n'); that however causes me a problem because if there isn't a newline character to be consumed an unnecessary scan for input takes place.

Example:

int ch;
char* buffer = (char*)malloc(BUFSIZ*sizeof(char));
while((ch = getchar()) != '\n' && ch != EOF);
fgets(buffer,BUFSIZ*sizeof(char),stdin);

If the buffer isn't too small and no trailing characters remain in the stream then there is an unecessary getchar() causing input.

Output:

A

A

You typed A

Intended Output:

A

You typed A

I hope that I made this clear enough, I appreciate any help.

Box Box Box Box
  • 5,094
  • 10
  • 49
  • 67
Tomwa ivory
  • 271
  • 1
  • 3
  • 7
  • Please don't use malloc to allocate a buffer, unless it's VERY large. Sooner or later, you'll forget to deallocate it. The stack (in userspace) for both Windows and Linux is several megabytes. If, later on, you need to store the input data into some organized data structure, then you may want to malloc and free that structure. But calling malloc on small buffers that are used locally is a bad choice. – Mats Petersson Dec 20 '12 at 23:09
  • He may need to return it, you don't know the context. – Ramy Al Zuhouri Dec 20 '12 at 23:11
  • could use alloca if it's not being returned. That does get freed when the function returns, but really just declaring an array is probably the way to go. – kdubs Dec 20 '12 at 23:13
  • @Tomwa ivory at your place I would use only fgets.You can ignore the existence of the buffer as long as you ignore the existence of scanf and it's family functions.Remember that if the number of characters read by fgets is greater than the maximum length, the '\n' is not appended in the string, so remove it only if is actually existent in the string. – Ramy Al Zuhouri Dec 20 '12 at 23:15
  • @kdubs I think that this would be longto say , so I created a chatroom: http://chat.stackoverflow.com/rooms/21486/flush-input-in-c-comments – Ramy Al Zuhouri Dec 20 '12 at 23:18
  • @kdubs: far better to use `malloc()` than `alloca()`; the former is at least portable, whereas the latter is tied to the GCC infrastructure. – Jonathan Leffler Dec 21 '12 at 00:09
  • but who doesn't use GCC ? ... 8-) but yes, alloca does have some issues I suppose. I use to love using it back in the day though. – kdubs Dec 21 '12 at 00:35
  • @kdubs Would char buffer[BUFSIZE]; be preferable then? – Tomwa ivory Dec 21 '12 at 00:56
  • that would work just fine. it will be released when you leave the function. You can't use it as a return value. just remember that. – kdubs Dec 21 '12 at 01:29

1 Answers1

6

Check whether the string you read includes a newline.

  • If there is a newline, you don't need to clear the input.
  • If there is no newline, read until you come across one.

On Unix, this loop is reasonable:

int c;
while ((c = getchar()) != EOF && c != '\n')
    ;

Note the EOF test compared with what you quoted (in the text of the question; this is what you quoted in your code snippet, but it is spread over two lines here, which is generally better for readability). I would do this 'gobbling' after the fgets(), rather than before the next one.

On Windows with the Microsoft compilers and libraries, you can play with fflush(stdin) if you are so minded. That has documented behaviour (see the MSDN web site). On Unix, trying fflush(stdin) yields undefined behaviour — don't do it.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    "On Windows" - for certain compilers perhaps; with gcc under Cygwin it does not flush the input. – M.M Jul 30 '14 at 04:41