C - scanf() vs gets() vs fgets()
c, fgets, gets, scanf
Solution
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.
Problem
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?