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?
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.
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.
You can use fgets or gets_s:
http://www.java2s.com/Code/C/Console/Usefgetstoreadstringfromstandardinput.htm
According to man 3 gets, fgets.
Related
The Apple developer documentation states:
Security Note for fgets: Although the fgets function provides the ability to read a limited amount of data, you must be careful when using it. Like the other functions in the “safer” column, fgets always terminates the string. However, unlike the other functions in that column, it takes a maximum number of bytes to read, not a buffer size.
The last sentence sounds wrong to me. For comparison, here is what POSIX says:
The fgets() function shall read bytes from stream into the array pointed to by s until n-1 bytes are read, or a <newline> is read and transferred to s, or an end-of-file condition is encountered. A null byte shall be written immediately after the last byte read into the array.
Here is what an ISO C draft from 2005 says:
The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array.
The FreeBSD man page says the same as the C standard and POSIX.
This makes me think that the Apple documentation is clearly wrong. The simplest explanation is that Apple didn't know better when they published this article. But although simple, this hypothesis doesn't feel plausible to me.
Are there other reasons that Apple could deviate from the wording of the C standard?
Even early (early 1970s) versions of fgets() specified that n is the buffer size, and that the buffer will be terminated with a '\0'.
Kernighan and Ritchie reflected that correctly in all their books and documentation.
However, a number of authors of introductory texts (who I won't attempt to name, since I'm sure I'll miss some, and all deserve to be equally embarrassed) documented that up to n characters could be written to the buffer, and that the trailing '\0' might be dropped in some cases.
The fgets functions reads at most the size minus one bytes from the file. If the wrong value is passed as the buffer size then fgets might write out of bounds.
So the quote from the Apple documentation that you show is correct in that the value is more related to the number of bytes to read from the file. But on the other hand any normal code would use the actual buffer size when falling fgets. And if that number is input from a user then it should be validated before use.
On the other hand the documentation continues to state (thanks for the note Sander De Dycker)
In practical terms, this means that you must always pass a size value that is one fewer than the size of the buffer to leave room for the null termination. If you do not, the fgets function will dutifully terminate the string past the end of your buffer, potentially overwriting whatever byte of data follows it.
And this is wrong. The size argument passed to fgets always includes the string terminator. At least according to the C standard.
I thought getchar() or fflush(stdin) was used to take the newline or space left by the previous input, because the gets() function is unable to differentiate between that newline and the input we provide. We did not need those when we use %s on the scanf function. Why do we need it when we use %c or %d on the same function?
The fact is that fflush() has no defined behavior for input streams, there are some specific implementation defined behaviors. Also, there is fpurge() in glibc which does what you want.
When using scanf() the rule is that it will stop when it finds a white space character as returned by isspace(), except when using %c which behaves differently as it can capture white spaces, or ignore them all if preceded by a white space.
Also, the gets() function is dangerous and was recently removed from the c standard so you should not use it or refer to it as an example.
The fgets() function, which is a better version of gets() does capture the final '\n' if it can, i.e. if the number of characters captured so far does not exceed the value of it's second parameter so you don't need to flush anything after it.
You should consider, that scanf() not only leaves the last '\n' in the input buffer but any white space following it too. So a single getchar() is usually not enough, you should getchar() as many white spaces as were left there to ensure the apparent behavior of fflush(stdin).
If the code is
scanf("%s\n",message)
vs
gets(message)
what's the difference?It seems that both of them get input to message.
The basic difference [in reference to your particular scenario],
scanf() ends taking input upon encountering a whitespace, newline or EOF
gets() considers a whitespace as a part of the input string and ends the input upon encountering newline or EOF.
However, to avoid buffer overflow errors and to avoid security risks, its safer to use fgets().
Disambiguation: In the following context I'd consider "safe" if not leading to trouble when correctly used. And "unsafe" if the "unsafetyness" cannot be maneuvered around.
scanf("%s\n",message)
vs
gets(message)
What's the difference?
In terms of safety there is no difference, both read in from Standard Input and might very well overflow message, if the user enters more data then messageprovides memory for.
Whereas scanf() allows you to be used safely by specifying the maximum amount of data to be scanned in:
char message[42];
...
scanf("%41s", message); /* Only read in one few then the buffer (messega here)
provides as one byte is necessary to store the
C-"string"'s 0-terminator. */
With gets() it is not possible to specify the maximum number of characters be read in, that's why the latter shall not be used!
The main difference is that gets reads until EOF or \n, while scanf("%s") reads until any whitespace has been encountered. scanf also provides more formatting options, but at the same time it has worse type safety than gets.
Another big difference is that scanf is a standard C function, while gets has been removed from the language, since it was both superfluous and dangerous: there was no protection against buffer overruns. The very same security flaw exists with scanf however, so neither of those two functions should be used in production code.
You should always use fgets, the C standard itself even recommends this, see C11 K.3.5.4.1
Recommended practice
6 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.
(emphasis mine)
There are several. One is that gets() will only get character string data. Another is that gets() will get only one variable at a time. scanf() on the other hand is a much, much more flexible tool. It can read multiple items of different data types.
In the particular example you have picked, there is not much of a difference.
gets - Reads characters from stdin and stores them as a string.
scanf - Reads data from stdin and stores them according to the format specified int the scanf statement like %d, %f, %s, etc.
gets:->
gets() reads a line from stdin into the buffer pointed to by s until either a terminating newline or EOF, which it replaces with a null byte ('\0').
BUGS:->
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
scanf:->
The scanf() function reads input from the standard input stream stdin;
BUG:->
Some times scanf makes boundary problems when deals with array and string concepts.
In case of scanf you need that format mentioned, unlike in gets. So in gets you enter charecters, strings, numbers and spaces.
In case of scanf , you input ends as soon as a white-space is encountered.
But then in your example you are using '%s' so, neither gets() nor scanf() that the strings are valid pointers to arrays of sufficient length to hold the characters you are sending to them. Hence can easily cause an buffer overflow.
Tip: use fgets() , but that all depends on the use case
The concept that scanf does not take white space is completely wrong. If you use this part of code it will take white white space also :
#include<stdio.h>
int main()
{
char name[25];
printf("Enter your name :\n");
scanf("%[^\n]s",name);
printf("%s",name);
return 0;
}
Where the use of new line will only stop taking input. That means if you press enter only then it will stop taking inputs.
So, there is basically no difference between scanf and gets functions. It is just a tricky way of implementation.
scanf() is much more flexible tool while gets() only gets one variable at a time.
gets() is unsafe, for example: char str[1]; gets(str)
if you input more then the length, it will end with SIGSEGV.
if only can use gets, use malloc as the base variable.
From The GNU C Programming Tutorial:
The fgets ("file get string") function is similar to the gets
function. This function is deprecated -- that means it is obsolete
and it is strongly suggested you do not use it -- because it is
dangerous. It is dangerous because if the input data contains a null
character, you can't tell. Don't use fgets unless you know the data
cannot contain a null. Don't use it to read files edited by the user
because, if the user inserts a null character, you should either
handle it properly or print a clear error message. Always use
getline or getdelim instead of fgets if you can.
I thought the fgets function stops when it encounters a \0 or \n; why does this manual page suggest a null byte is "dangerous" when fgets should handle the input properly? Furthermore, what is the difference between getline and fgets, and is the fgets function truly considered deprecated in the C99 or future C standards?
No, fgets is not actually deprecated in C99 or the current standard, C11. But the author of that tutorial is right that fgets will not stop when it encounters a NUL, and has no mechanism for reporting its reading of such a character.
The fgets function reads at most one less than the number of characters specified by n
from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file.
(§7.21.7.2)
GNU's getdelim and getline have been standardized in POSIX 2008, so if you're targeting a POSIX platform, then it might not be a bad idea to use those instead.
EDIT I thought there was absolutely no safe way to use fgets in the face of NUL characters, but R.. (see comments) pointed out there is:
char buf[256];
memset(buf, '\n', sizeof(buf)); // fgets will never write a newline
fgets(buf, sizeof(buf), fp);
Now look for the last non-\n character in buf. I wouldn't actually recommend this kludge, though.
This is just GNU propaganda. In no official sense is fgets deprecated. gets however is dangerous and deprecated.
Of the below three functions:
getc
getchar &
scanf
which is the best one for reading a character from stdin and why?
Are there any known disadvantages or limitations for any of these functions which makes one better than the other?
If you simply want to read a single character from stdin, then getchar() is the appropriate choice. If you have more complicated requirements, then getchar() won't be sufficient.
getc() allows you to read from a different stream (say, one opened with fopen());
scanf() allows you to read more than just a single character at a time.
The most common error when using getchar() is to try and use a char variable to store the result. You need to use an int variable, since the range of values getchar() returns is "a value in the range of unsigned char, plus the single negative value EOF". A char variable doesn't have sufficient range for this, which can mean that you can confuse a completely valid character return with EOF. The same applies to getc().
from Beej's Guide to C Programming
All of these functions in one way or another, read a single character
from the console or from a FILE. The differences are fairly minor, and
here are the descriptions:
getc() returns a character from the specified FILE. From a usage
standpoint, it's equivalent to the same fgetc() call, and fgetc() is a
little more common to see. Only the implementation of the two
functions differs.
fgetc() returns a character from the specified FILE. From a usage
standpoint, it's equivalent to the same getc() call, except that
fgetc() is a little more common to see. Only the implementation of the
two functions differs.
Yes, I cheated and used cut-n-paste to do that last paragraph.
getchar() returns a character from stdin. In fact, it's the same as
calling getc(stdin).