Does the alternative get?

I used to use, but then I heard that it retired from c11 and that its general is very dangerous. So I did some searching and found out that you can use fgets () to do the same.

The problem is that when I use fgets (), it also copies the end of the line, resulting in an extra, unnecessary 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 that I can use instead?

+3


source to share


2 answers


There is no standard direct replacement for gets()

, but there are many easy ways to get rid of the newline if there is one:

  • Simplest usage strcspn

    (declared in <string.h>

    ):

    if (fgets(buf, sizeof buf, fp)) {
        buf[strcspn(buf, "\n")] = '\0';
    }
    
          

  • Classics 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 may 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 to *n

. The initial values ​​must be lineptr = NULL

and n = 0

.

+4


source


The answer is that it fgets

reads as many characters as fits into the buffer, including the null terminator, but only until the end of the file or newline, and it will store the newline in a string as well:man 3 fgets

So, if you enter input on the terminal, the newline will also be passed to standard input and read with fgets

. This is different from the old one gets

, which replaces the new string with a null byte.

So if you are reading lines and you don't want a newline to appear, disable it. Unfortunately, it fgets

doesn't tell you how many characters were read, so you have to scan the string again to solve it:



char* p = fgets(key, sizeof(key), stdin);

if (!p) { /* error */ }

size_t n = strlen(key);

if (n > 0 && key[n - 1] == '\n') {
  key[n - 1] = '\0';
} else {
  /* buffer too short or EOF reached without newline */
}

printf("The line was: '%s'\n", key);

      

It might be worth considering alternatives: if you only need one input, don't type a newline in the first place. If you need a lot of lines, use fread

a fixed size buffer and scan new lines yourself.

+1


source







All Articles