C - 检查一个变量是否是多个选项的*none*的最简洁的方法?
C - Most succinct way to check if a variable is *none* of many options?
背景:
通常,我们开发人员必须检查单个变量是否至少是多个选项中的一个。例如,
if ( (data == 125) || (data == 500) || (data == 750) )
{
/* ... do stuff ...*/
}
建议 here(尽管是用 C# 编写的)提供了一个优雅的解决方案,可以像这样使用 switch
语句,
switch ( data )
{
case 125:
case 500:
case 750:
/* ... do stuff ...*/
break;
default:
/* ... do nothing ... */
break;
}
这适用于 "or" 条件,但对于否定的 "or" 条件就很丑陋,如下所示,
if ( !( (data == 125) || (data == 500) || (data == 750) ) )
{
/* ... do stuff ...*/
}
可以写成
switch ( data )
{
case 125:
case 500:
case 750:
/* ... do nothing ... */
break;
default:
/* ... do stuff ...*/
break;
}
似乎有点老套。
问题:
是否有更简洁的方法来检查单个变量是否是多个选项的 none,例如上面否定的 "or" 条件?
参考文献:
- C++ Most efficient way to compare a variable to multiple values?
- C#Comparing a variable to multiple values
我觉得后者还好
不过你可以更好地形式化它:
static bool in_sprawling_set(int data)
{
switch ( data )
{
case 125:
case 500:
case 750:
return true;
}
return false;
}
然后是您想在哪里做的工作:
if(!in_sprawling_set(data))
{
/* do the work, not in set */
}
这将 "in set" 逻辑置于其自身的函数中,使其适度地自我记录,并且由于 !
变得更加突出并且最终的 if
非常可读 ("if not in sprawling set").
注意:如果值的数量真的很大,我可能会使用预排序数组和二进制搜索,而不是巨大的 switch
。我意识到一个足够聪明的编译器可以自己完成这个转换,但是一个巨大的 switch
的可读性会相当低(特别是如果你想每行只放一个 case
)。有 bsearch()
用于搜索:
static int cmp_int(const void *ap, const void *bp)
{
const int a = *(const int *) ap, b = *(const int *) bp;
return a < b ? -1 : a > b;
}
static bool in_sprawling_set(int data)
{
static const int values[] = { 125, 500, 750 };
return bsearch(&data, values, sizeof values / sizeof *values, sizeof *values, cmp_int) != 0;
}
有很多样板代码,但您可以看到列出实际值的部分(唯一会随着添加更多值而增加的部分)更加紧凑。
Is there a more succinct way to check if a single variable is none of many options?
switch()
语句当然是一个很好的解决方案。
作为替代方案,如果产品没有溢出,代码可以使用单分支测试:
unsigned data = foo();
if ( (data - 125) * (data - 500) * (data - 750) ) {
/* ... do stuff as long as data is not 125, 500 or 750 ...*/
}
如果它更清楚 - 不是真的,它比 switch()
快吗? 它有潜力。
您始终可以使用 De-morgans 定律来简化表达式,而不是否定条件
if (data != 125 && data != 500 && data != 750) ...
背景:
通常,我们开发人员必须检查单个变量是否至少是多个选项中的一个。例如,
if ( (data == 125) || (data == 500) || (data == 750) )
{
/* ... do stuff ...*/
}
建议 here(尽管是用 C# 编写的)提供了一个优雅的解决方案,可以像这样使用 switch
语句,
switch ( data )
{
case 125:
case 500:
case 750:
/* ... do stuff ...*/
break;
default:
/* ... do nothing ... */
break;
}
这适用于 "or" 条件,但对于否定的 "or" 条件就很丑陋,如下所示,
if ( !( (data == 125) || (data == 500) || (data == 750) ) )
{
/* ... do stuff ...*/
}
可以写成
switch ( data )
{
case 125:
case 500:
case 750:
/* ... do nothing ... */
break;
default:
/* ... do stuff ...*/
break;
}
似乎有点老套。
问题:
是否有更简洁的方法来检查单个变量是否是多个选项的 none,例如上面否定的 "or" 条件?
参考文献:
- C++ Most efficient way to compare a variable to multiple values?
- C#Comparing a variable to multiple values
我觉得后者还好
不过你可以更好地形式化它:
static bool in_sprawling_set(int data)
{
switch ( data )
{
case 125:
case 500:
case 750:
return true;
}
return false;
}
然后是您想在哪里做的工作:
if(!in_sprawling_set(data))
{
/* do the work, not in set */
}
这将 "in set" 逻辑置于其自身的函数中,使其适度地自我记录,并且由于 !
变得更加突出并且最终的 if
非常可读 ("if not in sprawling set").
注意:如果值的数量真的很大,我可能会使用预排序数组和二进制搜索,而不是巨大的 switch
。我意识到一个足够聪明的编译器可以自己完成这个转换,但是一个巨大的 switch
的可读性会相当低(特别是如果你想每行只放一个 case
)。有 bsearch()
用于搜索:
static int cmp_int(const void *ap, const void *bp)
{
const int a = *(const int *) ap, b = *(const int *) bp;
return a < b ? -1 : a > b;
}
static bool in_sprawling_set(int data)
{
static const int values[] = { 125, 500, 750 };
return bsearch(&data, values, sizeof values / sizeof *values, sizeof *values, cmp_int) != 0;
}
有很多样板代码,但您可以看到列出实际值的部分(唯一会随着添加更多值而增加的部分)更加紧凑。
Is there a more succinct way to check if a single variable is none of many options?
switch()
语句当然是一个很好的解决方案。
作为替代方案,如果产品没有溢出,代码可以使用单分支测试:
unsigned data = foo();
if ( (data - 125) * (data - 500) * (data - 750) ) {
/* ... do stuff as long as data is not 125, 500 or 750 ...*/
}
如果它更清楚 - 不是真的,它比 switch()
快吗? 它有潜力。
您始终可以使用 De-morgans 定律来简化表达式,而不是否定条件
if (data != 125 && data != 500 && data != 750) ...