As well known, former gets()
offers no control/detection of buffer overflow leading to UB. It could have had it had a size parameter.
In addition to @William Pursel good answer concerning int
range.
scanf("%d", ...)
: Input not limited to one line.
gets()
read 1 line. "%d"
in scanf()
, first consumes leading white-space which may include several lines.
scanf("%d", ...)
: does not read the whole line.
Unlike gets()
, scanf("%d", ...)
leaves any input after the input for the int
. This often includes a '\n'
. Not reading the entire lines often sets the seed for subsequent problems.
Depending on goals, scanf("%d", ...)
does not complain about trailing non-numeric text.
C lacks a robust ways to read a line. IMO, fgets()
, gets_s()
, scanf(anything)
, extension getline()
all lack some functionality.
I'd campaign for a int scan_line(size_t sz, char *buf /*, size_t *length_read*/)
that always reads a line, always forms a string in buf
and returns EOF
(end-of-file, input error), 1 on success and 0 when sz
is too small.
Alternatively (and more debatable) *scanf()
could be improved:
Add ability to pass in size
for "%s"
and friends. This is sorely needed.
Defined behavior on int
overflow.
Something like "%#\n"
to scan in white-space, but not '\n'
. Does not contribute to the return value.
Something like "%\n"
to scan in 1 '\n'
. Contributes to the return value. May use a leading space "% \n"
to allow optional leading non-'\n'
white-space.
Offer *scanfln()
which always read just 1 line.