'Testing the same condition without OR operator

My lecturer does not want us to use the OR operator when using an if statement neither should both condition testing be on the same line. eg.

if(condition1 || condition2){
  statement
}
if(condition1 || condition3){
  statement
}

But we've received a project asking for us to update books where the user can select either options, or both options. I tried using a switch, but I think its too long.

A sample of the code is below. However, is there any way to shorten it without using the case 3 and typing redundant code.

#include  <stdio.h>
#include <stdlib.h>
int main()
{
    int opt;

    printf("(1) Option 1");
    printf("\n(2) Option 2");
    printf("\n(3) Both\n");
    printf("Choice: ");
    scanf(" %d", &opt);
    switch(opt){
        case 1:
            printf("\nThis is option one");
            break;
        case 2:
            printf("\nThis is option two");
            break;
        case 3:
            printf("\nThis is option one");
            printf("\nThis is option two");
            break;
    }
    return 0;
}
c


Solution 1:[1]

You can use De Morgan's laws to avoid the OR. The relevant one

not (A or B) = not A and not B

which when transformed to your case becomes

A or B = not (not A and not B)

Here is the truth table to showcase this logic

A B A or B not A not B not A and not B not(not A and not B)
true true true false false false true
true false true false true false true
false true true true false false true
false false false true true true false

So with this in mind the condition

if(condition1 || condition2)

turns into

if (! (!condition1 && !condition2) )

Solution 2:[2]

In this case you can use the bitwise AND-operator (&) instead:

if(opt & 1)
{
  // option 1 or 3 chosen
}
if(opt & 2)
{
  // option 2 or 3 chosen
}

The decimal numbers 1, 2 and 3 are in binary 01, 10 and 11 respectively. (Denoted as 0b01, 0b10 and 0b11 below to distinguish from decimal numbers).

The bitwise AND-operator yields a 1 if and only if both bits are 1.
I.e. 1 & 1 = 1, 0 & 1 = 0, 1 & 0 = 0 and 0 & 0 = 0.

Truth-table:

&   0  1
   -----
0 | 0  0
1 | 0  1

When opt equals 1 then only the first if-statement is true.
0b01 & 0b01 = 0b01 (true) and 0b01 & 0b10 = 0b00 (false)

When opt equals 2 then only the second if-statement is true.
0b10 & 0b01 = 0b00 (false) and 0b10 & 0b10 = 0b10 (true)

When opt equals 3 then both if-statements are true.
0b11 & 0b01 = 0b01 (true) and 0b11 & 0b10 = 0b10 (true)

Anything not zero is true so all your conditions are met accordingly.

Solution 3:[3]

1 is 0b01, 2 is 0b10 and 3 is 0b11.

Therefore use the idiomatic

if (opt & 0b01){
    // 1 or 3 selected
}
if (opt & 0b10){
    // 2 or 3 selected
}

My binary literals 0b01 &c. are a compiler extension. If your compiler doesn't support them, then use an alternative such as the less clear 1, 2, and 3 or standard hexadecimal constants such as 0x01 &c. which can flag to readers of your code that bit locations are important.

Solution 4:[4]

You could us "else if" syntax as well.

#include <stdio.h>

int main()
{
    int opt;

    printf("(1) Option 1");
    printf("\n(2) Option 2");
    printf("\n(3) Both\n");
    printf("Choice: ");
    scanf(" %d", &opt);

    if (opt == 3){
        printf("\nBoth");
    }
    else if (opt == 2){
        printf("\n2");
    }
    else{
        printf("\n1");
    }
    return 0;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4