Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining a single statement in a conditional statement is true

Tags:

c

I have a number of signals that can be true, false or invalid, but only one of these can be true otherwise it is an error.

I want to know if there is a way to check for this easily rather than needing to do a large if statement

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
  }
}

etc... Which is a significant amount of code and only increases as I add signals so in this state is going to be unmanageable

like image 460
Firedragon Avatar asked Dec 12 '22 05:12

Firedragon


2 Answers

You can use the fact that logical expressions in C evaluate to 0 for false or 1 for true, and sum these together. If the total is greater than 1, you have an error, otherwise you don't.

Separately, if you think you might need more (or just a variable number of) signals in future, I'd use an array to hold them instead of separate variables. Then the test can be done inside a for loop:

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 */
}

If you meant that exactly 1 signal must be true, replace the t > 1 test with t != 1.

EDIT: Originally had a throw in the error handler, though that's not C.

like image 94
j_random_hacker Avatar answered May 19 '23 05:05

j_random_hacker


There is no need to solve this in obscure, ineffective and needlessly complicated ways.

Either store all signals in an array, or if that isn't possible, store an array of pointers to them as below:

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

Then iterate through this array.

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
like image 22
Lundin Avatar answered May 19 '23 06:05

Lundin