标准库函数fgets()
有两个缺点:
int
我创建了一个类似于fgets()
的简单函数,不包括上面提到的缺点,试图提高我的一个程序的效率,该程序获取文本文件的行并终止char
使用函数strcspn()
在。换行符处的数组。
但它真的更有效吗?有没有理由为什么标准库函数优于以下天真的实现?
#include <stdio.h>
char *my_fgets(char *buf, size_t maxCount, FILE *stream);
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "Usage: %s [filename]", argv[0]);
}
FILE *fp;
fp = fopen(argv[1], "r");
if (!fp)
{
perror(argv[1]);
return 1;
}
char buf[256];
/*while (fgets(buf, sizeof(buf), fp))
{
buf[strcspn(buf, "\n")] = '\0';
// . . .
puts(buf);
}*/
while (my_fgets(buf, sizeof(buf) - 1, fp))
{
puts(buf);
}
return 0;
}
char *my_fgets(char *buf,
size_t maxCount, FILE *stream)
{
int ch;
size_t n = 0;
while ((ch = fgetc(stream)) != EOF)
{
if (ch == '\n' || n == maxCount)
{
break;
}
else
{
buf[n++] = ch;
}
}
if (n == 0 && ch == EOF)
{
return NULL;
}
buf[n] = '\0';
return buf;
}
答案 0 :(得分:1)
<强>性能强>
您使用fgetc()
逐个获取字符可确保my_fgets()
无法与明智优化的解决方案竞争。要获得良好的性能,您需要通过read()
系统调用将一些字符读入缓冲区,然后直接从该缓冲区中使用数据。对每个字节执行一个完整的函数调用是 lot 的开销。
<强>安全强>
fgets()
不安全用于一般用法:它会拆分长行。这种情况通常是未预料到的(例如,您的示例代码也没有处理此问题),并且当向您的程序提供非常长的输入行时,通常会导致错误的行为。尾随\n
的存在实际上可以帮助您处理该问题。 如果您需要安全软件,则必须在使用fgets()
时明确处理缓冲区不足的情况。没有这样做,你肯定有一个等待罢工的bug。您的实现甚至没有尝试解决此问题。
这就是为什么我强烈建议使用可以处理任何长度的输入行的输入函数。在符合POSIX的系统上getline()
:此函数为您分配一个足够大的缓冲区,因此您的唯一限制是可用RAM。如果您的平台上没有getline()
,我建议重新实现其功能,而不是fgets()
的“更好”版本。
答案 1 :(得分:0)
真的更有效率吗?
不 - 不是更多在效率上有效。 my_fgets()
充其量只能提高效率,但即使这样也不太可能,因为fgets()
可以访问精心设计的汇编代码而my_fgets()
没有@Peter。
是的,如果功能目标是获得一行用户输入并not save the '\n'
,那么它可能具有编码效率,因为这比编码要少于fgets() ... code_to_rid_\n()
然而效率是次要的功能。
my_fgets()
对input errors造成轻微麻烦。
my_fgets()
@melpomene 不同, fgets()
可以删除字符
size_t maxCount
的角色与fgets()
的类似参数相差1。
很好的尝试,因为标准库fgets()
有各种各样的弱点,迫使编码人员尝试更好的低级输入行功能。