在if-else语句中“等于”与“不等于”运算符
在C中编写if-else语句时,是否有人会优先使用“等于”运算符而不是“不等于”,这两种情况都可以产生相同的结果?
下面的代码提供了上下文。 因此,如果参数计数等于2,则将从用户检索字符串。 但是,如果获得任何其他参数值,则会显示错误消息。
int main(int argc, string argv[]) { string msg; if (argc == 2) { msg = GetString(); } else { printf("ERROR: Please only enter a single key! \n"); return 1; }
但是,通过将if-else循环的条件更改为“不等于”,并翻转相关的操作,我可以实现与上述完全相同的结果。 见下文:
int main(int argc, string argv[]) { string msg; if (argc != 2) { printf("ERROR: Please only enter a single key! \n"); return 1; } else { msg = GetString(); }
无论如何,因为两者产生相同的结果,是否应该优先使用另一个?
在C ++中有一个技术原因,那就是因为如果你习惯使用==
over !=
,你就不需要重载那么多的运算符。
当您处理函数对象(“仿函数”)时,这很重要。 例如,当您使用标准容器类来存储自己的自定义对象并希望自动对它们进行排序时。 为了使函数对象(例如std :: equal_to)起作用,您的类只需要重载==
运算符。 您不必重载==
和!=
两者。
类似地,其他函数对象要求您只重载<
而不是所有< > == != <= >=
。
一般来说,否定对于人类大脑来说并不容易理解。 特别是如果你有双重否定。 如果顺序在技术上无关紧要,那么在大多数编程语言中自定义首先编写相等性检查。 大多数情况下,它使代码更容易阅读。
但是,与编程和编码风格一样,没有黑色或白色规则。 如果检查的原因是找到错误,那么编写error handling的最可读方式优先于“人类发现更难以阅读的否定”。
考虑一下这个编写得不太好的代码:
if(input == good) { if(format == expected) { do_stuff(); return ok; } else { return error_format; } } else { return error_input; }
想象一下,我们需要为此添加更多的error handling。 相当常见的情况:假设我们正在编写一个解析器或一些具有大量error handling的数据协议解码器。 嵌套大括号的多层次很快就会把代码变成一个完整的混乱。
如果我们从==更改为!=,我们可以摆脱嵌套if语句的需要。
if(input != good) { return error_input; } if(format != expected) { return error_format; } // if we got here then all is well do_stuff(); return ok;
如果我们需要添加更多错误检查,这将更具可读性和扩展性。 因此,通过更改为!=我们使代码更具可读性。
这只是一个编码风格问题。 我讨厌嵌套主逻辑,我会把它写成:
int main(int argc, string argv[]) { if (argc != 2) { printf("ERROR: Please only enter a single key! \n"); return 1; } string msg = GetString(); }
顺便说一句: main
的signatrue应该是int main(int argc, char *argv[])
。
我通常更喜欢“等于”,因为它使代码对人类更具“可读性”。 它使代码更简单。 它将被称为“不错的编码指南”,而不是“规则”,因为它根本不影响运行时(它是我以前公司的编码指南的一部分)。
检查一下:
if ( !isEmpty() )
与你写作相比,你的大脑需要几毫秒才能理解测试的内容:
if ( isEmpty() )
即使它对运行时没有影响,我通常更喜欢“等于”到“不等于”。
变量和函数名称使用相同的参数。 首选isSet
属性/方法。 像if ( !isNotSet() )
一样读取一段代码比if ( isSet() )
更容易,即使它们最终是等价的。
如果你使用的代码是你无法控制的,那么这个代码会提供一个回答否定问题的成员,然后:
if ( isNotSet() )
绝对比开发人员更容易阅读:
if ( !isNotSet() )
正如其他人所说,这是一个风格问题。 没有真正的区别。
但要记住的一件事是尽量保持一致。 如果你有一个块检查value1 == 2
,那么尽量不要让下一个块检查value2 != 4
。 唯一不好的风格是不一致的风格。
这是一个程序设计问题。 作为程序员,您必须确定哪一个程序可以更好地执行,维护,可读性和性能。 此外,这是两个完全不同的陈述。 如果希望你的函数只在argc等于2时调用,而不是调用GetString(); 每当数字不是2时。
如今两种情况之间没有语义差异,因为即使编译器应用的更简单的优化也可能破坏 “ 预期的执行流程 ”。
也许30到40年前,当C编译器的代码生成步骤与编写的代码完全一致时,两种选择之间可能会有一些差异。
今天的实际差异在于语法和风格的清晰度。
所以,在写作的同时
while( *dst++=*src++ );
现在可以生成与之相同的机器代码
for( i=0; src[i] != 0; i++ ) dst[i] = src[i]; dst[i] = '\0';
后者通常更容易阅读,如图所示
if( ! isOK() ) dontDoIt(); else doIt();
并在
if( isOK() ) doIt() else dontDoIt();
但请放心,“清晰度”不是绝对的价值:它不仅取决于读者/评论者的“编程技巧和品味”,还取决于代码本身。
底线:选择你的产品并坚持下去以保持一致性!