Categories
c fgets gcc newline string

Removing trailing newline character from fgets() input

325

I am trying to get some data from the user and send it to another function in gcc. The code is something like this.

printf("Enter your Name: ");
if (!(fgets(Name, sizeof Name, stdin) != NULL)) {
    fprintf(stderr, "Error reading Name.\n");
    exit(1);
}

However, I find that it has a newline \n character in the end. So if I enter John it ends up sending John\n. How do I remove that \n and send a proper string.

4

  • 26

    if (!fgets(Name, sizeof Name, stdin)) (at the very least don’t use two negations, ! and !=)

    – Roger Pate

    Apr 22, 2010 at 20:05

  • 7

    @Roger Pate “don’t use two negations” –> hmmm, if we dig deep “don’t” and “negation” are both negations. ;-). Perhaps “Use if (fgets(Name, sizeof Name, stdin)) {.

    Aug 24, 2016 at 14:53


  • 3

    @chux, I am sure you meant if (fgets(Name, sizeof Name, stdin) == NULL ) {

    – R Sahu

    Apr 5, 2018 at 18:50

  • @RSahu True: pesky !:

    Apr 5, 2018 at 19:30

221

The elegant way:

Name[strcspn(Name, "\n")] = 0;

The slightly ugly way:

char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
    *pos="\0";
else
    /* input too long for buffer, flag error */

The slightly strange way:

strtok(Name, "\n");

Note that the strtok function doesn’t work as expected if the user enters an empty string (i.e. presses only Enter). It leaves the \n character intact.

There are others as well, of course.

5

  • 7

    Any C runtime library that is thread aware (which is to say, most any that target a multi-threaded platform), strtok() will be thread safe (it will use thread local storage for the ‘inter-call’ state). That said, it’s still generally better to use the non-standard (but common enough) strtok_r() variant.

    Apr 22, 2010 at 21:36

  • 2

    See my answer for completely thread-safe and reentrant variant, similar to your strtok approach (and it works with empty inputs). In fact, a good way to implement strtok is to use strcspn and strspn.

    – Tim Čas

    Feb 11, 2015 at 19:09


  • 3

    It’s important to handle the else case if you are in an environment where there is a risk of over-long lines. Silently truncating input can cause very damaging bugs.

    Jan 8, 2017 at 18:52

  • 3

    If you like one-liners and are using glibc, try *strchrnul(Name, '\n') = '\0';.

    – twobit

    Aug 17, 2017 at 8:55

  • 1

    When strchr(Name, '\n') == NULL, then aside from “input too long for buffer, flag error”, other possibilities exist: Last text in stdin did not end with a '\n' or a rare embedded null character was read.

    Dec 6, 2017 at 22:36

221

The elegant way:

Name[strcspn(Name, "\n")] = 0;

The slightly ugly way:

char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
    *pos="\0";
else
    /* input too long for buffer, flag error */

The slightly strange way:

strtok(Name, "\n");

Note that the strtok function doesn’t work as expected if the user enters an empty string (i.e. presses only Enter). It leaves the \n character intact.

There are others as well, of course.

5

  • 7

    Any C runtime library that is thread aware (which is to say, most any that target a multi-threaded platform), strtok() will be thread safe (it will use thread local storage for the ‘inter-call’ state). That said, it’s still generally better to use the non-standard (but common enough) strtok_r() variant.

    Apr 22, 2010 at 21:36

  • 2

    See my answer for completely thread-safe and reentrant variant, similar to your strtok approach (and it works with empty inputs). In fact, a good way to implement strtok is to use strcspn and strspn.

    – Tim Čas

    Feb 11, 2015 at 19:09


  • 3

    It’s important to handle the else case if you are in an environment where there is a risk of over-long lines. Silently truncating input can cause very damaging bugs.

    Jan 8, 2017 at 18:52

  • 3

    If you like one-liners and are using glibc, try *strchrnul(Name, '\n') = '\0';.

    – twobit

    Aug 17, 2017 at 8:55

  • 1

    When strchr(Name, '\n') == NULL, then aside from “input too long for buffer, flag error”, other possibilities exist: Last text in stdin did not end with a '\n' or a rare embedded null character was read.

    Dec 6, 2017 at 22:36

86

size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n') 
    name[ln] = '\0';

10

  • 9

    Will probably throw exception if the string is empty, won’t it? Like index out of range.

    May 31, 2013 at 3:26


  • 2

    @EdwardOlamisan, the string won’t ever be empty however.

    Jul 14, 2013 at 23:27

  • 6

    @James Morris In unusual cases fgets(buf, size, ....) –> strlen(buf) == 0. 1) fgets() reads as the first char a '\0'. 2) size == 1 3) fgets() returns NULL then buf contents could be anything. (OP’s code does test for NULL though) Suggest: size_t ln = strlen(name); if (ln > 0 && name[ln-1] == '\n') name[--ln] = '\0';

    Jul 2, 2014 at 14:00


  • 2

    What if the string is empty? ln would be -1, save for the fact size_t is unsigned, thus writing to random memory. I think you want to use ssize_t and check ln is >0.

    – abligh

    Mar 16, 2015 at 22:38

  • 3

    @legends2k: A search for a compile-time value (especially a zero value as in strlen) can be implemented much more efficiently than a plain char-by-char search. For which reason I’d consider this solution better than a strchr or strcspn based ones.

    Mar 29, 2016 at 18:28