Hi everyone,
gets
is an unsafe C function that reads from standard input. It’s unsafe because once you call gets
, you have no control over how much stuff gets
reads. If someone provides too much input, gets
keeps reading and reading, clobbering whatever happens to get in its way.
In the Algorithmic Thinking book, I used the C gets
function a few times.
Take a look at Listing 2-19 in the book, and you’ll see that I used gets
to read a string. In this context, it’s safe, because we know the maximum number of characters that could be provided in a test case. It was also an easy way for me to read a string and not distract from our main task.
But gets
is removed from C as of C11, so maybe your compiler will give a warning or outright reject programs that use gets
. Or maybe you just don’t want to use it, and want to know what to use instead.
gets
We can replace calls of gets
with fgets
. We have to be a little careful, as you’ll see now.
Here’s listing 2-19 again, replacing gets
by fgets
:
To call fgets
instead of gets
, we need three arguments instead of one: the string to read into, the size of that string, and the file to read from (9).
One annoyance for us here is that fgets
includes the newline in the string that it produces. (gets
doesn’t do that; it throws the newline away without storing it.) To get rid of that newline, I find the length of what fgets
produced and replace the final character (the newline) with a null character (10).
The second argument to fgets
, the SIZE + 2
here, is what tells fgets
the size of the array that it’s reading into.
Here, we’re saying that fgets
is reading into an array that has room for SIZE + 2
characters. fgets
reads at most one character less than this, so that it’s guaranteed to have room for the null character.
So, here, fgets
will read at most SIZE + 1
characters. We’re safe: the SIZE
covers the string from the test case, and the + 1
covers the newline that it will read.
What if the input ends without a newline? What if fgets
fails to read anything at all? These are concerns for code in the wild, of course, but as in the rest of the book I’ve gone light on error-checking so as to not distract from the data structure/algorithm content.
There are a few different ways to get rid of the newline that fgets
leaves at the end of the string that it produces. You can check out some of that fgets
newline discussion on Stack Overflow.
One of the coolest solutions provided there goes like this:
It’s clear that this code somehow finds the newline and replaces it by the null character. But how? The secret is the strcspn
C function, which I hadn’t known about prior to reading about it here. It takes two arguments: the first is a string to search, and the second is a string of characters to search for. It returns the number of characters that it finds in the first string before it finds one of the characters from the second string. Here, we’re using it to tell us how many characters are found in line
before the newline. That gives us the index of the newline character, which we replace by the null character. (For example, imagine that line
consists of hello\n
. Then, when searching for the \n
, strcspn
would return 5. Index 5 is where the newline is, which is exactly what we need to replace by the null character.)
And what if there is no newline at all in line
? No problem for strcspn
: in this case, strcspn
returns the length of the string, so we end up just replacing the null character with another null character.
Thank you all for your engagement and support of my work. There are a zillion ways that you could be spending your time online, a zillion things you could be reading. I appreciate you making time for what I have to say, and in return I hope it has been well worth it in terms of your learning.
Written on December 23rd , 2020 by Daniel Zingaro