Alternative to gets?

Mathue24 picture Mathue24 · Apr 3, 2017 · Viewed 7.6k times · Source

I used to use gets but then I heard that it got removed from c11 and that its overall very dangerous. So I did some searching and found out that you can use fgets() to do the same thing.

The problems is that when I do use fgets() it seems to also copy the end of the line aswell, which ends up making an extra unwanted line.

To show you what I mean:

//if I have 
char key[30];
fgets(key, sizeof(key), stdin);

//now if ender for instance: Doggo and do:
printf("The key is:%s|hozaah!\n", key);

//I expect it to print:
The key is:Doggo|hozaah!

//Instead it prints:
The key is:Doggo
|hozaah!

Is there a way to get around this? Or is there another function I can use instead?

Answer

chqrlie picture chqrlie · Apr 3, 2017

There is no standard direct replacement for gets(), but there are many easy ways to get rid of the newline if present:

  • The simplest using strcspn (declared in <string.h>):

    if (fgets(buf, sizeof buf, fp)) {
        buf[strcspn(buf, "\n")] = '\0';
    }
    
  • The classic using strlen:

    if (fgets(buf, sizeof buf, fp)) {
        size_t len = strlen(buf);
        if (len > 0 && buf[len - 1] == '\n')
            buf[--len] = '\0';
    }
    
  • Another classic with strchr:

    if (fgets(buf, sizeof buf, fp)) {
        char *p = strchr(buf, '\n');
        if (p != NULL)
            *p = '\0';
    }
    

An alternative is the POSIX function getline() which might be available on your system:

#include <stdio.h>
ssize_t getline(char **lineptr, size_t *n, FILE *stream);

The buffer is allocated or reallocated with malloc() and its size is updated into *n. The initial values should be lineptr = NULL and n = 0.