Modern C++ has a lot of useful functions coming from C. One of them was the gets()
function that we use to get string inputs and that we were able to use in C++11 or earlier. In C++14, the gets
function was removed, while fgets
or other input functions remain there. If you have older C++ code that uses the gets()
functions your C++14 version compiler will not compile it. Why was the gets
function removed? In this post, we explain what the gets
function is, why the std::gets
function was removed by the C++14 standards, and how can we use similar functions or alternatives to the gets()
function.
What was the gets() function considered dangerous in C++?
In C++11 and before, we were able to use the gets
function. The std::gets
function was first defined in the C language and was available in C++11 and earlier. The gets
function reads inputs into a given char string. When a char
string has a newline character, it is considered the end of input, and an end-of-file condition occurs. The return value is captured on success, or a null pointer on failure.
The syntax below is deprecated in C++11 and removed in C++14.
1 2 3 |
char* gets( char* str ); |
Here is an example of a dangerous gets
function,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> #include <cstdio> int main() { char str[8]; gets(str); printf(str: %s", str); return 0; } |
Why was the std::gets function removed In C++14?
According to C++14 document N4140 (Page 1237), the “use of gets is considered dangerous“, because the std::gets
function does not check the bounds of a char
array. This makes gets
extremely vulnerable to buffer-overflow attacks. In other words, the std::gets function cannot be used safely. The std::gets()
function was deprecated in C++11 and removed completely in C++14. If you REALLY need to use it in your apps, then there are some alternatives – for example you can use std::fgets()
.
If we use gets()
, it is impossible to tell without knowing the data in advance how many characters will be read, and because std:: gets()
will continue to store characters past the end of the buffer, it is extremely ‘dangerous’ to use.
Here is the definition from C++14 (Document Number: N4140, Page 1237).
1 2 3 4 5 6 7 |
C.3.4 Clause 27: input/output library Change: gets is not defined. Rationale: Use of gets is considered dangerous. Effect on original feature: Valid C++ 2011 code that uses the gets function may fail to compile in this International Standard. |
They added a note to [c.files] saying that the C function gets() is not part of C++ and they removed gets
from tables 134 and 153. We should note that there are some compilers that still support the gets()
function. The gets
function may be only used if the program runs in an environment that restricts inputs from stdin
.
Are there any alternatives to the std::gets function in modern C++?
First of all, never use std::gets()
function, use std::fgets()
instead or other input methods of modern C++. There is no way to check the size of input before we store data to that variable. If you have older C++ code that uses the gets
function and you want to modernize it, you can use std::fgets()
as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <iostream> #include <array> #include <cstdio> #include <cstring> // C++14: never use the std::gets() function, use std::fgets() instead or other input methods of modern C++ int main() { std::array<char, 4> arr; std::cout << "Enter a string (max 4 char):"; if ( std::fgets(arr.data(), arr.size(), stdin) ) { unsigned int len = 1 + std::strlen( arr.data() ); std::printf( "Array:'%s' Length: %u ", arr.data(), len ); } else { std::cout << "Error: I/O error, the end of stream input has been reached, or unknown error"; } system("pause"); return 0; } |
If you still need more alternatives gets_s function can be used. 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 input. POSIX 2008 provides a safe alternative to gets() called getline()
, which can be used in C++ applications.
Of course in modern console applications use the std::string and the std::cin can be used to get string inputs. In C++ Builder, VCL or FMX apps, use UnicodeString and TEdit components to get strings.
For more information about the removal of gets() function, please see this, https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1420.htm
C++ Builder is the easiest and fastest C and C++ IDE for building simple or professional applications on the Windows, MacOS, iOS & Android operating systems. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for cross-platform UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise version.