This is a commonly discussed topic, full of opinion but interesting none the less. I have observed that a large majority of those that have already responded to similar questions on this site fall on the side of fgets()
. I am one of them. I find fgets()
to be much better to use for user input than scanf()
with few exceptions. scanf()
is considered by many as as sub-optimal method for handling user input. For example
"...it will tell you whether it succeeded or failed, but can tell you only approximately where it failed, and not at all how or why. You
have very little opportunity to do any error recovery."
(jamesdlin). But in the interest of attempting balance, will start off citing this discussion.
For user input that comes from stdin
, i.e. keyboard input, fgets()
will be a better choice. It is much more forgiving in that the string it reads can be fully validated before conversion is attempted
One of the few times using a form of scanf(): fscanf() would be okay to use might be when converting input from a very controlled source, i.e. from reading a strictly formatted file with repeating predictable fields.
For more discussion, this comparison of the two highlights additional advantages and disadvantages of both.
Edit: to address OP additional question about overflow:
"One more thing I want to ask is: even when we use fgets what happen if user enter characters more than boundary (I mean a lot of
characters), does it lead to buffer overflow? Then how to deal with
it?"
[fgets()](https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm is nicely designed to prevent buffer overflow, simply by using its parameters properly, eg:
char buffer[100] = {0};
...
while fgets(buffer, sizeof buffer, stdin);
This prevents input greater than the buffer size from being processed, thus preventing the overflow.
even using scanf()
preventing buffer overflow is pretty straight forward: Use a width specifier in the format string. If you want to read input for example and limit input size from user to 100 characters max, the code would include the following:
char buffer[101] = {0};// includes space for 100 + 1 for NULL termination
scanf("%100s", buffer);
^^^ width specifier
However with numbers, overflow is not so nice using scanf()
. To demonstrate, use this simple code, inputting the two values indicated in comment one per run:
int main(void)
{
int val = 0;
// test with 2147483647 & 2147483648
scanf("%d", &val);
printf("%d\n", val);
return 0;
}
For the second value, my system throws the following:
NON-FATAL RUN-TIME ERROR: "test.c", line 11, col 5, thread id 22832: Function scanf: (errno == 34 [0x22]). Range error
`
Here you need to read in a string, then follow with a string to number conversion using one of the strto_()
functions: strtol(), strtod(), ...). Both include the ability to test for overflow before causing a run-time warning or error. Note that using atoi()
, atod()
will not protect from overflow either.