该gets
函数首先在C99中弃用,最后在C11中删除.然而,在C库中没有直接替代它.
fgets()
不是替代品,因为它不会剥离最终版本'\n'
,这可能在文件末尾不存在.许多程序员也错了.
有一个单行代码可以删除换行符:buf[strcspn(buf, "\n")] = '\0';
但它不重要,通常需要解释.它也可能效率低下.
这会适得其反.许多初学者仍然使用,gets()
因为他们的老师是蹩脚的或他们的教程已经过时.
微软提出了gets_s()
许多相关的函数,但它并没有默默地截断超长行,这种约束违规的行为并不简单.
BSD和GNU libc都getline
在POSIX中标准化,通过realloc
... 分配或重新分配缓冲区.
教初学者关于这个混乱的最佳方法是什么?
这个问题的本质就是猜测和意见.但我们可以从C99基本原理和C11标准中找到一些信息.
在C99理由,当gets()
被弃用,规定如下理由废除了它:
因为gets不检查缓冲区溢出,所以当它的输入不在程序员的控制之下时,使用它通常是不安全的.这导致一些人质疑它是否应该出现在标准中.委员会认为,在程序员对输入有足够控制的情况下,在特殊情况下,获取是有用和方便的,并且作为长期存在的实践,它需要标准规范.但是,一般来说,首选函数是fgets(参见§7.19.7.2).
我认为gets_s()
不能被视为替代方案.因为gets_s()
是可选的界面.C11实际上建议fgets()
过gets_s()
:
§K.3.5.4.1,C11草案
fgets函数允许正确编写的程序安全地处理输入行太长而无法存储在结果数组中.通常,这要求fgets的调用者注意结果数组中是否存在换行符.考虑使用fgets(以及基于换行符的任何所需处理)而不是gets_s.
因此,fgets()
作为gets()
ISO C中唯一真正的替代品,这就fgets()
等同于gets()
除了如果有缓冲空间它将在换行符中读取.那么值得引入一个新的界面,与长期和广泛使用的(fgets()
)一个相比有一个小的改进吗?国际海事组织,没有.
此外,许多现实世界的应用程序不仅限于ISO C.所以有机会使用扩展和POSIX getline()
等作为替代品.
如果有必要在ISO C中找到编写解决方案,那么fgets()
无论如何都要编写一个包装器很容易,例如my_fgets()
,如果存在,则会删除换行符.
当然,fgets()
向新手教学涉及解释潜在的换行问题.但IMO,并不难理解,有意学习C的人应该能够迅速掌握它.它(找到最后一个角色并替换它的角色"X")甚至可以被认为是初学者的一个好练习.
因此,鉴于上述原因,我认为ISO C中的新功能绝对没有必要作为真正的替代品gets()
.