我正在尝试有效减去哪些条件导致if语句被程序忽略而不使用if语句序列来单独验证每个变量的相对完整性。
这可能吗?
import collections
class BinarySearchTree:
Node = collections.namedtuple('Node', ['left', 'right', 'value'])
@staticmethod
def contains(self,root, value):
if (root is None):
return None
elif (root.value==value):
return root
elif (root.value < value):
self.contains(root.right,value)
else:
self.contains(root.left,value)
n1 = BinarySearchTree.Node(value=1, left=None, right=None)
n3 = BinarySearchTree.Node(value=3, left=None, right=None)
n2 = BinarySearchTree.Node(value=2, left=n1, right=n3)
print(BinarySearchTree.contains(n2,3))
答案 0 :(得分:1)
您可以在if
中的每个条件之间引入一个计数器作为“条件”,以查看运算符&&
的短路评估何时禁止执行后一条件:
int nrOfConditionFailing = 1;
if(x == 0 &&
nrOfConditionFailing++ && y == 1 &&
nrOfConditionFailing++ && z == 2) {
state = true;
}
if (!state) {
cout << "failed due to condition nr " << nrOfConditionFailing << endl;
}
如果要检查所有条件,则不能在单个if语句中执行此操作;操作员&amp;&amp; amp;的短路评估如果前一个条件之一评估为假,则会阻止后一个条件被检查/评估。
但是,你可以做一个检查,作为一个表达式,在每个未满足的条件下标记一个unsigned int:
int x = 1;
int y = 1;
int z = 3;
unsigned int c1 = !(x == 0);
unsigned int c2 = !(y == 1);
unsigned int c3 = !(z == 2);
unsigned int failures =
(c1 << 0)
| (c2 << 1)
| (c3 << 2);
if (failures) {
for(int i=0; i<3; i++) {
if (failures & (1 << i)) {
cout << "condition " << (i+1) << " failed." << endl;
}
}
}
else {
cout << "no failures." << endl;
}
答案 1 :(得分:0)
如果您希望向最终用户显示这些内容,而不仅仅是在调试过程中,如评论中所建议的那样,您可以为自己设计一个简单的数据结构。它将是一个列表/向量/数组的条目,每个条目包含a)要比较的值,b)要测试的值,以及可选的c)测试的描述。
然后简单地迭代列表,并检查所有这些是否相等。如果没有,您可以停止程序流程并打印出描述。
更直接地回答你的问题:不,C ++中没有任何内容可以让你检查以前语句的结果。您在源代码中看到的语句和操作被编译,甚至可能在组装指令中无法识别。能够检查结果意味着数据必须存储在某个地方,这将是令人难以置信的浪费内存和处理时间。这就是你必须自己做的原因。
答案 2 :(得分:0)
这可能吗?
你想到这个问题的方式是不可能的。您可以通过单独运行每个测试,存储结果,然后确定哪些是false
来解决您的问题:
std::vector<std::tuple<std::string,bool> > tests = {
{"x==0",x==0}, // test name as a string followed by the actual test
{"y==1",y==1},
{"z==2",z==2}
};
if(!all_of(tests.begin(),tests.end(),[](std::tuple<std::string,bool> &t) { return std::get<1>(t); }))
{
std::cout << "The following tests failed: ";
//remove all tests that passed
tests.erase(
std::remove_if(tests.begin(),tests.end(),[](std::tuple<std::string,bool> &t) { return std::get<1>(t); }),
tests.end());
//This will only print out the tests that failed
std::transform(tests.begin(),tests.end(),std::ostream_iterator<std::string>(std::cout, " "),[](std::tuple<std::string,bool> &t) { return std::get<0>(t); });
std::cout << std::endl;
} else {
//what to do if all tests were true
}
这将评估所有测试(即,它不会使用&&
的短路)并打印所有失败的测试。您可以将其包装到class
中,以使其更具通用性和用户友好性。
答案 3 :(得分:0)
原始代码单独测试每个变量。 &&
系列完全等同于一系列if ... else语句。与另一个相比,没有什么是低效的,并且没有什么“聪明”使用一些棘手的解决方案来实现与简单代码相同的最终结果。
我可能会写:
char const *reason = nullptr;
if(x != 0)
reason = "x failed";
else if (y != 1)
reason = "y failed";
else if (z != 2 )
reason = "z failed";
if ( reason )
std::cout << reason << '\n';
else
{
// success code here...
}
答案 4 :(得分:0)
我通常会执行以下操作来确定一系列有效性检查是否有效并标记哪些失败。
unsigned long ulFlags = 0;
int x = 0;
int y = 1;
int z = 3;
ulFlags |= (x == 0) : 0 ? 0x0001; // if bit set then condition failed.
ulFlags |= (y == 1) : 0 ? 0x0002; // if bit set then condition failed.
ulFlags |= (z == 2) : 0 ? 0x0004; // if bit set then condition failed.
if(ulFlags == 0) {
// Do something since all conditions are met and valid ...
} else {
std::cout << "I did not execute if statement because: " << std::hex << ulFlags << std::endl;
/* Find a way to make the program output that z != 3 stopped the
conditional from running without directly using if(z != 2) */
}
答案 5 :(得分:0)
这与其他一些答案的想法相同,但使用模板来简化使用它的语法。将所有单独的支票存储在std::array<bool, N>
和另外一个bool中,以便能够重新检查完整的语句,而无需再次查看单个结果。
也没有动态分配。
#include <iostream>
#include <array>
#include <type_traits>
template <typename... N>
struct what_failed {
what_failed(N... n) : arr{n...}, status{(... && n)} {
static_assert(std::conjunction_v<std::is_same<N, bool>...>, "Only pass bools");
}
std::array<bool, sizeof...(N)> arr;
bool status;
operator bool() { return status; }
};
int main() {
auto check = what_failed(2 == 5, 2 < 5, 2 > 5, 1 == 1);
if (check)
std::cout << "Check: All true";
else {
std::cout << "Check: ";
for (auto c : check.arr)
std::cout << c << ' ';
}
return 0;
}
由于构造函数中的折叠表达式和模板推导,这需要c ++ 17,但是这可以通过一些额外的帮助模板来解决c ++ 11。