学习 C++ 并做一个基本的三角形练习。
如果我做的一切都正确,任何人都可以检查我的代码并解释为什么我会收到这个错误:建议在“||”中的“&&”周围加上括号
#include <iostream>
int main()
{
// enter 3 numbers for sides of triangle
int a, b, c;
std::cout << "Input three numbers: " << std::endl;
std::cin >> a;
std::cin >> b;
std::cin >> c;
// check what kind of traingle it is and output result
if(a == b && b == c){
std::cout << "You have an equalateral triangle." << std::endl;
}else if(a == b && b !=c || a!=b && b==c || a==c && b!=c){
std::cout << "You have an iso triangle." << std::endl;
}else{
std::cout << "You have an scalene triangle." << std::endl;
}
}
回答1
您收到的错误消息是 Clang 可以生成的诊断信息
如果这些显示为错误,您可能在编译器选项中启用了 -Werror
。您可以删除该标志以停止将警告升级为错误。或者,如果您不希望它针对(说实话)非常虚假的诊断发出警告(升级为错误),您可以将 -Wno-logical-op-parentheses
添加到编译器选项中。
至于为什么首先生成此诊断: &&
和 ||
之间的运算符优先级并不总是很明显,尤其是对于新程序员而言,Clang 建议您明确指定运算符优先级以确保您'写的是你想要的。所以它要求你像这样重写这些行:
if(a == b && b == c) {
std::cout << "You have an equalateral triangle." << std::endl;
} else if((a == b && b != c) || (a != b && b == c) || (a == c && b != c)) {
std::cout << "You have an iso triangle." << std::endl;
} else {
std::cout << "You have an scalene triangle." << std::endl;
}
额外的括号使警告消失。
据我所知,您的代码中实际上没有逻辑错误(布尔逻辑的行为与您期望的一样),实际上,如果您将此代码发送到不同的编译器,它们会毫无问题地编译它。所以这实际上只是 Clang 的一个特殊怪癖。
回答2
编译器建议您使用括号使第二个 if
语句更清晰/更易于解析。
特别是,您应该使用括号对 ||
语句中的 &&
语句进行分组。也就是改变这段代码
(a == b && b !=c || a != b && b == c || a == c && b != c)
至
((a == b && b != c) || (a != b && b == c) || (a == c && b != c))
值得注意的是,这是一个“风格错误”;第一种形式并不是严格不正确的代码(实际上,在没有编译器标志的情况下,我能够很好地编译和运行它),但是以第二种方式编写它是一种很好的做法。
如果您将 -Wall
标志传递给您的编译器(或者更具体地说,在这种情况下是 -Wlogical-op-parentheses
标志),这将显示为警告。传递 -Werror
会将这些警告更改为错误,这里似乎就是这种情况。最好同时使用 -Wall
和 -Werror
,因为编译器会指出类似这样的潜在清晰度问题,并强制您在继续编译之前修复它们。
回答3
这肯定会产生分歧,但我认为在您尝试将任何代码推送到生产环境之前,您需要充分了解 C++ 语法。
事实上,||
的优先级低于 &&
。这应该是你的第二天性,就像二元运算符 +
和 *
的优先级应该是一样。用括号强调显而易见的东西会引入噪音并使您的代码更难阅读。我建议您关闭该特定警告,然后按。
请注意,在您的特定情况下,尽管第二个条件简化为
else if (a == b || a == c || b == c)
因为你已经消除了等边的可能性。同样,一些软件公司坚持认为 if
语句都是互斥的,因为它们可以在不破坏代码的情况下任意重新排序。恐怕还有更多的意见。