Difference to get string with gets and fgets in C

171 Views Asked by At

My question is, what is the difference between these two pieces of code.

1)

#include <stdio.h>
#include <stdlib.h>

#define  SIZE 7

int main()
{
    int strSize;
    char tim[SIZE];
    printf("Enter the time (format xx:yy)= ");
    // for example when I type 14:45
    gets(tim); 
    int i;
    for (i=0; tim[i] != '\0'; i++)
    {
    }
    strSize=i;
    // result of program turns as 5.
    printf("%d", strSize);
    return 0;     
}   
#include <stdio.h>
#include <stdlib.h>

#define  SIZE 7

int main()
{
    int strSize;
    char tim[SIZE];
    printf("Enter the time (format xx:yy)= ");
    // when I type again 14:45
    fgets(tim, SIZE, stdin);
    int i;
    for (i=0; tim[i] != '\0'; i++)
    {
    }
    strSize=i;
    // result turns as 6
    printf("%d", strSize);
    return 0;     
}  

I also use strlen to see if there is really a difference between these two methods. And strlen also give different values.

2

There are 2 best solutions below

0
Andrew On

The TL;DR; answer is that fgets() includes a size parameter (it reads up to n-1 characters) whereas gets() is unconstrained by size.

This makes any system using gets() vulnerable to buffer-overflow, simply by entering too many characters.

As such gets() should NEVER BE USED - to reinforce this, ISO/IEC JTC1/SC22/WG14 (the custodians of the C standard) have removed this function from the standard!

Example (for your tim[7]) and "The cat sat on the mat":

gets() returns "The cat sat on the mat\0", overwriting the next block of memory (or stack) fgets() returns "The ca\0".

0
Lundin On

Differences:

  • fgets is a standard library function, gets is a withdrawn function no longer used. It was flagged obsolescent somewhere in the 1990s (30 years ago!) and finally removed entirely in the year 2011 (13 years ago!). So if your learning material mentions gets, there's a good reason to suspect that said learning material was written by the dinosaurs.
  • fgets can read from any stream/file, gets can only read from stdin.
  • fgets gives the opportunity to set a maximum size before it stops reading.
  • fgets stops reading upon encountering new line \n and then stores that new line character in the read string. Which can explain differences in string length.
  • gets is highly dysfunctional since it has no maximum limit and therefore prone to buffer overruns. fgets is only somewhat dysfunctional since it on one hand it has a maximum limit (good) but it returns no information of how many characters that were actually read (bad), like any half-decently designed function does. Better functions surely exist for your specific target, but those functions won't be portable.

Best practice is to avoid the whole of stdio.h if possible.