我曾经使用过gets,但后来我听说它已从c11中删除了,而且它的整体非常危险。 所以我做了一些搜索,发现你可以使用fgets()做同样的事情。
问题在于,当我使用fgets()时,它似乎也复制了行的末尾,这最终会产生额外的不需要的行。
告诉你我的意思:
//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!
有没有办法解决这个问题?或者我可以使用另一种功能吗?
答案 0 :(得分:4)
gets()
没有标准的直接替换,但有很多简单的方法可以摆脱换行符:
最简单的使用strcspn
(在<string.h>
中声明):
if (fgets(buf, sizeof buf, fp)) {
buf[strcspn(buf, "\n")] = '\0';
}
使用strlen
的经典:
if (fgets(buf, sizeof buf, fp)) {
size_t len = strlen(buf);
if (len > 0 && buf[len - 1] == '\n')
buf[--len] = '\0';
}
strchr
的另一个经典之作:
if (fgets(buf, sizeof buf, fp)) {
char *p = strchr(buf, '\n');
if (p != NULL)
*p = '\0';
}
另一种选择是POSIX函数getline()
,它可能在您的系统上可用:
#include <stdio.h>
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
使用malloc()
分配或重新分配缓冲区,其大小更新为*n
。初始值应为lineptr = NULL
和n = 0
。
答案 1 :(得分:1)
答案在于fgets
读取适合缓冲区的字符数,包括空终止符,但只能到文件末尾或换行符,并且存储换行符在字符串中:man 3 fgets
因此,如果您在终端上输入输入,新行也会传输到标准输入,并由fgets
读取。这与旧gets
不同,后者用空字节替换换行符。
因此,如果您正在阅读行并且不想要潜在的换行符,请将其删除。不幸的是,fgets
并没有告诉你读了多少个字符,所以你必须再次扫描字符串才能解决它:
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);
可能值得考虑替代方案:如果您只需要一个输入,请不要首先输入换行符。如果您需要大量的行,请将fread
用于固定大小的缓冲区并自行扫描换行符。