Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - scanf() vs gets() vs fgets()

Tags:

c

fgets

gets

scanf

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?

like image 809
Marko Avatar asked Jul 21 '10 17:07

Marko


People also ask

Is fgets better than scanf?

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.

What's the difference between gets () and fgets ()?

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.

Which is better gets or fgets?

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).

What is the difference between scanf () and gets ()?

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.


1 Answers

  • 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.

like image 60
jamesdlin Avatar answered Oct 01 '22 03:10

jamesdlin