本函数可以无限读取,不会判断上限,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值。这个事实导致gets函数只适用于玩具程序,为了避免这种情况,我们可以用fgets(stdin) (fgets实际上可以读取标准输入(即大多数情况下的键盘输入),具体参阅fgets词条)来替换gets()。在V7的手册(1979年)中说明:为了向后兼容,gets删除换行符,gets并不将换行符存入缓冲区。
由于可以无限读取,所以在2011年12月,ANSI 采纳了 ISO/IEC 9899:2011 标准,标准中删除了 gets()函数,使用一个新的更安全的函数gets_s()替带。(摘抄百度百科)
gets_s()是C11标准,由于C11标准还没有完全普及很多编译器还不支持C11标准。我的编译器还不支持C11标准,在这我们就用fgets代替gets。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buf[10];
gets(buf);
printf("%s",buf);
printf("hello\n");
return 0;
}
从上图我们看出gets没有将\n符号写到缓冲区,我们打印的时候没有出现换行
从上图我们看出gets函数输入的数据过多,buffer空间不够,多出的数据将会写入堆栈中造成不可预料的错误。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buf[10];
fgets(buf,10,stdin);// stdin 表示中断输入
printf("%s",buf);
printf("hello\n");
return 0;
}
结果
从上图我们看出,fgets读到\n结束符结束,且当前的数据小于n-1(9),且fgets将\n也写入的缓冲区。
如上图,当输出的数据大于n-1(9)的时候,发现\n符号没有写到缓冲区,且最后一个数据也么有写到缓冲。原来我们对于fgets,必须指定缓存的长度n。此函数一直读到下一个新行符为止,但是不超过n-1个字符,读入的字符被送入缓存。该缓存以null字符结尾。如若该行,包括最后一个新行符的字符数超过n-1,则只返回一个不完整的行,而且缓存总是以null字符结尾。对fgets的下一次调用会继续读该行。