14

If the code is

scanf("%s\n",message)  

vs

gets(message)

what's the difference?It seems that both of them get input to message.

Shihe Zhang
  • 2,641
  • 5
  • 36
  • 57

10 Answers10

23

The basic difference [in reference to your particular scenario],

  • scanf() ends taking input upon encountering a whitespace, newline or EOF

  • gets() considers a whitespace as a part of the input string and ends the input upon encountering newline or EOF.

However, to avoid buffer overflow errors and to avoid security risks, its safer to use fgets().

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Note: `scanf("%s\n",message)` does _not_ end taking input upon encountering a whitespace, newline. `"%s\n"` causes `scanf()` to 1) scan in all white-space input and discard them 2) scan in all non-white-space input and save them to `message`, finally appending `'\0'` 3) scan in all white-space input and discard them until encountering a non-white-space `char`, which is put back into `stdin` for the next IO call. – chux - Reinstate Monica Oct 29 '14 at 19:22
  • @chux Thank you sir for the clarification. In my answer, by saying `taking input` i meant storing non-whitespaces into the supplied buffer `message`. However, your comment makes this answer complete. – Sourav Ghosh Oct 29 '14 at 19:29
  • Dear Downvoter, instead of downvote-and-run policy, if you care to leave a comment, it will help me to improve this answer (and next ones). Thank you. – Sourav Ghosh Nov 02 '14 at 12:24
7

Disambiguation: In the following context I'd consider "safe" if not leading to trouble when correctly used. And "unsafe" if the "unsafetyness" cannot be maneuvered around.

scanf("%s\n",message)

vs

gets(message)

What's the difference?

In terms of safety there is no difference, both read in from Standard Input and might very well overflow message, if the user enters more data then messageprovides memory for.

Whereas scanf() allows you to be used safely by specifying the maximum amount of data to be scanned in:

char message[42];

...

scanf("%41s", message); /* Only read in one few then the buffer (messega here) 
                           provides as one byte is necessary to store the 
                           C-"string"'s 0-terminator. */

With gets() it is not possible to specify the maximum number of characters be read in, that's why the latter shall not be used!

alk
  • 69,737
  • 10
  • 105
  • 255
  • scanf() is less safe than gets, because of the reduced type safety. – Lundin Oct 28 '14 at 07:27
  • Well yes, but to start argueing on this, one might better define "*safe*" before. @Lundin – alk Oct 28 '14 at 07:30
  • Safe as in "known to cause bugs, poorly-defined behavior and program crashes"? I can't think of many less safe functions in the C language. – Lundin Oct 28 '14 at 07:37
  • @Lundin: If having defined "*unsafe*" like you just did in your comment I fully agree, `scanf()` is a blxxdy, dxxm, fxcking unsafe sxcker. I nearly ever and always refused playing with it. ... – alk Oct 28 '14 at 07:40
5

The main difference is that gets reads until EOF or \n, while scanf("%s") reads until any whitespace has been encountered. scanf also provides more formatting options, but at the same time it has worse type safety than gets.

Another big difference is that scanf is a standard C function, while gets has been removed from the language, since it was both superfluous and dangerous: there was no protection against buffer overruns. The very same security flaw exists with scanf however, so neither of those two functions should be used in production code.

You should always use fgets, the C standard itself even recommends this, see C11 K.3.5.4.1

Recommended practice

6 The fgets function allows properly-written programs to safely process input lines too long to store in the result array. In general this requires that callers of fgets pay attention to the presence or absence of a new-line character in the result array. Consider using fgets (along with any needed processing based on new-line characters) instead of gets_s.

(emphasis mine)

Lundin
  • 195,001
  • 40
  • 254
  • 396
4

gets - Reads characters from stdin and stores them as a string.

scanf - Reads data from stdin and stores them according to the format specified int the scanf statement like %d, %f, %s, etc.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Shwetha
  • 150
  • 7
4

There are several. One is that gets() will only get character string data. Another is that gets() will get only one variable at a time. scanf() on the other hand is a much, much more flexible tool. It can read multiple items of different data types.

In the particular example you have picked, there is not much of a difference.

Dinesh
  • 4,437
  • 5
  • 40
  • 77
3

gets:->

gets() reads a line from stdin into the buffer pointed to by s until either a terminating newline or EOF, which it replaces with a null byte ('\0').

BUGS:->

Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.

scanf:->

The scanf() function reads input from the standard input stream stdin;

BUG:->

Some times scanf makes boundary problems when deals with array and string concepts.

Community
  • 1
  • 1
Anbu.Sankar
  • 1,326
  • 8
  • 15
2

In case of scanf you need that format mentioned, unlike in gets. So in gets you enter charecters, strings, numbers and spaces.

In case of scanf , you input ends as soon as a white-space is encountered.

But then in your example you are using '%s' so, neither gets() nor scanf() that the strings are valid pointers to arrays of sufficient length to hold the characters you are sending to them. Hence can easily cause an buffer overflow.

Tip: use fgets() , but that all depends on the use case

argentum47
  • 2,385
  • 1
  • 18
  • 20
0

The concept that scanf does not take white space is completely wrong. If you use this part of code it will take white white space also :

#include<stdio.h>
int main()
{
char name[25];  
printf("Enter your name :\n");
scanf("%[^\n]s",name);
printf("%s",name);
return 0;
}

Where the use of new line will only stop taking input. That means if you press enter only then it will stop taking inputs.

So, there is basically no difference between scanf and gets functions. It is just a tricky way of implementation.

0

scanf() is much more flexible tool while gets() only gets one variable at a time.

Robert Columbia
  • 6,313
  • 15
  • 32
  • 40
-1

gets() is unsafe, for example: char str[1]; gets(str) if you input more then the length, it will end with SIGSEGV. if only can use gets, use malloc as the base variable.

  • As others mentioned, yes, it's unsafe to use `gets()`, but: *if you input more then the length* err, what? How would you ever input the length of a "string" in C? You seem to be mixing up something here. – alk Mar 11 '19 at 06:50