gets() vs fgets() in C and C++


Reading time: 20 minutes | Coding time: 5 minutes

gets() and fgets() are functions in C language to take input of string with spaces in between characters. The problem of gets() is that it suffers from buffer overflow that is it takes more input than it is supposed to take. This problem is solved using fgets().

The problem with the most used standard scanf() is that it cannot take spaces in input for a string. That's why we use gets() and fgets() functions when we take input of a string in buffer for standard input or file.

We will go through the basics of gets() and fgets() one by one before going into the problem of buffer overflow and compare both.

gets()

gets() keeps reading input until newline character or end-of-file is reached. It stores that into a string variable and it is possible that we get buffer overflow error when the buffer for gets() overflows.

Syntax:

gets(str);
  • str: Pointer to a block of memory
  • returns: A string

Example code with gets():

#include <stdio.h>
#define SIZE_OF_BUFF 15 

int main()
{
    char buffer_input[SIZE_OF_BUFF];
    
    gets(buffer_input);
    printf("\nYou entered: %s", buffer_input);
    
    return 0;
}

Let's say our input is,

Hello, learning here is fun!

Output:

You entered: Hello, learning here is fun!

Here, we get the input as it is.

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

Syntax:

fgets( char *str, int n, FILE *stream);

str: Pointer to a block of memory
n: Maximum numbers of characters in input
stream: to specific the input source like file
returns: A string

Example code:

#include <stdio.h> 
#define SIZE_OF_BUFF 15 

int main()
{ 
    char buffer_input[SIZE_OF_BUFF]; 
   
    fgets(buffer_input, SIZE_OF_BUFF, stdin); 
    printf("You entered: %s\n", buffer_input);
    
    return 0; 
} 

Let's say our input is,

Hello, learning here is fun!

Output:

You entered: Hello, learnin

Here, we are not able to read the whole input because the maximum size is limited to 15 from SIZE_OF_BUFF.

Note The fgets() includes the terminating character in the buffer and because of that the string has 14 characters of our input.

What is the problem with gets()?

Writing data past the end of allocated memory can sometimes be detected by the operating system to generate a segmentation fault error that terminates the process.

buff_ovf

Example:

#include <stdio.h>
#define SIZE_OF_USERNAME 8 

int main()
{
    char buffer[SIZE_OF_USERNAME];
    
    gets(buffer);
    printf("\nYour username: %s", buffer);
    
    return 0;
}

Suppose you enter,

Harshiv512

Then, in case of gets() as it does not check our array bounds the value '1' and '2' goes and overwrites some other variable's value.

On the other hand, fgets() is a lot safer than gets() because it checks the bounds of maximum input characters.

Which function can handle buffer overflow issue better than the other one?

fgets()
gets()
depends on input
depends on system
gets() keeps reading input until newline character or end-of-file(EOF) shows up.This can lead to buffer overflow as it doesn't check array bounds of variable. While in case of fgets() it will also stop when maximum limit of input characters is reached.

What is the benefit of using gets() or fgets() over scanf()?

You can take space as input
They are faster
They are thread safe
They are platform independent