确定条件语句中的单个语句是正确的

时间:2014-07-01 10:07:20

标签: c

我有许多信号可以是真,假或无效,但只有其中一条可以为真,否则就是错误。

我想知道是否有办法轻松检查,而不是需要做一个大的if语句

enum sig_type
{
  sig_invalid, sig_true, sig_false
};

sig_type sig1 = GetSignal("sig1");
sig_type sig2 = GetSignal("sig1");
sig_type sig3 = GetSignal("sig1");
sig_type sig4 = GetSignal("sig1");

if (sig1 == sig_true)
{
  if (sig2 == sig_true || sig3 == sig_true || sig4 == sig_true)
  {
    // Error
  }
}
else if (sig2 == sig_true)
{
  if (sig1 == sig_true || sig3 == sig_true || sig4 == sig_true)
  {
    // Error
  }
}

等......这是一个重要的代码量,只是随着我添加信号而增加,因此在这种状态下将无法管理

5 个答案:

答案 0 :(得分:6)

您可以使用C中的逻辑表达式求值为0表示false或1表示true表示的事实,并将它们加在一起。如果总数大于1,则表示您有错误,否则您不会。

另外,如果您认为将来可能需要更多(或仅可变数量)信号,我会使用数组来保存它们而不是单独的变量。然后可以在for循环内完成测试:

sig_type sig[NSIGNALS];
int t = 0;

for (int i = 0; i < NSIGNALS; ++i) {
    char buf[50];   /* Make sure your buffer is large enough, of course */
    sprintf(buf, "sig%d", i + 1);    /* Or however you want to generate it */
    sig[i] = GetSignal(buf);
    t += sig[i] == sig_true;
}

if (t > 1) {
    /* Complain */
}

如果您的意思是1个信号必须为真,请将t > 1测试替换为t != 1

编辑:错误处理程序中最初有一个throw,但这不是C。

答案 1 :(得分:3)

没有必要以模糊,无效和不必要的复杂方式解决这个问题。

将所有信号存储在一个数组中,或者如果不可能,则存储一个指针数组,如下所示:

const sig_type* sigs [number_of_sig] = 
{
  &sig1,
  &sig2,
  ...
};

然后遍历这个数组。

bool one_sig_true = false;

for(int i=0; i<number_of_sig; i++)
{
  if(*sigs[i] == sig_true)
  {
    if(one_sig_true)    // if one was already true from before
    {
      error();
      break;
    }

    one_sig_true = true; // otherwise, set this flag
  }
}

// if the loop finished without error, everything is fine

答案 2 :(得分:2)

有一个简单的技巧可断言给定的value将多个位设置为1:

value & (value-1)

以下是如何使用此技巧以使用单个if语句实现目标:

enum sig_type
{
    sig_inv   = 0,
    sig_true  = 1,
    sig_false = 2,
};

int b0 = (int)GetSignal("sig1") & 1;
int b1 = (int)GetSignal("sig1") & 1;
int b2 = (int)GetSignal("sig1") & 1;
int b3 = (int)GetSignal("sig1") & 1;

int value = (b0<<0) | (b1<<1) | (b2<<2) | (b3<<3);
if (value & (value-1))
{
    // Error
}

答案 3 :(得分:1)

让你的代码记住&#34;状态&#34;在变量中。

enum sig_type
{
    sig_invalid, sig_true, sig_false
};

sig_type sig1 = GetSignal("sig1");
sig_type sig2 = GetSignal("sig1");
sig_type sig3 = GetSignal("sig1");
sig_type sig4 = GetSignal("sig1");

int count = 0;

if (sig1 == sig_true) {
    count++;
}
if (sig2 == sig_true) {
    count++;
}
if (sig3 == sig_true) {
    count++;
}
if( sig4 == sig_true) {
    count++;
}

if (count > 1) {
    /* your error code here */
}

答案 4 :(得分:1)

我会提出一个算术解决方案。我有好处,你也可以为有效的案件找到一个好地方。此外,您不需要任何可以刷新指令管道的循环。

enum sig_type
{
  sig_invalid, sig_true, sig_false
};

sig_type sig1 = GetSignal("sig1");
sig_type sig2 = GetSignal("sig1");
sig_type sig3 = GetSignal("sig1");
sig_type sig4 = GetSignal("sig1");

// This can be rewritten as needed and the personal preferences. 
// The arithmetic that is described in this answer remains.
int cumulative_result = 
    ((sig1 == sig_true) << 0) |
    ((sig2 == sig_true) << 1) |
    ((sig3 == sig_true) << 2) |
    ((sig4 == sig_true) << 3));

switch (cumulative_result)
{
case 0:
case 1:
case 2:
case 4:
case 8:
    break;
default:
    /* your error code here */
    break;
}

对于“更邪恶”的案件,你可以更具体。