使用scanf()读取一行不好?
scanf(" %[^\n]",line);
我的一个朋友建议使用fgets()
读取一行作为输入比使用上面的语句中的scanf()
更好。 他有道理吗?
char * fgets ( char * str, int num, FILE * stream );
使用是安全的,因为它避免了缓冲区溢出问题,它只扫描num-1
个char。
从流中读取字符并将它们作为C字符串存储到str中,直到读取(num-1)个字符或者到达换行符或文件结尾,以先发生者为准。
这里的第二个参数num
是要复制到str的最大字符数(包括终止空字符)。
例如,假设在您的代码中,字符串数组的容量只有5
字符长,如下所示。
char str[5]; fgets (str, 5, fp); //5 =you have provision to avoid buffer overrun
使用上面的代码,如果来自fp
输入超过4
字符, fgets()
将只读取前4
字符然后追加\0
( ,并丢弃其他额外的输入字符,只在str[]
存储5个字符 )。
而scanf(" %[^\n]",str);
将读取,直到\n
未找到,如果输入字符串较长,则4
字符scanf()
将导致缓冲区溢出 (因为scanf
将尝试访问str[]
超出最大索引4
内存。
C FAQ对scanf
的问题有一些详细的解释:
更一般地,
scanf
被设计用于相对结构化的格式化输入(其名称实际上源自“扫描格式化”)。 如果你注意,它会告诉你它是成功还是失败,但它只能告诉你它大概失败的地方,而不是告诉你如何或为什么。 您几乎没有机会进行任何错误恢复。
看详情。
fgets
将比这个scanf
更好。 如OP中给出的scanf
可能存在以下问题
1)@Grijesh建议的缓冲区溢出
2)之后可能的next scanf
将无效,因为换行符保留在输入流中。(如果你错过了一个空格)
简单地说:是的, fgets
是一个更好的选择。
我看了你的scanf
格式说明符,我很神秘。 准确理解它的作用需要一些时间阅读man
页。
此外,您的scanf
代码容易受到缓冲区溢出的影响。
保持简单,您将降低维护成本,避免很难找到错误!
是的fgets是从标准输入读取一行的更好,更安全的方法。
此外,代码中的可读性更高。 查看您提供的scanf语句。
看到它的任何第二个人都会彻底混淆。 但是对于fgets来说会有更多的可重玩性,而且很容易理解。
不要使用fgets(…)而是使用以下代码段:
char _x[7000]; char* y; while ( ! feof (_f) ) { fscanf(_f,"%[^\n]\n",_x); y=x; }