逗号在C中的while循环中分隔表达式

我以前从未见过这么久的声明。

while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) { .. .. } 

我在网上看到,来自while循环的条件是最右边的[!feof(stdin)]。 然后,使用上面的while语句而不是什么

 while(!feof(stdin)) { printf("> "); fgets(str, 100, stdin); ... ... } 

另外, while语句是一个表达式,1,1是一个有效的表达式吗?

给出的两个循环不具有相同的含义。 通过以这种方式使用逗号运算符,作者能够指定每次迭代应执行的代码,即使从未输入循环本身。 它更像是一个do ... while ()循环,或类似以下内容:

  printf("> "); fgets(str, 100, stdin); while(!feof(stdin)) { .. .. printf("> "); fgets(str, 100, stdin); } 

逗号运算符最好被认为是运算符。 就像+是一个运算符一样, 2 + 3是一个表达式(碰巧导致值为5 ),因此也是一个运算符,因此0, 1是一个有效的表达式(这恰好导致了值为1 ,因为那是最后一个操作数)。

您提议的修改不等同。 这是:

 while (1) { printf("> "); fgets(str, 100, stdin); if (feof(stdin)) { break; } ... ... } 

我建议把工作分解成一个函数:

 int get_input(char* buffer, int size) { printf("> "); fgets(buffer, size, stdin); return !feof(stdin); } while (get_input(str, 100)) { ... ... } 

您的第二个示例与第一个示例的行为不同,并且有一个错误。

如果代码行:

 fgets(str, 100, stdin); 

失败,因为它是在文件末尾的读取,然后将执行块的其余部分。

在第一组代码中, feof()测试发生在导致EOF条件的fgets()之后,因此不会执行while()块。

因为fgets()如果已经命中了EOF(并且没有将任何数据读入缓冲区),则返回NULL,我可能将循环编码为:

 while (fgets(str, 100, stdin)) { printf("> "); // ... } 

这仍然是略有不同的行为(将会少一个“>”打印)。 如果这很重要,我会在循环之前添加一个printf()的额外实例。

一般来说,因为它往往会引起混淆,所以我会避免使用逗号运算符,除非它真正地,真正需要它或不会引起混淆的地方。 例如,它有时以非混淆的方式用于for循环子句,以允许在每次循环迭代时更新多个变量。

 while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) { .. .. } 

逗号一段时间内表现得更像这样:

 int feof_wrapper(FILE * stream) { printf("> "); fgets(str, 100, stream); return feof(stream); } while(!feof_wrapper(stdin)) { .. .. }