缩短条件来检查x是不是四个数字中的任何一个
有没有办法缩短这个if
语句的条件?
int x; if (x != 3 && x != 8 && x != 87 && x != 9){ SomeStuff(); }
我在想这样的事情:
if (x != 3, 8, 87, 9) {}
但是我试过了,不行。 我只需要长时间写下这些东西吗?
如果你想知道一个整数是否在给定的整数集合中,那么使用std::set
:
std::set<int> accept { 1, 4, 6, 8, 255, 42 }; int x = 1; if (!accept.count(x)) { // ... }
为了完整起见,我会提供一个开关:
switch (x) { case 1: case 2: case 37: case 42: break; default: SomeStuff(); break; }
虽然这是相当详细的,它只评估一次x
(如果它是一个expression式),并可能生成任何解决scheme的最有效的代码。
这是我使用可变参数模板的解决scheme。 运行时性能与手动编写x != 3 && x != 8 && x != 87 && x != 9
一样高效。
template <class T, class U> bool not_equal(const T& t, const U& u) { return t != u; } template <class T, class U, class... Vs> bool not_equal(const T& t, const U& u, const Vs... vs) { return t != u && not_equal(t, vs...); } int main() { std::cout << not_equal( 3, 3, 8, 87, 9) << std::endl; std::cout << not_equal( 8, 3, 8, 87, 9) << std::endl; std::cout << not_equal(87, 3, 8, 87, 9) << std::endl; std::cout << not_equal( 9, 3, 8, 87, 9) << std::endl; std::cout << not_equal(10, 3, 8, 87, 9) << std::endl; }
那这个呢:
#include <iostream> #include <initializer_list> #include <algorithm> template <typename T> bool in(const T t, const std::initializer_list<T> & l) { return std::find(l.begin(), l.end(), t) != l.end(); } int main() { std::cout << !in(3, {3, 8, 87, 9}) << std::endl; std::cout << !in(87, {3, 8, 87, 9}) << std::endl; std::cout << !in(10, {3, 8, 87, 9}) << std::endl; }
或者重载operator!=
:
template<typename T> bool operator!=(const T t, const std::vector<T> & l) { return std::find(l.begin(), l.end(), t) == l.end(); } int main() { std::cout << ( 3!=std::vector<int>{ 3, 8, 87, 9}) << std::endl; std::cout << ( 8!=std::vector<int>{ 3, 8, 87, 9}) << std::endl; std::cout << (10!=std::vector<int>{ 3, 8, 87, 9}) << std::endl; }
不幸的是,目前parsing器不喜欢将initializer_list
作为运算符的参数 ,所以在第二个解决scheme中不可能去掉std::vector<int>
。
如果你不想一再重复这个条件,那就用macros。
#include <iostream> #define isTRUE(x, a, b, c, d) ( x != a && x != b && x != c && x != d ) int main() { int x(2); std::cout << isTRUE(x,3,8,87,9) << std::endl; if ( isTRUE(x,3,8,87,9) ){ // SomeStuff(); } return 0; }
如果数字不是“1,2,3,4”,而是随机数的随机整数,那么你可以把这些数字放在一个数据结构(如std::vector
)中,然后迭代该数组使用循环(如下所示,std :: find是一个现成的选项)。
例如:
#include <algorithm> int x; std::vector<int> checknums; // fill the vector with your numbers to check x against if (std::find(checknums.begin(), checknums.end(), x) != checknums.end()){ DoStuff(); }
int A[]={3, 8, 87, 9}; int x; if (std::find(A, A+4, x)==A+4) SomeStuff();
请注意,许多C ++程序员对macros的使用非常不满,因为macros非常强大,并且如果创build不当,可能会感到沮丧。 但是,如果适当和智能地创build和使用,他们可以成为主要的节省时间。 我没有看到另一种方式来获得所需的语法和代码空间,每个比较类似于您请求的内容,而不影响程序使用的效率,代码空间或内存。 你的目标是要有一个捷径,这里提出的其他解决scheme大多比你最初想要缩短的时间要长。 假设你正在比较一个整数,这里有macros将安全地执行:
#pragma once int unused; #define IFNOTIN2(x, a, b) \ if (unused = (x) && unused != (a) && unused != (b)) #define IFNOTIN3(x, a, b, c) \ if (unused = (x) && unused != (a) && unused != (b) && unused != (c)) #define IFNOTIN4(x, a, b, c, d) \ if (unused = (x) && unused != (a) && unused != (b) && unused != (c) && unused != (d)) #define IFNOTIN5(x, a, b, c, d, e) \ if (unused = (x) && unused != (a) && unused != (b) && unused != (c) && unused != (d) && unused != (e))
这里是一个工作testing的例子与上面的macros之一:
#include <iostream> #include "macros.h" int main () { std::cout << "Hello World\n"; for (int i = 0; i < 100; i ++) { std::cout << i << ": "; IFNOTIN4 (i, 7, 17, 32, 87) { std::cout << "PASSED\n"; } else { std::cout << "FAILED\n"; } } std::cin.get(); return 0; }
请注意,这些macros应该放在任何需要使用它们的头文件中。 如果您已经在您的代码中使用名为“unused”的variables,或者尝试使用这些macros来比较除整数以外的内容,则代码将无法编译。 我相信你可以扩展macros来处理其他types的数据,如果这是必要的。
通过在所有input周围使用括号来保存操作顺序,并且在比较之前将值保存到variables中,以防止多次执行CPU密集型代码。