让我们先解决这个问题:我完全明白为什么 gets
函数已被弃用以及如何在不受控制的环境中恶意使用它。我确信该功能可以在我的设置中安全使用。
“替代”功能不适用于我的用例。我正在编写的软件对性能非常敏感,所以使用 fgets
然后使用一个完整的字符串循环(明确地或通过像 strlen
这样的辅助函数)来摆脱字符串末尾的换行符根本行不通。写我自己的 gets
函数使用 getchar
或类似的东西也可能比 native 实现效率低得多(更不用说非常容易出错)。
Visual Studio 编译器有一个 gets_s
符合我需要的函数,但是在 gcc 中找不到这个函数。是否有任何编译器选项/标志可以恢复此功能和/或它实现的某些替代功能?
先感谢您。
最佳答案
实现自己的保险箱 gets()
函数使用 getchar_unlocked()
很容易而且相当有效。
如果您的应用程序对性能如此敏感,您会认为 fgets()
并且删除扫描将成为瓶颈,您可能根本不应该使用流函数并使用较低级别的 read()
系统调用或内存映射文件。
在任何情况下,您都应该仔细地对您的应用程序进行基准测试,并使用分析工具来确定时间花在哪里。
这是一个简单的实现,它返回行长度但将行截断为适合目标数组 buf
的任何值长度n
并返回 EOF
在文件末尾:
int my_gets(char *buf, size_t n) {
int c;
size_t i = 0;
while ((c = getchar_unlocked()) != EOF && c != '\n') {
if (i < n) {
buf[i] = c;
}
i++;
}
if (i < n) {
buf[i] = '\0';
} else
if (n > 0) {
buf[n - 1] = '\0';
}
if (c == EOF && i == 0) {
return EOF;
} else {
return (int)i;
}
}
如果您的目标是逐行解析日志文件,并且只有此函数从 stdin
中读取,您可以使用 read
实现自定义缓冲方案或 fread
在 gets()
的自定义版本中.这将是便携且快速的,但不是线程安全的,也不是优雅的。这是一个比
fgets()
快 20% 的示例在我的系统上:/* read a line from stdin
strip extra characters and the newline
return the number of characters before the newline, possibly >= n
return EOF at end of file
*/
static char gets_buffer[65536];
static size_t gets_pos, gets_end;
int my_fast_gets(char *buf, size_t n) {
size_t pos = 0;
for (;;) {
char *p = gets_buffer + gets_pos;
size_t len = gets_end - gets_pos;
char *q = memchr(p, '\n', len);
if (q != NULL) {
len = q - p;
}
if (pos + len < n) {
memcpy(buf + pos, p, len);
buf[pos + len] = '\0';
} else
if (pos < n) {
memcpy(buf + pos, p, n - pos - 1);
buf[n - 1] = '\0';
}
pos += len;
gets_pos += len;
if (q != NULL) {
gets_pos += 1;
return (int)pos;
}
gets_pos = 0;
gets_end = fread(gets_buffer, 1, sizeof gets_buffer, stdin);
if (gets_end == 0) {
return pos == 0 ? EOF : (int)pos;
}
}
}
关于c - 是否有任何 gcc 编译器选项或类似的东西来绕过过时的gets 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67664505/