Reputation: 178
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?
Upvotes: 4
Views: 13722
Reputation: 144715
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
.
Upvotes: 4
Reputation: 477030
The answer lies in the fact that fgets
reads as many characters as fit into the buffer, including a null terminator, but only up to end of file or a newline, and it will store the newline in the string, too: man 3 fgets
So if you enter input on the terminal, the newline is transmitted to the standard input, too, and read by fgets
. This is different from the old gets
, which replaces the newline with a null byte.
So if you're reading lines and don't want the potential newline, strip it out. Unfortunately, fgets
does not tell you how many characters were read, so you have to scan the string again to work it out:
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 may be worth considering alternatives: If you only need one input, don't input the newline in the first place. If you need lots of lines, use fread
into a fixed-size buffer and scan for newlines yourself.
Upvotes: 1