I've been doing a fairly easy program of converting a string of Characters (assuming numbers are entered) to an Integer.
After I was done, I noticed some very peculiar "bugs" that I can't answer, mostly because of my limited knowledge of how the scanf()
, gets()
and fgets()
functions work. (I did read a lot of literature though.)
So without writing too much text, here's the code of the program:
#include <stdio.h> #define MAX 100 int CharToInt(const char *); int main() { char str[MAX]; printf(" Enter some numbers (no spaces): "); gets(str); // fgets(str, sizeof(str), stdin); // scanf("%s", str); printf(" Entered number is: %d\n", CharToInt(str)); return 0; } int CharToInt(const char *s) { int i, result, temp; result = 0; i = 0; while(*(s+i) != '\0') { temp = *(s+i) & 15; result = (temp + result) * 10; i++; } return result / 10; }
So here's the problem I've been having. First, when using gets()
function, the program works perfectly.
Second, when using fgets()
, the result is slightly wrong because apparently fgets()
function reads newline (ASCII value 10) character last which screws up the result.
Third, when using scanf()
function, the result is completely wrong because first character apparently has a -52 ASCII value. For this, I have no explanation.
Now I know that gets()
is discouraged to use, so I would like to know if I can use fgets()
here so it doesn't read (or ignores) newline character. Also, what's the deal with the scanf()
function in this program?
fgets is likely going to be the better choice. You can then use sscanf() to evaluate it. For numeric types, scanf() does not need to do bounds checking. For string types, you can tell scanf() to do boundary checking.
Even though both the functions, gets() and fgets() can be used for reading string inputs. The biggest difference between the two is the fact that the latter allows the user to specify the buffer size. Hence it is highly recommended over the gets() function.
fgets() is a safer version of gets() where you can provide limitation on input size. You can also decide to take input from which stream(e.g. File or standard input).
The scanf() function can read input from keyboard and stores them according to the given format specifier. It reads the input till encountering a whitespace, newline or EOF. On other hand gets() function is used to receive input from the keyboard till it encounters a newline or EOF.
Never use gets
. It offers no protections against a buffer overflow vulnerability (that is, you cannot tell it how big the buffer you pass to it is, so it cannot prevent a user from entering a line larger than the buffer and clobbering memory).
Avoid using scanf
. If not used carefully, it can have the same buffer overflow problems as gets
. Even ignoring that, it has other problems that make it hard to use correctly.
Generally you should use fgets
instead, although it's sometimes inconvenient (you have to strip the newline, you must determine a buffer size ahead of time, and then you must figure out what to do with lines that are too long–do you keep the part you read and discard the excess, discard the whole thing, dynamically grow the buffer and try again, etc.). There are some non-standard functions available that do this dynamic allocation for you (e.g. getline
on POSIX systems, Chuck Falconer's public domain ggets
function). Note that ggets
has gets
-like semantics in that it strips a trailing newline for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With