使用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 FAQscanf问题有一些详细的解释:

更一般地, 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; }