22

From cplusplus.com

The most recent revision of the C standard (2011) has definitively removed this function from its specification

The function is deprecated in C++ (as of 2011 standard, which follows C99+TC3).

I just wanted to know what is the alternative to gets() in C11 standard?

bames53
  • 86,085
  • 15
  • 179
  • 244
Shash
  • 4,160
  • 8
  • 43
  • 67

4 Answers4

16

In C11 gets has been substituted by gets_s that has the following declaration:

char *gets_s(char *str, rsize_t n);

This function will read at most n-1 chars from stdin into *str. This is to avoid the buffer overflow vulnerability inherent to gets. The function fgets is also an option. From http://en.cppreference.com/w/c/io/gets:

The gets() function does not perform bounds checking, therefore this function is extremely vulnerable to buffer-overflow attacks. It cannot be used safely (unless the program runs in an environment which restricts what can appear on stdin). For this reason, the function has been deprecated in the third corrigendum to the C99 standard and removed altogether in the C11 standard. fgets() and gets_s() are the recommended replacements.

Never use gets().

Given that gets_s is defined in an extension to the standard, only optionally implemented, you should probably write your programs using fgets instead. If you use fgets on stdin your program will also compile in earlier versions of C. But keep in mind the difference in the behavior: when gets_s has read n-1 characters it keeps reading until a new line or end-of-file is reached, discarding the input. So, with gets_s you are always reading an entire line, even if only a part of it can be returned in the input buffer.

Joni
  • 108,737
  • 14
  • 143
  • 193
  • 7
    It should be noted that `gets_s` is optional, need not be present if the implementation doesn't define `__STDC_LIB_EXT1__`, and if it does, need `__STDC_WANT_LIB_EXT1__` defined to 1 (if that's not defined at all, it's implementation-defined whether the functions in annex K are included in the respective headers). – Daniel Fischer Oct 15 '12 at 11:33
  • 6
    `fgets` should be used. `gets_s` is an optional interface that only exists on Windows and was mentioned in the standard only for political reasons. Pretty much everybody outside of MS finds the _s interfaces misguided and harmful. Reportedly the standardized behavior of some or all of the _s interfaces even differs from the only existing implementations (the MS ones), making their use even more harmful. – R.. GitHub STOP HELPING ICE Oct 15 '12 at 13:05
  • 1
    I suspect that you have misunderstood the behavior of gets_s. Just like fgets, it reads at most n-1 characters. The difference is that gets_s stops if it encounters a new line character. Nothing in the standard indicates that it keeps reading after n-1. Don't confuse the standard version with various non-standard implementations that existed before C11. – Lundin Oct 15 '12 at 13:45
  • @Lundin Do you have access to the text of the C11 standard? All references I can find document this behaviour, including this "committee draft" http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf: *Unlike the fgets function, gets_s maintains a one-to-one relationship between input lines and successful calls to gets_s. Programs that use gets expect such a relationship.* – Joni Oct 15 '12 at 14:31
  • @Joni Yes I have the actual C11 standard and not just a draft. I will include the text in the "informative" answer I made, for reference. – Lundin Oct 15 '12 at 14:47
  • @Lundin The text I quoted is from a footnote on the page that specifies the behavior of `gets_s`. Was it removed from the final version? Just curious.. – Joni Oct 16 '12 at 06:25
  • @Joni Ah ok, well nothing appears to have changed between the draft and the standard, the text regarding gets_s is identical. I posted the relevant, normative part of the standard (btw please note that foot notes are never normative in ISO standards). The only differences between fgets and gets_s, is that fgets can be used on any kind of file stream and not just stdin, while gets_s automatically stops reading if it encounters \n. – Lundin Oct 16 '12 at 10:41
  • @Lundin: Would another major difference be that gets_s() omits the newline from the buffer, thus avoiding the need to scan the newly-received string in order to find and eliminate it? – supercat Aug 04 '16 at 19:49
9

Others have already answered the question. For the sake of completeness, this is the C standard's recommendation:

ISO9899:2011 K.3.5.4.1/6

Recommended practice

The fgets function allows properly-written programs to safely process input lines too long to store in the result array. In general this requires that callers of fgets pay attention to the presence or absence of a new-line character in the result array. Consider using fgets (along with any needed processing based on new-line characters) instead of gets_s.

So you should use fgets whenever possible.

EDIT

gets_s behavior is specified to be:

ISO9899:2011 K.3.5.4.1/4

Description

The gets_s function reads at most one less than the number of characters specified by n from the stream pointed to by stdin, into the array pointed to by s. No additional characters are read after a new-line character (which is discarded) or after end-of-file. The discarded new-line character does not count towards number of characters read. A null character is written immediately after the last character read into the array.

If end-of-file is encountered and no characters have been read into the array, or if a read error occurs during the operation, then s[0] is set to the null character, and the other elements of s take unspecified values.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 4
    Note that `gets_s()` reports a constraint violation if there is neither a newline nor EOF within the `n-1` characters; it is an error to get an overlong line. – Jonathan Leffler Mar 10 '14 at 08:23
6

You can use fgets or gets_s:

http://www.java2s.com/Code/C/Console/Usefgetstoreadstringfromstandardinput.htm

Ta Duy Anh
  • 1,478
  • 9
  • 16
4

According to man 3 gets, fgets.

jbowes
  • 4,062
  • 22
  • 38
  • The gets equivalent in the C11 standard is gets_s, although it should technically be the same thing as fgets(..., stdin); – Lundin Oct 15 '12 at 13:03
  • 1
    "In an optional annex added for political reasons" is hardly "in the C11 standard". You will not find a C11-conformant version of the _s functions anywhere, because nobody plans to implement them. – R.. GitHub STOP HELPING ICE Oct 15 '12 at 13:06
  • 2
    @R.. Annex K of C11 is normative, even though it is not mandatory to implement. What this means in practice, is that C implementations can no longer contain weird, non-standard gets_s functions that have a behavior that collides with the standard. I also bet that GCC will implement these functions: that compiler just loves optional, redundant, pointless features. I would however recommend fgets(), for compatibility reasons. – Lundin Oct 15 '12 at 13:51
  • 1
    Since they're library functions, they're outside the scope of GCC. If you mean glibc, I'm pretty sure the maintainers have already expressed a strong disinterest in adding them. Also, I'm not even sure that non-standard versions of the functions are non-conformant unless an implementation advertises (via the appropriate predefined macros) that it supports Annex K. If MS's functions really do differ from the standard, I think the chance of them getting changed is approximately zero; they don't seem to care about conformance anyway. – R.. GitHub STOP HELPING ICE Oct 15 '12 at 14:12