我正在查看Beej的IPC指南,一行代码引起了我的注意。
在特定页面中,speak.c
中的while循环有两个条件来检查while (gets(s), !feof(stdin))
。
所以我的问题是,在我看到大部分时间只测试一种情况时,这是怎么可能的。
PS:我对这些并不陌生。将不胜感激任何帮助。谢谢!答案 0 :(得分:6)
摘录
while (gets(s), !feof(stdin))
使用逗号运算符,首先执行gets(s)
,然后测试!feof(stdin)
,这是条件的结果。
顺便说一句不要使用获取,这是非常不安全的。警惕使用它的消息来源,它们可能不是学习该语言的好资源。
代码
while(gets(s), !feof(stdin)) {
/* loop body */
}
相当于
gets(s);
while(!feof(stdin)) {
/* loop body */
gets(s);
}
更简洁,因为它避免了在循环之前和循环体中重复gets
。
答案 1 :(得分:3)
有几个人已经指出了一些问题。我当然同意使用gets
(根本没有)是一个糟糕的想法。
我认为值得一提的是另外一个细节:因为它使用feof(file)
作为退出循环的条件,如果在文件结束之前遇到错误,它也会/可能会出错。当发生错误时,将设置错误标志但是(通常)EOF标志将不会 - 并且由于您不能再从文件读取(由于错误)它也不会,所以这将进入一个无限循环。
正确的工作方式是使用fgets
,并检查其返回值:
while (fgets(s, length_of_s, stdin))
process(s);
在从文件读取时测试fgets
成功,因此它将退出文件的任一端或错误的循环。
另一个小细节:当fgets
读取字符串时,通常保留行末尾的新行(其中gets
将其抛弃)。您可能需要添加更多代码才能将其删除(如果不存在换行符,可能会处理比您分配的缓冲区更长的行)。
答案 2 :(得分:2)
此测试使用的是comma operator,并且已被用作使用gets(s)
获取下一行文本并使用!feof(stdin)
测试文件结尾的方法。
答案 3 :(得分:2)
此语法不评估两个表达式。它首先执行gets(s)
,然后评估可能被!feof(stdin)
函数调用修改的gets()
。
这不是一个非常好的方法,因为它都使用gets()
,这不是一个安全的功能,而且对于初学者来说是非常不安的(因此你的问题)。
答案 4 :(得分:1)
我同意@DanielFischer和@trojanfoe,逗号运营商。
另外需要注意的一点是,您通常不想使用它,尤其是在上述问题的上下文中。作为一名专业编码员,它会使您的代码更易于阅读,并且对其他开发人员来说更加混乱,因此有一次攻击。
另外,如果您使用静态代码分析工具(如LINT(http://en.wikipedia.org/wiki/PC-Lint)),它会向您发出大量警告,因此还有另一个问题如果你想要专业的质量代码。
最后,正如@DanielFischer所说,gets()根本不安全,并且负责许多漏洞和溢出错误。请改用fgets()函数,因为它允许您设置要读取的字符数的上限。
http://www.cplusplus.com/reference/clibrary/cstdio/fgets/
你不会后悔习惯总是使用fgets()代替获取,特别是如果这是生产代码。
您也可以考虑查看安全字符串函数。
http://linux.die.net/man/3/snprintf
它们不是标准ANSI / C99 C的一部分,但如果您只是为某个平台开发,它们会阻止您崩溃程序或打开安全漏洞。
祝你好运!